You've already forked sap-jenkins-library
mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-09-16 09:26:22 +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:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -19,3 +19,5 @@ documentation/docs-gen
|
|||||||
consumer-test/**/workspace
|
consumer-test/**/workspace
|
||||||
|
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
|
piper
|
||||||
|
piper.exe
|
||||||
|
115
cmd/getConfig.go
Normal file
115
cmd/getConfig.go
Normal 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
90
cmd/getConfig_test.go
Normal 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
58
cmd/piper.go
Normal 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
9
main.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/SAP/jenkins-library/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cmd.Execute()
|
||||||
|
}
|
@@ -1,6 +1,8 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
@@ -25,8 +27,8 @@ type StepMetadata struct {
|
|||||||
type StepSpec struct {
|
type StepSpec struct {
|
||||||
Inputs StepInputs `json:"inputs"`
|
Inputs StepInputs `json:"inputs"`
|
||||||
// Outputs string `json:"description,omitempty"`
|
// Outputs string `json:"description,omitempty"`
|
||||||
Containers []StepContainers `json:"containers,omitempty"`
|
Containers []Container `json:"containers,omitempty"`
|
||||||
Sidecars []StepSidecars `json:"sidecars,omitempty"`
|
Sidecars []Container `json:"sidecars,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// StepInputs defines the spec details for a step, like step inputs, containers, sidecars, ...
|
// StepInputs defines the spec details for a step, like step inputs, containers, sidecars, ...
|
||||||
@@ -66,14 +68,23 @@ type StepSecrets struct {
|
|||||||
// Name string `json:"name"`
|
// Name string `json:"name"`
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// StepContainers defines the containers required for a step
|
// Container defines an execution container
|
||||||
type StepContainers struct {
|
type Container struct {
|
||||||
Containers map[string]interface{} `json:"containers"`
|
//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
|
// EnvVar defines an environment variable
|
||||||
type StepSidecars struct {
|
type EnvVar struct {
|
||||||
Sidecars map[string]interface{} `json:"sidecars"`
|
Name string `json:"name"`
|
||||||
|
Value string `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// StepFilters defines the filter parameters for the different sections
|
// 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.Parameters = append(filters.Parameters, secret.Name)
|
||||||
filters.Env = append(filters.Env, 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
|
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
|
||||||
|
}
|
||||||
|
@@ -2,9 +2,12 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadPipelineStepData(t *testing.T) {
|
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) {
|
t.Run("Secrets", func(t *testing.T) {
|
||||||
for _, s := range metadata1.Spec.Inputs.Secrets {
|
filters := metadata1.GetContextParameterFilters()
|
||||||
t.Run("All", func(t *testing.T) {
|
assert.Equal(t, []string{"testSecret1", "testSecret2"}, filters.All, "incorrect filter All")
|
||||||
if !sliceContains(filters.All, s.Name) {
|
assert.Equal(t, []string{"testSecret1", "testSecret2"}, filters.General, "incorrect filter General")
|
||||||
t.Errorf("Creation of context filter failed, expected: %v to be contained", s.Name)
|
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")
|
||||||
t.Run("General", func(t *testing.T) {
|
assert.Equal(t, []string{"testSecret1", "testSecret2"}, filters.Env, "incorrect filter Env")
|
||||||
if !sliceContains(filters.General, s.Name) {
|
})
|
||||||
t.Errorf("Creation of context filter failed, expected: %v to be contained", s.Name)
|
|
||||||
}
|
t.Run("Containers", func(t *testing.T) {
|
||||||
})
|
filters := metadata2.GetContextParameterFilters()
|
||||||
t.Run("Step", func(t *testing.T) {
|
assert.Equal(t, []string{"containerCommand", "containerShell", "dockerEnvVars", "dockerImage", "dockerOptions", "dockerPullImage", "dockerVolumeBind", "dockerWorkspace"}, filters.All, "incorrect filter All")
|
||||||
if !sliceContains(filters.Steps, s.Name) {
|
assert.NotEqual(t, []string{"containerCommand", "containerShell", "dockerEnvVars", "dockerImage", "dockerOptions", "dockerPullImage", "dockerVolumeBind", "dockerWorkspace"}, filters.General, "incorrect filter General")
|
||||||
t.Errorf("Creation of context filter failed, expected: %v to be contained", s.Name)
|
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")
|
||||||
t.Run("Stages", func(t *testing.T) {
|
assert.NotEqual(t, []string{"containerCommand", "containerShell", "dockerEnvVars", "dockerImage", "dockerOptions", "dockerPullImage", "dockerVolumeBind", "dockerWorkspace"}, filters.Env, "incorrect filter Env")
|
||||||
if !sliceContains(filters.Steps, s.Name) {
|
})
|
||||||
t.Errorf("Creation of context filter failed, expected: %v to be contained", s.Name)
|
|
||||||
}
|
t.Run("Sidecars", func(t *testing.T) {
|
||||||
})
|
filters := metadata3.GetContextParameterFilters()
|
||||||
t.Run("Parameters", func(t *testing.T) {
|
assert.Equal(t, []string{"containerName", "containerPortMappings", "dockerName", "sidecarEnvVars", "sidecarImage", "sidecarName", "sidecarOptions", "sidecarPullImage", "sidecarReadyCommand", "sidecarVolumeBind", "sidecarWorkspace"}, filters.All, "incorrect filter All")
|
||||||
if !sliceContains(filters.Parameters, s.Name) {
|
assert.NotEqual(t, []string{"containerName", "containerPortMappings", "dockerName", "sidecarEnvVars", "sidecarImage", "sidecarName", "sidecarOptions", "sidecarPullImage", "sidecarReadyCommand", "sidecarVolumeBind", "sidecarWorkspace"}, filters.General, "incorrect filter General")
|
||||||
t.Errorf("Creation of context filter failed, expected: %v to be contained", s.Name)
|
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")
|
||||||
t.Run("Env", func(t *testing.T) {
|
assert.NotEqual(t, []string{"containerName", "containerPortMappings", "dockerName", "sidecarEnvVars", "sidecarImage", "sidecarName", "sidecarOptions", "sidecarPullImage", "sidecarReadyCommand", "sidecarVolumeBind", "sidecarWorkspace"}, filters.Env, "incorrect filter Env")
|
||||||
if !sliceContains(filters.Env, s.Name) {
|
})
|
||||||
t.Errorf("Creation of context filter failed, expected: %v to be contained", s.Name)
|
}
|
||||||
}
|
|
||||||
})
|
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
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user