1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-20 05:19:40 +02:00

Provide golang based Piper library (#915)

* Provide golang based Piper  library

This includes the main command
and a sub command for config resolution
This commit is contained in:
Oliver Nocon 2019-10-24 10:59:58 +02:00 committed by GitHub
parent f92bd31114
commit 1f34511407
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 519 additions and 41 deletions

2
.gitignore vendored
View File

@ -19,3 +19,5 @@ documentation/docs-gen
consumer-test/**/workspace
*.code-workspace
piper
piper.exe

115
cmd/getConfig.go Normal file
View File

@ -0,0 +1,115 @@
package cmd
import (
"fmt"
"io"
"os"
"github.com/SAP/jenkins-library/pkg/config"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
type configCommandOptions struct {
output string //output format, so far only JSON
parametersJSON string //parameters to be considered in JSON format
stepMetadata string //metadata to be considered, can be filePath or ENV containing JSON in format 'ENV:MY_ENV_VAR'
stepName string
contextConfig bool
openFile func(s string) (io.ReadCloser, error)
}
var configOptions configCommandOptions
// ConfigCommand is the entry command for loading the configuration of a pipeline step
func ConfigCommand() *cobra.Command {
configOptions.openFile = openPiperFile
var createConfigCmd = &cobra.Command{
Use: "getConfig",
Short: "Loads the project 'Piper' configuration respecting defaults and parameters.",
RunE: func(cmd *cobra.Command, _ []string) error {
return generateConfig()
},
}
addConfigFlags(createConfigCmd)
return createConfigCmd
}
func generateConfig() error {
var myConfig config.Config
var stepConfig config.StepConfig
var metadata config.StepData
metadataFile, err := configOptions.openFile(configOptions.stepMetadata)
if err != nil {
return errors.Wrap(err, "metadata: open failed")
}
err = metadata.ReadPipelineStepData(metadataFile)
if err != nil {
return errors.Wrap(err, "metadata: read failed")
}
customConfig, err := configOptions.openFile(generalConfig.customConfig)
if err != nil {
return errors.Wrap(err, "config: open failed")
}
defaultConfig, paramFilter, err := defaultsAndFilters(&metadata)
if err != nil {
return errors.Wrap(err, "defaults: retrieving step defaults failed")
}
for _, f := range generalConfig.defaultConfig {
fc, err := configOptions.openFile(f)
if err != nil {
return errors.Wrapf(err, "config: getting defaults failed: '%v'", f)
}
defaultConfig = append(defaultConfig, fc)
}
var flags map[string]interface{}
stepConfig, err = myConfig.GetStepConfig(flags, generalConfig.parametersJSON, customConfig, defaultConfig, paramFilter, generalConfig.stageName, configOptions.stepName)
if err != nil {
return errors.Wrap(err, "getting step config failed")
}
//ToDo: Check for mandatory parameters
myConfigJSON, _ := config.GetJSON(stepConfig.Config)
fmt.Println(myConfigJSON)
return nil
}
func addConfigFlags(cmd *cobra.Command) {
//ToDo: support more output options, like https://kubernetes.io/docs/reference/kubectl/overview/#formatting-output
cmd.Flags().StringVar(&configOptions.output, "output", "json", "Defines the output format")
cmd.Flags().StringVar(&configOptions.parametersJSON, "parametersJSON", os.Getenv("PIPER_parametersJSON"), "Parameters to be considered in JSON format")
cmd.Flags().StringVar(&configOptions.stepMetadata, "stepMetadata", "", "Step metadata, passed as path to yaml")
cmd.Flags().StringVar(&configOptions.stepName, "stepName", "", "Name of the step for which configuration should be included")
cmd.Flags().BoolVar(&configOptions.contextConfig, "contextConfig", false, "Defines if step context configuration should be loaded instead of step config")
cmd.MarkFlagRequired("stepMetadata")
cmd.MarkFlagRequired("stepName")
}
func defaultsAndFilters(metadata *config.StepData) ([]io.ReadCloser, config.StepFilters, error) {
if configOptions.contextConfig {
defaults, err := metadata.GetContextDefaults(configOptions.stepName)
if err != nil {
return nil, config.StepFilters{}, errors.Wrap(err, "metadata: getting context defaults failed")
}
return []io.ReadCloser{defaults}, metadata.GetContextParameterFilters(), nil
}
//ToDo: retrieve default values from metadata
return nil, metadata.GetParameterFilters(), nil
}

90
cmd/getConfig_test.go Normal file
View File

@ -0,0 +1,90 @@
package cmd
import (
"io"
"io/ioutil"
"strings"
"testing"
"github.com/SAP/jenkins-library/pkg/config"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
)
func openFileMock(name string) (io.ReadCloser, error) {
var r string
switch name {
case "TestAddCustomDefaults_default1":
r = "default1"
case "TestAddCustomDefaults_default2":
r = "default3"
default:
r = ""
}
return ioutil.NopCloser(strings.NewReader(r)), nil
}
func TestConfigCommand(t *testing.T) {
cmd := ConfigCommand()
gotReq := []string{}
gotOpt := []string{}
cmd.Flags().VisitAll(func(pflag *flag.Flag) {
annotations, found := pflag.Annotations[cobra.BashCompOneRequiredFlag]
if found && annotations[0] == "true" {
gotReq = append(gotReq, pflag.Name)
} else {
gotOpt = append(gotOpt, pflag.Name)
}
})
t.Run("Required flags", func(t *testing.T) {
exp := []string{"stepMetadata", "stepName"}
assert.Equal(t, exp, gotReq, "required flags incorrect")
})
t.Run("Optional flags", func(t *testing.T) {
exp := []string{"contextConfig", "output", "parametersJSON"}
assert.Equal(t, exp, gotOpt, "optional flags incorrect")
})
t.Run("Run", func(t *testing.T) {
t.Run("Success case", func(t *testing.T) {
configOptions.openFile = openFileMock
err := cmd.RunE(cmd, []string{})
assert.NoError(t, err, "error occured but none expected")
})
})
}
func TestDefaultsAndFilters(t *testing.T) {
metadata := config.StepData{
Spec: config.StepSpec{
Inputs: config.StepInputs{
Parameters: []config.StepParameters{
{Name: "paramOne", Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS", "ENV"}},
},
},
},
}
t.Run("Context config", func(t *testing.T) {
configOptions.contextConfig = true
defer func() { configOptions.contextConfig = false }()
defaults, filters, err := defaultsAndFilters(&metadata)
assert.Equal(t, 1, len(defaults), "getting defaults failed")
assert.Equal(t, 0, len(filters.All), "wrong number of filter values")
assert.NoError(t, err, "error occured but none expected")
})
t.Run("Step config", func(t *testing.T) {
defaults, filters, err := defaultsAndFilters(&metadata)
assert.Equal(t, 0, len(defaults), "getting defaults failed")
assert.Equal(t, 1, len(filters.All), "wrong number of filter values")
assert.NoError(t, err, "error occured but none expected")
})
}

58
cmd/piper.go Normal file
View File

@ -0,0 +1,58 @@
package cmd
import (
"fmt"
"io"
"os"
"strings"
"github.com/spf13/cobra"
)
type generalConfigOptions struct {
customConfig string
defaultConfig []string //ordered list of Piper default configurations. Can be filePath or ENV containing JSON in format 'ENV:MY_ENV_VAR'
parametersJSON string
stageName string
stepConfigJSON string
stepMetadata string //metadata to be considered, can be filePath or ENV containing JSON in format 'ENV:MY_ENV_VAR'
stepName string
verbose bool
}
var rootCmd = &cobra.Command{
Use: "piper",
Short: "Executes CI/CD steps from project 'Piper' ",
Long: `
This project 'Piper' binary provides a CI/CD step libary.
It contains many steps which can be used within CI/CD systems as well as directly on e.g. a developer's machine.
`,
//ToDo: respect stageName to also come from parametersJSON -> first env.STAGE_NAME, second: parametersJSON, third: flag
}
var generalConfig generalConfigOptions
// Execute is the starting point of the piper command line tool
func Execute() {
rootCmd.AddCommand(ConfigCommand())
rootCmd.PersistentFlags().StringVar(&generalConfig.customConfig, "customConfig", ".pipeline/config.yml", "Path to the pipeline configuration file")
rootCmd.PersistentFlags().StringSliceVar(&generalConfig.defaultConfig, "defaultConfig", nil, "Default configurations, passed as path to yaml file")
rootCmd.PersistentFlags().StringVar(&generalConfig.parametersJSON, "parametersJSON", os.Getenv("PIPER_parametersJSON"), "Parameters to be considered in JSON format")
rootCmd.PersistentFlags().StringVar(&generalConfig.stageName, "stageName", os.Getenv("STAGE_NAME"), "Name of the stage for which configuration should be included")
rootCmd.PersistentFlags().StringVar(&generalConfig.stepConfigJSON, "stepConfigJSON", os.Getenv("PIPER_stepConfigJSON"), "Step configuration in JSON format")
rootCmd.PersistentFlags().BoolVarP(&generalConfig.verbose, "verbose", "v", false, "verbose output")
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func openPiperFile(name string) (io.ReadCloser, error) {
//ToDo: support also https as source
if !strings.HasPrefix(name, "http") {
return os.Open(name)
}
return nil, fmt.Errorf("file location not yet supported for '%v'", name)
}

9
main.go Normal file
View File

@ -0,0 +1,9 @@
package main
import (
"github.com/SAP/jenkins-library/cmd"
)
func main() {
cmd.Execute()
}

View File

@ -1,6 +1,8 @@
package config
import (
"bytes"
"fmt"
"io"
"io/ioutil"
@ -25,8 +27,8 @@ type StepMetadata struct {
type StepSpec struct {
Inputs StepInputs `json:"inputs"`
// Outputs string `json:"description,omitempty"`
Containers []StepContainers `json:"containers,omitempty"`
Sidecars []StepSidecars `json:"sidecars,omitempty"`
Containers []Container `json:"containers,omitempty"`
Sidecars []Container `json:"sidecars,omitempty"`
}
// StepInputs defines the spec details for a step, like step inputs, containers, sidecars, ...
@ -66,14 +68,23 @@ type StepSecrets struct {
// Name string `json:"name"`
//}
// StepContainers defines the containers required for a step
type StepContainers struct {
Containers map[string]interface{} `json:"containers"`
// Container defines an execution container
type Container struct {
//ToDo: check dockerOptions, dockerVolumeBind, containerPortMappings, sidecarOptions, sidecarVolumeBind
Command []string `json:"command"`
EnvVars []EnvVar `json:"env"`
Image string `json:"image"`
ImagePullPolicy string `json:"imagePullPolicy"`
Name string `json:"name"`
ReadyCommand string `json:"readyCommand"`
Shell string `json:"shell"`
WorkingDir string `json:"workingDir"`
}
// StepSidecars defines any sidears required for a step
type StepSidecars struct {
Sidecars map[string]interface{} `json:"sidecars"`
// EnvVar defines an environment variable
type EnvVar struct {
Name string `json:"name"`
Value string `json:"value"`
}
// StepFilters defines the filter parameters for the different sections
@ -135,5 +146,87 @@ func (m *StepData) GetContextParameterFilters() StepFilters {
filters.Parameters = append(filters.Parameters, secret.Name)
filters.Env = append(filters.Env, secret.Name)
}
containerFilters := []string{}
if len(m.Spec.Containers) > 0 {
containerFilters = append(containerFilters, []string{"containerCommand", "containerShell", "dockerEnvVars", "dockerImage", "dockerOptions", "dockerPullImage", "dockerVolumeBind", "dockerWorkspace"}...)
}
if len(m.Spec.Sidecars) > 0 {
//ToDo: support fallback for "dockerName" configuration property -> via aliasing?
containerFilters = append(containerFilters, []string{"containerName", "containerPortMappings", "dockerName", "sidecarEnvVars", "sidecarImage", "sidecarName", "sidecarOptions", "sidecarPullImage", "sidecarReadyCommand", "sidecarVolumeBind", "sidecarWorkspace"}...)
}
if len(containerFilters) > 0 {
filters.All = append(filters.All, containerFilters...)
filters.Steps = append(filters.Steps, containerFilters...)
filters.Stages = append(filters.Stages, containerFilters...)
filters.Parameters = append(filters.Parameters, containerFilters...)
}
return filters
}
// GetContextDefaults retrieves context defaults like container image, name, env vars, ...
// It only supports scenarios with one container and optionally one sidecar
func (m *StepData) GetContextDefaults(stepName string) (io.ReadCloser, error) {
p := map[string]interface{}{}
//ToDo error handling empty Containers/Sidecars
//ToDo handle empty Command
if len(m.Spec.Containers) > 0 {
if len(m.Spec.Containers[0].Command) > 0 {
p["containerCommand"] = m.Spec.Containers[0].Command[0]
}
p["containerName"] = m.Spec.Containers[0].Name
p["containerShell"] = m.Spec.Containers[0].Shell
p["dockerEnvVars"] = envVarsAsStringSlice(m.Spec.Containers[0].EnvVars)
p["dockerImage"] = m.Spec.Containers[0].Image
p["dockerName"] = m.Spec.Containers[0].Name
p["dockerPullImage"] = m.Spec.Containers[0].ImagePullPolicy != "Never"
p["dockerWorkspace"] = m.Spec.Containers[0].WorkingDir
// Ready command not relevant for main runtime container so far
//p[] = m.Spec.Containers[0].ReadyCommand
}
if len(m.Spec.Sidecars) > 0 {
if len(m.Spec.Sidecars[0].Command) > 0 {
p["sidecarCommand"] = m.Spec.Sidecars[0].Command[0]
}
p["sidecarEnvVars"] = envVarsAsStringSlice(m.Spec.Sidecars[0].EnvVars)
p["sidecarImage"] = m.Spec.Sidecars[0].Image
p["sidecarName"] = m.Spec.Sidecars[0].Name
p["sidecarPullImage"] = m.Spec.Sidecars[0].ImagePullPolicy != "Never"
p["sidecarReadyCommand"] = m.Spec.Sidecars[0].ReadyCommand
p["sidecarWorkspace"] = m.Spec.Sidecars[0].WorkingDir
}
// not filled for now since this is not relevant in Kubernetes case
//p["dockerOptions"] = m.Spec.Containers[0].
//p["dockerVolumeBind"] = m.Spec.Containers[0].
//p["containerPortMappings"] = m.Spec.Sidecars[0].
//p["sidecarOptions"] = m.Spec.Sidecars[0].
//p["sidecarVolumeBind"] = m.Spec.Sidecars[0].
c := Config{
Steps: map[string]map[string]interface{}{
stepName: p,
},
}
JSON, err := yaml.Marshal(c)
if err != nil {
return nil, errors.Wrap(err, "failed to create context defaults")
}
r := ioutil.NopCloser(bytes.NewReader(JSON))
return r, nil
}
func envVarsAsStringSlice(envVars []EnvVar) []string {
e := []string{}
for _, v := range envVars {
e = append(e, fmt.Sprintf("%v=%v", v.Name, v.Value))
}
return e
}

View File

@ -2,9 +2,12 @@ package config
import (
"fmt"
"io"
"io/ioutil"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestReadPipelineStepData(t *testing.T) {
@ -227,40 +230,148 @@ func TestGetContextParameterFilters(t *testing.T) {
},
}
filters := metadata1.GetContextParameterFilters()
metadata2 := StepData{
Spec: StepSpec{
Containers: []Container{
{Name: "testcontainer"},
},
},
}
metadata3 := StepData{
Spec: StepSpec{
Sidecars: []Container{
{Name: "testsidecar"},
},
},
}
t.Run("Secrets", func(t *testing.T) {
for _, s := range metadata1.Spec.Inputs.Secrets {
t.Run("All", func(t *testing.T) {
if !sliceContains(filters.All, s.Name) {
t.Errorf("Creation of context filter failed, expected: %v to be contained", s.Name)
}
})
t.Run("General", func(t *testing.T) {
if !sliceContains(filters.General, s.Name) {
t.Errorf("Creation of context filter failed, expected: %v to be contained", s.Name)
}
})
t.Run("Step", func(t *testing.T) {
if !sliceContains(filters.Steps, s.Name) {
t.Errorf("Creation of context filter failed, expected: %v to be contained", s.Name)
}
})
t.Run("Stages", func(t *testing.T) {
if !sliceContains(filters.Steps, s.Name) {
t.Errorf("Creation of context filter failed, expected: %v to be contained", s.Name)
}
})
t.Run("Parameters", func(t *testing.T) {
if !sliceContains(filters.Parameters, s.Name) {
t.Errorf("Creation of context filter failed, expected: %v to be contained", s.Name)
}
})
t.Run("Env", func(t *testing.T) {
if !sliceContains(filters.Env, s.Name) {
t.Errorf("Creation of context filter failed, expected: %v to be contained", s.Name)
}
})
}
filters := metadata1.GetContextParameterFilters()
assert.Equal(t, []string{"testSecret1", "testSecret2"}, filters.All, "incorrect filter All")
assert.Equal(t, []string{"testSecret1", "testSecret2"}, filters.General, "incorrect filter General")
assert.Equal(t, []string{"testSecret1", "testSecret2"}, filters.Steps, "incorrect filter Steps")
assert.Equal(t, []string{"testSecret1", "testSecret2"}, filters.Stages, "incorrect filter Stages")
assert.Equal(t, []string{"testSecret1", "testSecret2"}, filters.Parameters, "incorrect filter Parameters")
assert.Equal(t, []string{"testSecret1", "testSecret2"}, filters.Env, "incorrect filter Env")
})
t.Run("Containers", func(t *testing.T) {
filters := metadata2.GetContextParameterFilters()
assert.Equal(t, []string{"containerCommand", "containerShell", "dockerEnvVars", "dockerImage", "dockerOptions", "dockerPullImage", "dockerVolumeBind", "dockerWorkspace"}, filters.All, "incorrect filter All")
assert.NotEqual(t, []string{"containerCommand", "containerShell", "dockerEnvVars", "dockerImage", "dockerOptions", "dockerPullImage", "dockerVolumeBind", "dockerWorkspace"}, filters.General, "incorrect filter General")
assert.Equal(t, []string{"containerCommand", "containerShell", "dockerEnvVars", "dockerImage", "dockerOptions", "dockerPullImage", "dockerVolumeBind", "dockerWorkspace"}, filters.Steps, "incorrect filter Steps")
assert.Equal(t, []string{"containerCommand", "containerShell", "dockerEnvVars", "dockerImage", "dockerOptions", "dockerPullImage", "dockerVolumeBind", "dockerWorkspace"}, filters.Stages, "incorrect filter Stages")
assert.Equal(t, []string{"containerCommand", "containerShell", "dockerEnvVars", "dockerImage", "dockerOptions", "dockerPullImage", "dockerVolumeBind", "dockerWorkspace"}, filters.Parameters, "incorrect filter Parameters")
assert.NotEqual(t, []string{"containerCommand", "containerShell", "dockerEnvVars", "dockerImage", "dockerOptions", "dockerPullImage", "dockerVolumeBind", "dockerWorkspace"}, filters.Env, "incorrect filter Env")
})
t.Run("Sidecars", func(t *testing.T) {
filters := metadata3.GetContextParameterFilters()
assert.Equal(t, []string{"containerName", "containerPortMappings", "dockerName", "sidecarEnvVars", "sidecarImage", "sidecarName", "sidecarOptions", "sidecarPullImage", "sidecarReadyCommand", "sidecarVolumeBind", "sidecarWorkspace"}, filters.All, "incorrect filter All")
assert.NotEqual(t, []string{"containerName", "containerPortMappings", "dockerName", "sidecarEnvVars", "sidecarImage", "sidecarName", "sidecarOptions", "sidecarPullImage", "sidecarReadyCommand", "sidecarVolumeBind", "sidecarWorkspace"}, filters.General, "incorrect filter General")
assert.Equal(t, []string{"containerName", "containerPortMappings", "dockerName", "sidecarEnvVars", "sidecarImage", "sidecarName", "sidecarOptions", "sidecarPullImage", "sidecarReadyCommand", "sidecarVolumeBind", "sidecarWorkspace"}, filters.Steps, "incorrect filter Steps")
assert.Equal(t, []string{"containerName", "containerPortMappings", "dockerName", "sidecarEnvVars", "sidecarImage", "sidecarName", "sidecarOptions", "sidecarPullImage", "sidecarReadyCommand", "sidecarVolumeBind", "sidecarWorkspace"}, filters.Stages, "incorrect filter Stages")
assert.Equal(t, []string{"containerName", "containerPortMappings", "dockerName", "sidecarEnvVars", "sidecarImage", "sidecarName", "sidecarOptions", "sidecarPullImage", "sidecarReadyCommand", "sidecarVolumeBind", "sidecarWorkspace"}, filters.Parameters, "incorrect filter Parameters")
assert.NotEqual(t, []string{"containerName", "containerPortMappings", "dockerName", "sidecarEnvVars", "sidecarImage", "sidecarName", "sidecarOptions", "sidecarPullImage", "sidecarReadyCommand", "sidecarVolumeBind", "sidecarWorkspace"}, filters.Env, "incorrect filter Env")
})
}
func TestGetContextDefaults(t *testing.T) {
t.Run("Positive case", func(t *testing.T) {
metadata := StepData{
Spec: StepSpec{
Containers: []Container{
{
Command: []string{"test/command"},
EnvVars: []EnvVar{
{Name: "env1", Value: "val1"},
{Name: "env2", Value: "val2"},
},
Name: "testcontainer",
Image: "testImage:tag",
Shell: "/bin/bash",
WorkingDir: "/test/dir",
},
},
Sidecars: []Container{
{
Command: []string{"/sidecar/command"},
EnvVars: []EnvVar{
{Name: "env3", Value: "val3"},
{Name: "env4", Value: "val4"},
},
Name: "testsidecar",
Image: "testSidecarImage:tag",
ImagePullPolicy: "Never",
ReadyCommand: "/sidecar/command",
WorkingDir: "/sidecar/dir",
},
},
},
}
cd, err := metadata.GetContextDefaults("testStep")
t.Run("No error", func(t *testing.T) {
if err != nil {
t.Errorf("No error expected but got error '%v'", err)
}
})
var d PipelineDefaults
d.ReadPipelineDefaults([]io.ReadCloser{cd})
assert.Equal(t, "test/command", d.Defaults[0].Steps["testStep"]["containerCommand"], "containerCommand default not available")
assert.Equal(t, "testcontainer", d.Defaults[0].Steps["testStep"]["containerName"], "containerName default not available")
assert.Equal(t, "/bin/bash", d.Defaults[0].Steps["testStep"]["containerShell"], "containerShell default not available")
assert.Equal(t, []interface{}{"env1=val1", "env2=val2"}, d.Defaults[0].Steps["testStep"]["dockerEnvVars"], "dockerEnvVars default not available")
assert.Equal(t, "testImage:tag", d.Defaults[0].Steps["testStep"]["dockerImage"], "dockerImage default not available")
assert.Equal(t, "testcontainer", d.Defaults[0].Steps["testStep"]["dockerName"], "dockerName default not available")
assert.Equal(t, true, d.Defaults[0].Steps["testStep"]["dockerPullImage"], "dockerPullImage default not available")
assert.Equal(t, "/test/dir", d.Defaults[0].Steps["testStep"]["dockerWorkspace"], "dockerWorkspace default not available")
assert.Equal(t, "/sidecar/command", d.Defaults[0].Steps["testStep"]["sidecarCommand"], "sidecarCommand default not available")
assert.Equal(t, []interface{}{"env3=val3", "env4=val4"}, d.Defaults[0].Steps["testStep"]["sidecarEnvVars"], "sidecarEnvVars default not available")
assert.Equal(t, "testSidecarImage:tag", d.Defaults[0].Steps["testStep"]["sidecarImage"], "sidecarImage default not available")
assert.Equal(t, "testsidecar", d.Defaults[0].Steps["testStep"]["sidecarName"], "sidecarName default not available")
assert.Equal(t, false, d.Defaults[0].Steps["testStep"]["sidecarPullImage"], "sidecarPullImage default not available")
assert.Equal(t, "/sidecar/command", d.Defaults[0].Steps["testStep"]["sidecarReadyCommand"], "sidecarReadyCommand default not available")
assert.Equal(t, "/sidecar/dir", d.Defaults[0].Steps["testStep"]["sidecarWorkspace"], "sidecarWorkspace default not available")
})
t.Run("Negative case", func(t *testing.T) {
metadataErr := []StepData{
StepData{},
StepData{
Spec: StepSpec{},
},
StepData{
Spec: StepSpec{
Containers: []Container{},
Sidecars: []Container{},
},
},
}
t.Run("No containers/sidecars", func(t *testing.T) {
cd, _ := metadataErr[0].GetContextDefaults("testStep")
var d PipelineDefaults
d.ReadPipelineDefaults([]io.ReadCloser{cd})
//no assert since we just want to make sure that no panic occurs
})
t.Run("No command", func(t *testing.T) {
cd, _ := metadataErr[1].GetContextDefaults("testStep")
var d PipelineDefaults
d.ReadPipelineDefaults([]io.ReadCloser{cd})
//no assert since we just want to make sure that no panic occurs
})
})
}