mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-14 11:03:09 +02:00
cd243ee542
* Upload reports to Google Cloud Storage bucket * Added tests. Made fixes * Update step generation. GCS client was moved to GeneralConfig * Code was refactored * Fixed issues * Fixed issues * Code correction due to PR comments * Improved gcs client and integration tests * Integrated gcp config. Updated step metadata * Fixed issues. Added tests * Added cpe, vault, aliases resolving for reporting parameters * Added tests * Uncommented DeferExitHandler. Removed useless comments * fixed cloning of config * Added comments for exported functions. Removed unused mock * minor fix * Implemented setting of report name via paramRef * some refactoring. Writing tests * Update pkg/config/reporting.go * Update cmd/sonarExecuteScan_generated.go * Apply suggestions from code review * Update pkg/config/reporting.go * Update pkg/config/reporting.go * fixed removing valut secret files * Update pkg/config/reporting.go * restore order * restore order * Apply suggestions from code review * go generate * fixed tests * Update resources/metadata/sonarExecuteScan.yaml * Update resources.go * Fixed tests. Code was regenerated * changed somewhere gcp to gcs. Fixed one test * move gcsSubFolder to input parameters * fixed removing valut secret files * minor fix in integration tests * fix integration tests Co-authored-by: Oliver Nocon <33484802+OliverNocon@users.noreply.github.com> Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com> Co-authored-by: Sven Merk <33895725+nevskrem@users.noreply.github.com>
1005 lines
27 KiB
Go
1005 lines
27 KiB
Go
package config
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/SAP/jenkins-library/pkg/piperenv"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
type errReadCloser int
|
|
|
|
func (errReadCloser) Read(p []byte) (n int, err error) {
|
|
return 0, errors.New("read error")
|
|
}
|
|
|
|
func (errReadCloser) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func customDefaultsOpenFileMock(name string, tokens map[string]string) (io.ReadCloser, error) {
|
|
return ioutil.NopCloser(strings.NewReader("general:\n p0: p0_custom_default\nstages:\n stage1:\n p1: p1_custom_default")), nil
|
|
}
|
|
|
|
func TestReadConfig(t *testing.T) {
|
|
|
|
var c Config
|
|
|
|
t.Run("Success case", func(t *testing.T) {
|
|
|
|
myConfig := strings.NewReader("general:\n generalTestKey: generalTestValue\nsteps:\n testStep:\n testStepKey: testStepValue")
|
|
|
|
err := c.ReadConfig(ioutil.NopCloser(myConfig)) // NopCloser "no-ops" the closing interface since strings do not need to be closed
|
|
if err != nil {
|
|
t.Errorf("Got error although no error expected: %v", err)
|
|
}
|
|
|
|
if c.General["generalTestKey"] != "generalTestValue" {
|
|
t.Errorf("General config- got: %v, expected: %v", c.General["generalTestKey"], "generalTestValue")
|
|
}
|
|
|
|
if c.Steps["testStep"]["testStepKey"] != "testStepValue" {
|
|
t.Errorf("Step config - got: %v, expected: %v", c.Steps["testStep"]["testStepKey"], "testStepValue")
|
|
}
|
|
})
|
|
|
|
t.Run("Read failure", func(t *testing.T) {
|
|
var rc errReadCloser
|
|
err := c.ReadConfig(rc)
|
|
if err == nil {
|
|
t.Errorf("Got no error although error expected.")
|
|
}
|
|
})
|
|
|
|
t.Run("Unmarshalling failure", func(t *testing.T) {
|
|
myConfig := strings.NewReader("general:\n generalTestKey: generalTestValue\nsteps:\n testStep:\n\ttestStepKey: testStepValue")
|
|
err := c.ReadConfig(ioutil.NopCloser(myConfig))
|
|
if err == nil {
|
|
t.Errorf("Got no error although error expected.")
|
|
}
|
|
})
|
|
|
|
}
|
|
|
|
func TestGetStepConfig(t *testing.T) {
|
|
|
|
t.Run("Success case", func(t *testing.T) {
|
|
|
|
testConfig := `general:
|
|
p3: p3_general
|
|
px3: px3_general
|
|
p4: p4_general
|
|
steps:
|
|
step1:
|
|
p4: p4_step
|
|
px4: px4_step
|
|
p5: p5_step
|
|
dependentParameter: dependentValue
|
|
stepAlias:
|
|
p8: p8_stepAlias
|
|
stages:
|
|
stage1:
|
|
p5: p5_stage
|
|
px5: px5_stage
|
|
p6: p6_stage
|
|
`
|
|
filters := StepFilters{
|
|
General: []string{"p0", "p1", "p2", "p3", "p4"},
|
|
Steps: []string{"p0", "p1", "p2", "p3", "p4", "p5", "p8", "dependentParameter", "pd1", "dependentValue", "pd2"},
|
|
Stages: []string{"p0", "p1", "p2", "p3", "p4", "p5", "p6"},
|
|
Parameters: []string{"p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7"},
|
|
Env: []string{"p0", "p1", "p2", "p3", "p4", "p5"},
|
|
}
|
|
|
|
defaults1 := `general:
|
|
p0: p0_general_default
|
|
px0: px0_general_default
|
|
p1: p1_general_default
|
|
steps:
|
|
step1:
|
|
p1: p1_step_default
|
|
px1: px1_step_default
|
|
p2: p2_step_default
|
|
dependentValue:
|
|
pd1: pd1_dependent_default
|
|
`
|
|
|
|
defaults2 := `general:
|
|
p2: p2_general_default
|
|
px2: px2_general_default
|
|
p3: p3_general_default
|
|
`
|
|
|
|
paramJSON := `{"p6":"p6_param","p7":"p7_param"}`
|
|
|
|
flags := map[string]interface{}{"p7": "p7_flag"}
|
|
|
|
var c Config
|
|
defaults := []io.ReadCloser{ioutil.NopCloser(strings.NewReader(defaults1)), ioutil.NopCloser(strings.NewReader(defaults2))}
|
|
|
|
myConfig := ioutil.NopCloser(strings.NewReader(testConfig))
|
|
|
|
parameterMetadata := []StepParameters{
|
|
{
|
|
Name: "pd1",
|
|
Scope: []string{"STEPS"},
|
|
Conditions: []Condition{
|
|
{
|
|
Params: []Param{
|
|
{Name: "dependentParameter", Value: "dependentValue"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "pd2",
|
|
Default: "pd2_metadata_default",
|
|
Scope: []string{"STEPS"},
|
|
Conditions: []Condition{
|
|
{
|
|
Params: []Param{
|
|
{Name: "dependentParameter", Value: "dependentValue"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "pe1",
|
|
Scope: []string{"STEPS"},
|
|
ResourceRef: []ResourceReference{{Name: "commonPipelineEnvironment", Param: "test_pe1"}},
|
|
Type: "string",
|
|
},
|
|
}
|
|
secretMetadata := []StepSecrets{
|
|
{
|
|
Name: "sd1",
|
|
Type: "jenkins",
|
|
},
|
|
}
|
|
|
|
stepAliases := []Alias{{Name: "stepAlias"}}
|
|
|
|
stepMeta := StepData{
|
|
Spec: StepSpec{
|
|
Inputs: StepInputs{
|
|
Parameters: parameterMetadata,
|
|
Secrets: secretMetadata,
|
|
},
|
|
},
|
|
Metadata: StepMetadata{
|
|
Aliases: stepAliases,
|
|
},
|
|
}
|
|
|
|
dir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
t.Fatal("Failed to create temporary directory")
|
|
}
|
|
|
|
// clean up tmp dir
|
|
defer os.RemoveAll(dir)
|
|
|
|
piperenv.SetParameter(filepath.Join(dir, "commonPipelineEnvironment"), "test_pe1", "pe1_val")
|
|
|
|
stepConfig, err := c.GetStepConfig(flags, paramJSON, myConfig, defaults, false, filters, stepMeta, stepMeta.GetResourceParameters(dir, "commonPipelineEnvironment"), "stage1", "step1")
|
|
|
|
assert.Equal(t, nil, err, "error occurred but none expected")
|
|
|
|
t.Run("Config", func(t *testing.T) {
|
|
expected := map[string]string{
|
|
"p0": "p0_general_default",
|
|
"p1": "p1_step_default",
|
|
"p2": "p2_general_default",
|
|
"p3": "p3_general",
|
|
"p4": "p4_step",
|
|
"p5": "p5_stage",
|
|
"p6": "p6_param",
|
|
"p7": "p7_flag",
|
|
"p8": "p8_stepAlias",
|
|
"pd1": "pd1_dependent_default",
|
|
"pd2": "pd2_metadata_default",
|
|
"pe1": "pe1_val",
|
|
}
|
|
|
|
for k, v := range expected {
|
|
t.Run(k, func(t *testing.T) {
|
|
if stepConfig.Config[k] != v {
|
|
t.Errorf("got: %v, expected: %v", stepConfig.Config[k], v)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("Config not expected", func(t *testing.T) {
|
|
notExpectedKeys := []string{"px0", "px1", "px2", "px3", "px4", "px5"}
|
|
for _, p := range notExpectedKeys {
|
|
t.Run(p, func(t *testing.T) {
|
|
if stepConfig.Config[p] != nil {
|
|
t.Errorf("unexpected: %v", p)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("Success case - environment nil", func(t *testing.T) {
|
|
|
|
testConfig := ""
|
|
filters := StepFilters{
|
|
General: []string{"p0"},
|
|
}
|
|
|
|
defaults1 := `general:
|
|
p0: p0_general_default
|
|
`
|
|
var c Config
|
|
defaults := []io.ReadCloser{ioutil.NopCloser(strings.NewReader(defaults1))}
|
|
|
|
myConfig := ioutil.NopCloser(strings.NewReader(testConfig))
|
|
|
|
stepMeta := StepData{Spec: StepSpec{Inputs: StepInputs{Parameters: []StepParameters{
|
|
{Name: "p0", ResourceRef: []ResourceReference{{Name: "commonPipelineEnvironment", Param: "p0"}}},
|
|
}}}}
|
|
|
|
dir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
t.Fatal("Failed to create temporary directory")
|
|
}
|
|
|
|
// clean up tmp dir
|
|
defer os.RemoveAll(dir)
|
|
|
|
stepConfig, err := c.GetStepConfig(map[string]interface{}{}, "", myConfig, defaults, false, filters, stepMeta, stepMeta.GetResourceParameters(dir, "commonPipelineEnvironment"), "stage1", "step1")
|
|
|
|
assert.Equal(t, nil, err, "error occurred but none expected")
|
|
|
|
assert.Equal(t, "p0_general_default", stepConfig.Config["p0"])
|
|
})
|
|
|
|
t.Run("Consider custom defaults from config", func(t *testing.T) {
|
|
var c Config
|
|
testConfDefaults := "customDefaults:\n- testDefaults.yaml"
|
|
|
|
c.openFile = customDefaultsOpenFileMock
|
|
|
|
stepConfig, err := c.GetStepConfig(nil, "", ioutil.NopCloser(strings.NewReader(testConfDefaults)), nil, false, StepFilters{General: []string{"p0"}}, StepData{}, nil, "stage1", "step1")
|
|
|
|
assert.NoError(t, err, "Error occurred but no error expected")
|
|
assert.Equal(t, "p0_custom_default", stepConfig.Config["p0"])
|
|
assert.Equal(t, "p1_custom_default", stepConfig.Config["p1"])
|
|
|
|
})
|
|
|
|
t.Run("Don't consider custom defaults from config", func(t *testing.T) {
|
|
var c Config
|
|
testConfDefaults := "customDefaults:\n- testDefaults.yaml"
|
|
|
|
c.openFile = customDefaultsOpenFileMock
|
|
|
|
stepConfig, err := c.GetStepConfig(nil, "", ioutil.NopCloser(strings.NewReader(testConfDefaults)), nil, true, StepFilters{General: []string{"p0"}}, StepData{}, nil, "stage1", "step1")
|
|
|
|
assert.NoError(t, err, "Error occurred but no error expected")
|
|
assert.Equal(t, nil, stepConfig.Config["p0"])
|
|
assert.Equal(t, nil, stepConfig.Config["p1"])
|
|
|
|
})
|
|
|
|
t.Run("Consider defaults from step config", func(t *testing.T) {
|
|
var c Config
|
|
|
|
stepParams := []StepParameters{{Name: "p0", Scope: []string{"GENERAL"}, Type: "string", Default: "p0_step_default", Aliases: []Alias{{Name: "p0_alias"}}}}
|
|
metadata := StepData{
|
|
Spec: StepSpec{
|
|
Inputs: StepInputs{
|
|
Parameters: stepParams,
|
|
},
|
|
},
|
|
}
|
|
testConf := "general:\n p1: p1_conf"
|
|
|
|
stepConfig, err := c.GetStepConfig(nil, "", ioutil.NopCloser(strings.NewReader(testConf)), nil, false, StepFilters{General: []string{"p0", "p1"}}, metadata, nil, "stage1", "step1")
|
|
|
|
assert.NoError(t, err, "Error occurred but no error expected")
|
|
assert.Equal(t, "p0_step_default", stepConfig.Config["p0"])
|
|
assert.Equal(t, "p1_conf", stepConfig.Config["p1"])
|
|
})
|
|
|
|
t.Run("Ignore alias if wrong type", func(t *testing.T) {
|
|
var c Config
|
|
|
|
stepParams := []StepParameters{
|
|
{Name: "p0", Scope: []string{"GENERAL"}, Type: "bool", Aliases: []Alias{}},
|
|
{Name: "p1", Scope: []string{"GENERAL"}, Type: "string", Aliases: []Alias{{Name: "p0/subParam"}}}}
|
|
metadata := StepData{
|
|
Spec: StepSpec{
|
|
Inputs: StepInputs{
|
|
Parameters: stepParams,
|
|
},
|
|
},
|
|
}
|
|
testConf := "general:\n p0: true"
|
|
|
|
stepConfig, err := c.GetStepConfig(nil, "", ioutil.NopCloser(strings.NewReader(testConf)), nil, false, StepFilters{General: []string{"p0", "p1"}}, metadata, nil, "stage1", "step1")
|
|
|
|
assert.NoError(t, err, "Error occurred but no error expected")
|
|
assert.Equal(t, true, stepConfig.Config["p0"])
|
|
assert.Equal(t, nil, stepConfig.Config["p1"])
|
|
})
|
|
|
|
t.Run("Apply alias to paramJSON", func(t *testing.T) {
|
|
var c Config
|
|
|
|
secrets := []StepSecrets{
|
|
{Name: "p0", Type: "string", Aliases: []Alias{{Name: "p1/subParam"}}}}
|
|
metadata := StepData{
|
|
Spec: StepSpec{
|
|
Inputs: StepInputs{
|
|
Secrets: secrets,
|
|
},
|
|
},
|
|
}
|
|
testConf := ""
|
|
|
|
paramJSON := "{\"p1\":{\"subParam\":\"p1_value\"}}"
|
|
stepConfig, err := c.GetStepConfig(nil, paramJSON, ioutil.NopCloser(strings.NewReader(testConf)), nil, true, StepFilters{Parameters: []string{"p0"}}, metadata, nil, "stage1", "step1")
|
|
|
|
assert.NoError(t, err, "Error occurred but no error expected")
|
|
assert.Equal(t, "p1_value", stepConfig.Config["p0"])
|
|
})
|
|
|
|
t.Run("Failure case config", func(t *testing.T) {
|
|
var c Config
|
|
myConfig := ioutil.NopCloser(strings.NewReader("invalid config"))
|
|
_, err := c.GetStepConfig(nil, "", myConfig, nil, false, StepFilters{}, StepData{}, nil, "stage1", "step1")
|
|
assert.EqualError(t, err, "failed to parse custom pipeline configuration: format of configuration is invalid \"invalid config\": error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go value of type config.Config", "default error expected")
|
|
})
|
|
|
|
t.Run("Failure case defaults", func(t *testing.T) {
|
|
var c Config
|
|
myConfig := ioutil.NopCloser(strings.NewReader(""))
|
|
myDefaults := []io.ReadCloser{ioutil.NopCloser(strings.NewReader("invalid defaults"))}
|
|
_, err := c.GetStepConfig(nil, "", myConfig, myDefaults, false, StepFilters{}, StepData{}, nil, "stage1", "step1")
|
|
assert.EqualError(t, err, "failed to read default configuration: error unmarshalling \"invalid defaults\": error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go value of type config.Config", "default error expected")
|
|
})
|
|
|
|
t.Run("Test reporting parameters with aliases and cpe resources", func(t *testing.T) {
|
|
var c Config
|
|
testConfig := ioutil.NopCloser(strings.NewReader(`general:
|
|
gcpJsonKeyFilePath: gcpJsonKeyFilePath_value
|
|
steps:
|
|
step1:
|
|
jsonKeyFilePath: gcpJsonKeyFilePath_from_alias`))
|
|
testDefaults := []io.ReadCloser{ioutil.NopCloser(strings.NewReader(`general:
|
|
pipelineId: gcsBucketId_from_alias
|
|
steps:
|
|
step1:
|
|
gcsBucketId: gcsBucketId_value`))}
|
|
dir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
t.Fatal("Failed to create temporary directory")
|
|
}
|
|
|
|
// clean up tmp dir
|
|
defer os.RemoveAll(dir)
|
|
cpeDir := filepath.Join(dir, "commonPipelineEnvironment/custom")
|
|
err = os.MkdirAll(cpeDir, 0700)
|
|
if err != nil {
|
|
t.Fatal("Failed to create sub directory")
|
|
}
|
|
|
|
err = ioutil.WriteFile(filepath.Join(cpeDir, "gcsFolderPath.json"), []byte("\"value_from_cpe\""), 0700)
|
|
assert.NoError(t, err)
|
|
|
|
stepMeta := StepData{Spec: StepSpec{Inputs: StepInputs{Parameters: []StepParameters{}}}}
|
|
stepConfig, err := c.GetStepConfig(nil, "", testConfig, testDefaults, false, StepFilters{General: []string{"p0", "p1"}}, stepMeta, ReportingParameters.GetResourceParameters(dir, "commonPipelineEnvironment"), "stage1", "step1")
|
|
|
|
assert.NoError(t, err, "Error occurred but no error expected")
|
|
assert.Equal(t, "gcpJsonKeyFilePath_from_alias", stepConfig.Config["gcpJsonKeyFilePath"])
|
|
assert.Equal(t, "gcsBucketId_value", stepConfig.Config["gcsBucketId"])
|
|
assert.Equal(t, "value_from_cpe", stepConfig.Config["gcsFolderPath"])
|
|
})
|
|
|
|
//ToDo: test merging of env and parameters/flags
|
|
}
|
|
|
|
func TestGetStepConfigWithJSON(t *testing.T) {
|
|
|
|
filters := StepFilters{All: []string{"key1"}}
|
|
|
|
t.Run("Without flags", func(t *testing.T) {
|
|
sc := GetStepConfigWithJSON(nil, `"key1":"value1","key2":"value2"`, filters)
|
|
|
|
if sc.Config["key1"] != "value1" && sc.Config["key2"] == "value2" {
|
|
t.Errorf("got: %v, expected: %v", sc.Config, StepConfig{Config: map[string]interface{}{"key1": "value1"}})
|
|
}
|
|
})
|
|
|
|
t.Run("With flags", func(t *testing.T) {
|
|
flags := map[string]interface{}{"key1": "flagVal1"}
|
|
sc := GetStepConfigWithJSON(flags, `"key1":"value1","key2":"value2"`, filters)
|
|
if sc.Config["key1"] != "flagVal1" {
|
|
t.Errorf("got: %v, expected: %v", sc.Config["key1"], "flagVal1")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestGetStageConfig(t *testing.T) {
|
|
|
|
testConfig := `general:
|
|
p1: p1_general
|
|
px1: px1_general
|
|
stages:
|
|
stage1:
|
|
p2: p2_stage
|
|
px2: px2_stage
|
|
`
|
|
defaults1 := `general:
|
|
p0: p0_general_default
|
|
px0: px0_general_default
|
|
`
|
|
paramJSON := `{"p3":"p3_param"}`
|
|
|
|
t.Run("Success case - with filters", func(t *testing.T) {
|
|
|
|
acceptedParams := []string{"p0", "p1", "p2", "p3"}
|
|
|
|
var c Config
|
|
defaults := []io.ReadCloser{ioutil.NopCloser(strings.NewReader(defaults1))}
|
|
|
|
myConfig := ioutil.NopCloser(strings.NewReader(testConfig))
|
|
|
|
dir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
t.Fatal("Failed to create temporary directory")
|
|
}
|
|
|
|
// clean up tmp dir
|
|
defer os.RemoveAll(dir)
|
|
|
|
stepConfig, err := c.GetStageConfig(paramJSON, myConfig, defaults, false, acceptedParams, "stage1")
|
|
|
|
assert.Equal(t, nil, err, "error occurred but none expected")
|
|
|
|
t.Run("Config", func(t *testing.T) {
|
|
expected := map[string]string{
|
|
"p0": "p0_general_default",
|
|
"p1": "p1_general",
|
|
"p2": "p2_stage",
|
|
"p3": "p3_param",
|
|
}
|
|
|
|
for k, v := range expected {
|
|
t.Run(k, func(t *testing.T) {
|
|
if stepConfig.Config[k] != v {
|
|
t.Errorf("got: %v, expected: %v", stepConfig.Config[k], v)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("Config not expected", func(t *testing.T) {
|
|
notExpectedKeys := []string{"px0", "px1", "px2"}
|
|
for _, p := range notExpectedKeys {
|
|
t.Run(p, func(t *testing.T) {
|
|
if stepConfig.Config[p] != nil {
|
|
t.Errorf("unexpected: %v", p)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("Success case - no filters", func(t *testing.T) {
|
|
|
|
acceptedParams := []string{}
|
|
|
|
var c Config
|
|
defaults := []io.ReadCloser{ioutil.NopCloser(strings.NewReader(defaults1))}
|
|
|
|
myConfig := ioutil.NopCloser(strings.NewReader(testConfig))
|
|
|
|
dir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
t.Fatal("Failed to create temporary directory")
|
|
}
|
|
|
|
// clean up tmp dir
|
|
defer os.RemoveAll(dir)
|
|
|
|
stepConfig, err := c.GetStageConfig(paramJSON, myConfig, defaults, false, acceptedParams, "stage1")
|
|
|
|
assert.Equal(t, nil, err, "error occurred but none expected")
|
|
|
|
t.Run("Config", func(t *testing.T) {
|
|
expected := map[string]string{
|
|
"p0": "p0_general_default",
|
|
"px0": "px0_general_default",
|
|
"p1": "p1_general",
|
|
"px1": "px1_general",
|
|
"p2": "p2_stage",
|
|
"px2": "px2_stage",
|
|
"p3": "p3_param",
|
|
}
|
|
|
|
for k, v := range expected {
|
|
t.Run(k, func(t *testing.T) {
|
|
if stepConfig.Config[k] != v {
|
|
t.Errorf("got: %v, expected: %v", stepConfig.Config[k], v)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestApplyAliasConfig(t *testing.T) {
|
|
p := []StepParameters{
|
|
{
|
|
Name: "p0",
|
|
Aliases: []Alias{
|
|
{Name: "p0_notused"},
|
|
},
|
|
},
|
|
{
|
|
Name: "p1",
|
|
Aliases: []Alias{
|
|
{Name: "p1_alias"},
|
|
},
|
|
},
|
|
{
|
|
Name: "p2",
|
|
Aliases: []Alias{
|
|
{Name: "p2_alias/deep/test"},
|
|
},
|
|
},
|
|
{
|
|
Name: "p3",
|
|
Aliases: []Alias{
|
|
{Name: "p3_notused"},
|
|
},
|
|
},
|
|
{
|
|
Name: "p4",
|
|
Aliases: []Alias{
|
|
{Name: "p4_alias"},
|
|
{Name: "p4_2nd_alias"},
|
|
},
|
|
},
|
|
{
|
|
Name: "p5",
|
|
Aliases: []Alias{
|
|
{Name: "p5_notused"},
|
|
},
|
|
},
|
|
{
|
|
Name: "p6",
|
|
Aliases: []Alias{
|
|
{Name: "p6_1st_alias"},
|
|
{Name: "p6_alias"},
|
|
},
|
|
},
|
|
{
|
|
Name: "p7",
|
|
Aliases: []Alias{
|
|
{Name: "p7_alias"},
|
|
},
|
|
},
|
|
{
|
|
Name: "p8",
|
|
Aliases: []Alias{
|
|
{Name: "p8_alias"},
|
|
},
|
|
},
|
|
{
|
|
Name: "p9",
|
|
},
|
|
}
|
|
s := []StepSecrets{
|
|
{
|
|
Name: "s1",
|
|
Aliases: []Alias{
|
|
{Name: "s1_alias"},
|
|
},
|
|
},
|
|
}
|
|
|
|
filters := StepFilters{
|
|
General: []string{"p1", "p2"},
|
|
Stages: []string{"p4"},
|
|
Steps: []string{"p6", "p8", "s1"},
|
|
}
|
|
|
|
c := Config{
|
|
General: map[string]interface{}{
|
|
"p0_notused": "p0_general",
|
|
"p1_alias": "p1_general",
|
|
"p2_alias": map[string]interface{}{
|
|
"deep": map[string]interface{}{
|
|
"test": "p2_general",
|
|
},
|
|
},
|
|
},
|
|
Stages: map[string]map[string]interface{}{
|
|
"stage1": {
|
|
"p3_notused": "p3_stage",
|
|
"p4_alias": "p4_stage",
|
|
},
|
|
},
|
|
Steps: map[string]map[string]interface{}{
|
|
"step1": {
|
|
"p5_notused": "p5_step",
|
|
"p6_alias": "p6_step",
|
|
"p7": "p7_step",
|
|
},
|
|
"stepAlias1": {
|
|
"p7": "p7_stepAlias",
|
|
"p8_alias": "p8_stepAlias",
|
|
"p9": "p9_stepAlias",
|
|
"s1_alias": "s1_stepAlias",
|
|
},
|
|
},
|
|
}
|
|
|
|
stepAliases := []Alias{{Name: "stepAlias1"}}
|
|
|
|
c.ApplyAliasConfig(p, s, filters, "stage1", "step1", stepAliases)
|
|
|
|
t.Run("Global", func(t *testing.T) {
|
|
assert.Nil(t, c.General["p0"])
|
|
assert.Equal(t, "p1_general", c.General["p1"])
|
|
assert.Equal(t, "p2_general", c.General["p2"])
|
|
})
|
|
|
|
t.Run("Stage", func(t *testing.T) {
|
|
assert.Nil(t, c.General["p3"])
|
|
assert.Equal(t, "p4_stage", c.Stages["stage1"]["p4"])
|
|
})
|
|
|
|
t.Run("Steps", func(t *testing.T) {
|
|
assert.Nil(t, c.General["p5"])
|
|
assert.Equal(t, "p6_step", c.Steps["step1"]["p6"])
|
|
assert.Equal(t, "p7_step", c.Steps["step1"]["p7"])
|
|
assert.Equal(t, "p8_stepAlias", c.Steps["step1"]["p8"])
|
|
assert.Equal(t, "p9_stepAlias", c.Steps["step1"]["p9"])
|
|
assert.Equal(t, "s1_stepAlias", c.Steps["step1"]["s1"])
|
|
})
|
|
|
|
}
|
|
|
|
func TestGetDeepAliasValue(t *testing.T) {
|
|
c := map[string]interface{}{
|
|
"p0": "p0_val",
|
|
"p1": 11,
|
|
"p2": map[string]interface{}{
|
|
"p2_0": "p2_0_val",
|
|
"p2_1": map[string]interface{}{
|
|
"p2_1_0": "p2_1_0_val",
|
|
},
|
|
},
|
|
}
|
|
tt := []struct {
|
|
key string
|
|
expected interface{}
|
|
}{
|
|
{key: "p0", expected: "p0_val"},
|
|
{key: "p1", expected: 11},
|
|
{key: "p2/p2_0", expected: "p2_0_val"},
|
|
{key: "p2/p2_1/p2_1_0", expected: "p2_1_0_val"},
|
|
}
|
|
|
|
for k, v := range tt {
|
|
assert.Equal(t, v.expected, getDeepAliasValue(c, v.key), fmt.Sprintf("wrong return value for run %v", k+1))
|
|
}
|
|
}
|
|
|
|
func TestCopyStepAliasConfig(t *testing.T) {
|
|
t.Run("Step config available", func(t *testing.T) {
|
|
c := Config{
|
|
Steps: map[string]map[string]interface{}{
|
|
"step1": {
|
|
"p1": "p1_step",
|
|
"p2": "p2_step",
|
|
},
|
|
"stepAlias1": {
|
|
"p2": "p2_stepAlias",
|
|
"p3": "p3_stepAlias",
|
|
},
|
|
"stepAlias2": {
|
|
"p3": "p3_stepAlias2",
|
|
"p4": "p4_stepAlias2",
|
|
},
|
|
},
|
|
}
|
|
|
|
expected := Config{
|
|
Steps: map[string]map[string]interface{}{
|
|
"step1": {
|
|
"p1": "p1_step",
|
|
"p2": "p2_step",
|
|
"p3": "p3_stepAlias",
|
|
"p4": "p4_stepAlias2",
|
|
},
|
|
"stepAlias1": {
|
|
"p2": "p2_stepAlias",
|
|
"p3": "p3_stepAlias",
|
|
},
|
|
"stepAlias2": {
|
|
"p3": "p3_stepAlias2",
|
|
"p4": "p4_stepAlias2",
|
|
},
|
|
},
|
|
}
|
|
|
|
c.copyStepAliasConfig("step1", []Alias{{Name: "stepAlias1"}, {Name: "stepAlias2"}})
|
|
assert.Equal(t, expected, c)
|
|
})
|
|
|
|
t.Run("Step config not available", func(t *testing.T) {
|
|
c := Config{
|
|
Steps: map[string]map[string]interface{}{
|
|
"stepAlias1": {
|
|
"p2": "p2_stepAlias",
|
|
},
|
|
},
|
|
}
|
|
|
|
expected := Config{
|
|
Steps: map[string]map[string]interface{}{
|
|
"step1": {
|
|
"p2": "p2_stepAlias",
|
|
},
|
|
"stepAlias1": {
|
|
"p2": "p2_stepAlias",
|
|
},
|
|
},
|
|
}
|
|
|
|
c.copyStepAliasConfig("step1", []Alias{{Name: "stepAlias1"}})
|
|
assert.Equal(t, expected, c)
|
|
})
|
|
}
|
|
|
|
func TestGetJSON(t *testing.T) {
|
|
|
|
t.Run("Success case", func(t *testing.T) {
|
|
custom := map[string]interface{}{"key1": "value1"}
|
|
json, err := GetJSON(custom)
|
|
if err != nil {
|
|
t.Errorf("Got error although no error expected: %v", err)
|
|
}
|
|
|
|
if json != `{"key1":"value1"}` {
|
|
t.Errorf("got: %v, expected: %v", json, `{"key1":"value1"}`)
|
|
}
|
|
|
|
})
|
|
t.Run("Marshalling failure", func(t *testing.T) {
|
|
_, err := GetJSON(make(chan int))
|
|
if err == nil {
|
|
t.Errorf("Got no error although error expected")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestMerge(t *testing.T) {
|
|
|
|
testTable := []struct {
|
|
Source map[string]interface{}
|
|
Filter []string
|
|
MergeData map[string]interface{}
|
|
ExpectedOutput map[string]interface{}
|
|
}{
|
|
{
|
|
Source: map[string]interface{}{"key1": "baseValue"},
|
|
Filter: []string{},
|
|
MergeData: map[string]interface{}{"key1": "overwrittenValue"},
|
|
ExpectedOutput: map[string]interface{}{"key1": "overwrittenValue"},
|
|
},
|
|
{
|
|
Source: map[string]interface{}{"key1": "value1"},
|
|
Filter: []string{},
|
|
MergeData: map[string]interface{}{"key2": "value2"},
|
|
ExpectedOutput: map[string]interface{}{"key1": "value1", "key2": "value2"},
|
|
},
|
|
{
|
|
Source: map[string]interface{}{"key1": "value1"},
|
|
Filter: []string{"key1"},
|
|
MergeData: map[string]interface{}{"key2": "value2"},
|
|
ExpectedOutput: map[string]interface{}{"key1": "value1"},
|
|
},
|
|
{
|
|
Source: map[string]interface{}{"key1": map[string]interface{}{"key1_1": "value1"}},
|
|
Filter: []string{},
|
|
MergeData: map[string]interface{}{"key1": map[string]interface{}{"key1_2": "value2"}},
|
|
ExpectedOutput: map[string]interface{}{"key1": map[string]interface{}{"key1_1": "value1", "key1_2": "value2"}},
|
|
},
|
|
}
|
|
|
|
for _, row := range testTable {
|
|
t.Run(fmt.Sprintf("Merging %v into %v", row.MergeData, row.Source), func(t *testing.T) {
|
|
stepConfig := StepConfig{Config: row.Source}
|
|
stepConfig.mixIn(row.MergeData, row.Filter)
|
|
assert.Equal(t, row.ExpectedOutput, stepConfig.Config, "Mixin was incorrect")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestStepConfig_mixInHookConfig(t *testing.T) {
|
|
type fields struct {
|
|
Config map[string]interface{}
|
|
HookConfig map[string]interface{}
|
|
}
|
|
type args struct {
|
|
mergeData map[string]interface{}
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
args args
|
|
want map[string]interface{}
|
|
}{
|
|
{name: "Splunk only",
|
|
fields: fields{
|
|
Config: nil,
|
|
HookConfig: nil,
|
|
},
|
|
args: args{mergeData: map[string]interface{}{
|
|
"splunk": map[string]interface{}{
|
|
"dsn": "dsn",
|
|
"token": "token",
|
|
"sendLogs": "false",
|
|
},
|
|
}},
|
|
want: map[string]interface{}{
|
|
"splunk": map[string]interface{}{
|
|
"dsn": "dsn",
|
|
"token": "token",
|
|
"sendLogs": "false",
|
|
},
|
|
},
|
|
},
|
|
{name: "Sentry only",
|
|
fields: fields{
|
|
Config: nil,
|
|
HookConfig: nil,
|
|
},
|
|
args: args{mergeData: map[string]interface{}{
|
|
"sentry": map[string]interface{}{
|
|
"dsn": "sentrydsn",
|
|
},
|
|
}},
|
|
want: map[string]interface{}{
|
|
"sentry": map[string]interface{}{
|
|
"dsn": "sentrydsn",
|
|
},
|
|
},
|
|
},
|
|
{name: "Splunk and Sentry",
|
|
fields: fields{
|
|
Config: nil,
|
|
HookConfig: nil,
|
|
},
|
|
args: args{mergeData: map[string]interface{}{
|
|
"splunk": map[string]interface{}{
|
|
"dsn": "dsn",
|
|
"token": "token",
|
|
"sendLogs": "false",
|
|
},
|
|
"sentry": map[string]interface{}{
|
|
"dsn": "sentrydsn",
|
|
},
|
|
}},
|
|
want: map[string]interface{}{
|
|
"splunk": map[string]interface{}{
|
|
"dsn": "dsn",
|
|
"token": "token",
|
|
"sendLogs": "false",
|
|
},
|
|
"sentry": map[string]interface{}{
|
|
"dsn": "sentrydsn",
|
|
},
|
|
},
|
|
},
|
|
{name: "No Hook",
|
|
fields: fields{
|
|
Config: nil,
|
|
HookConfig: nil,
|
|
},
|
|
args: args{mergeData: nil},
|
|
want: map[string]interface{}{},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
s := &StepConfig{
|
|
Config: tt.fields.Config,
|
|
HookConfig: tt.fields.HookConfig,
|
|
}
|
|
s.mixInHookConfig(tt.args.mergeData)
|
|
if !reflect.DeepEqual(s.HookConfig, tt.want) {
|
|
t.Errorf("mixInHookConfig() = %v, want %v", s.HookConfig, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMixInStepDefaults(t *testing.T) {
|
|
tt := []struct {
|
|
name string
|
|
stepConfig *StepConfig
|
|
stepParams []StepParameters
|
|
expected map[string]interface{}
|
|
}{
|
|
{name: "empty", stepConfig: &StepConfig{}, stepParams: []StepParameters{}, expected: map[string]interface{}{}},
|
|
{name: "no condition", stepConfig: &StepConfig{}, stepParams: []StepParameters{{Name: "noCondition", Default: "noCondition_default"}}, expected: map[string]interface{}{"noCondition": "noCondition_default"}},
|
|
{
|
|
name: "with multiple conditions",
|
|
stepConfig: &StepConfig{},
|
|
stepParams: []StepParameters{
|
|
{Name: "dependentParam1", Default: "dependentParam1_value"},
|
|
{Name: "dependentParam2", Default: "dependentParam2_value"},
|
|
{
|
|
Name: "withConditionParameter",
|
|
Default: "withCondition_default_a",
|
|
Conditions: []Condition{
|
|
{ConditionRef: "strings-equal", Params: []Param{{Name: "dependentParam1", Value: "dependentParam1_value1"}}},
|
|
{ConditionRef: "strings-equal", Params: []Param{{Name: "dependentParam2", Value: "dependentParam2_value1"}}},
|
|
},
|
|
},
|
|
{
|
|
Name: "withConditionParameter",
|
|
Default: "withCondition_default_b",
|
|
Conditions: []Condition{
|
|
{ConditionRef: "strings-equal", Params: []Param{{Name: "dependentParam1", Value: "dependentParam1_value2"}}},
|
|
{ConditionRef: "strings-equal", Params: []Param{{Name: "dependentParam2", Value: "dependentParam2_value2"}}},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"dependentParam1": "dependentParam1_value",
|
|
"dependentParam2": "dependentParam2_value",
|
|
"dependentParam1_value1": map[string]interface{}{"withConditionParameter": "withCondition_default_a"},
|
|
"dependentParam2_value1": map[string]interface{}{"withConditionParameter": "withCondition_default_a"},
|
|
"dependentParam1_value2": map[string]interface{}{"withConditionParameter": "withCondition_default_b"},
|
|
"dependentParam2_value2": map[string]interface{}{"withConditionParameter": "withCondition_default_b"},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tt {
|
|
test.stepConfig.mixInStepDefaults(test.stepParams)
|
|
assert.Equal(t, test.expected, test.stepConfig.Config, test.name)
|
|
}
|
|
}
|
|
|
|
func TestCloneConfig(t *testing.T) {
|
|
testConfig := &Config{
|
|
General: map[string]interface{}{
|
|
"p0": "p0_general",
|
|
},
|
|
Stages: map[string]map[string]interface{}{
|
|
"stage1": {
|
|
"p1": "p1_stage",
|
|
},
|
|
},
|
|
Steps: map[string]map[string]interface{}{
|
|
"step1": {
|
|
"p2": "p2_step",
|
|
},
|
|
},
|
|
}
|
|
clone, err := cloneConfig(testConfig)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, testConfig, clone)
|
|
testConfig.General["p0"] = "new_value"
|
|
assert.NotEqual(t, testConfig.General, clone.General)
|
|
}
|