Piper-Go: Allow aliases also for inputs of type "secret" (#1355)

* Fix typos

* Support aliases also for secrets

* Adapt & extend Unit Tests

* Output deprecation warning for param/secret aliases

... if the alias is marked as 'deprecated'.
This commit is contained in:
Stephan Aßmus
2020-04-01 20:46:33 +02:00
committed by GitHub
parent 0a29ff2c57
commit da0f25fd7b
5 changed files with 76 additions and 38 deletions
+2 -2
View File
@@ -85,7 +85,7 @@ func generateConfig() error {
params = metadata.Spec.Inputs.Parameters
}
stepConfig, err = myConfig.GetStepConfig(flags, GeneralConfig.ParametersJSON, customConfig, defaultConfig, paramFilter, params, resourceParams, GeneralConfig.StageName, metadata.Metadata.Name, metadata.Metadata.Aliases)
stepConfig, err = myConfig.GetStepConfig(flags, GeneralConfig.ParametersJSON, customConfig, defaultConfig, paramFilter, params, metadata.Spec.Inputs.Secrets, resourceParams, GeneralConfig.StageName, metadata.Metadata.Name, metadata.Metadata.Aliases)
if err != nil {
return errors.Wrap(err, "getting step config failed")
}
@@ -111,7 +111,7 @@ func addConfigFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&configOptions.stepMetadata, "stepMetadata", "", "Step metadata, passed as path to yaml")
cmd.Flags().BoolVar(&configOptions.contextConfig, "contextConfig", false, "Defines if step context configuration should be loaded instead of step config")
cmd.MarkFlagRequired("stepMetadata")
_ = cmd.MarkFlagRequired("stepMetadata")
}
+2 -2
View File
@@ -137,7 +137,7 @@ func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName strin
}
}
stepConfig, err = myConfig.GetStepConfig(flagValues, GeneralConfig.ParametersJSON, customConfig, defaultConfig, filters, metadata.Spec.Inputs.Parameters, resourceParams, GeneralConfig.StageName, stepName, metadata.Metadata.Aliases)
stepConfig, err = myConfig.GetStepConfig(flagValues, GeneralConfig.ParametersJSON, customConfig, defaultConfig, filters, metadata.Spec.Inputs.Parameters, metadata.Spec.Inputs.Secrets, resourceParams, GeneralConfig.StageName, stepName, metadata.Metadata.Aliases)
if err != nil {
return errors.Wrap(err, "retrieving step configuration failed")
}
@@ -154,7 +154,7 @@ func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName strin
}
confJSON, _ := json.Marshal(stepConfig.Config)
json.Unmarshal(confJSON, &options)
_ = json.Unmarshal(confJSON, &options)
config.MarkFlagsWithValue(cmd, stepConfig)
+41 -20
View File
@@ -47,30 +47,42 @@ func (c *Config) ReadConfig(configuration io.ReadCloser) error {
}
// ApplyAliasConfig adds configuration values available on aliases to primary configuration parameters
func (c *Config) ApplyAliasConfig(parameters []StepParameters, filters StepFilters, stageName, stepName string, stepAliases []Alias) {
func (c *Config) ApplyAliasConfig(parameters []StepParameters, secrets []StepSecrets, filters StepFilters, stageName, stepName string, stepAliases []Alias) {
// copy configuration from step alias to correct step
if len(stepAliases) > 0 {
c.copyStepAliasConfig(stepName, stepAliases)
}
for _, p := range parameters {
c.General = setParamValueFromAlias(c.General, filters.General, p)
c.General = setParamValueFromAlias(c.General, filters.General, p.Name, p.Aliases)
if c.Stages[stageName] != nil {
c.Stages[stageName] = setParamValueFromAlias(c.Stages[stageName], filters.Stages, p)
c.Stages[stageName] = setParamValueFromAlias(c.Stages[stageName], filters.Stages, p.Name, p.Aliases)
}
if c.Steps[stepName] != nil {
c.Steps[stepName] = setParamValueFromAlias(c.Steps[stepName], filters.Steps, p)
c.Steps[stepName] = setParamValueFromAlias(c.Steps[stepName], filters.Steps, p.Name, p.Aliases)
}
}
for _, s := range secrets {
c.General = setParamValueFromAlias(c.General, filters.General, s.Name, s.Aliases)
if c.Stages[stageName] != nil {
c.Stages[stageName] = setParamValueFromAlias(c.Stages[stageName], filters.Stages, s.Name, s.Aliases)
}
if c.Steps[stepName] != nil {
c.Steps[stepName] = setParamValueFromAlias(c.Steps[stepName], filters.Steps, s.Name, s.Aliases)
}
}
}
func setParamValueFromAlias(configMap map[string]interface{}, filter []string, p StepParameters) map[string]interface{} {
if configMap != nil && configMap[p.Name] == nil && sliceContains(filter, p.Name) {
for _, a := range p.Aliases {
func setParamValueFromAlias(configMap map[string]interface{}, filter []string, name string, aliases []Alias) map[string]interface{} {
if configMap != nil && configMap[name] == nil && sliceContains(filter, name) {
for _, a := range aliases {
aliasVal := getDeepAliasValue(configMap, a.Name)
if aliasVal != nil {
configMap[p.Name] = aliasVal
configMap[name] = aliasVal
if a.Deprecated {
log.Entry().WithField("package", "SAP/jenkins-library/pkg/config").Warningf("DEPRECATION NOTICE: old step config key '%v' used. Please switch to '%v'!", a.Name, name)
}
}
if configMap[p.Name] != nil {
if configMap[name] != nil {
return configMap
}
}
@@ -108,7 +120,7 @@ func (c *Config) copyStepAliasConfig(stepName string, stepAliases []Alias) {
}
// GetStepConfig provides merged step configuration using defaults, config, if available
func (c *Config) GetStepConfig(flagValues map[string]interface{}, paramJSON string, configuration io.ReadCloser, defaults []io.ReadCloser, filters StepFilters, parameters []StepParameters, envParameters map[string]interface{}, stageName, stepName string, stepAliases []Alias) (StepConfig, error) {
func (c *Config) GetStepConfig(flagValues map[string]interface{}, paramJSON string, configuration io.ReadCloser, defaults []io.ReadCloser, filters StepFilters, parameters []StepParameters, secrets []StepSecrets, envParameters map[string]interface{}, stageName, stepName string, stepAliases []Alias) (StepConfig, error) {
var stepConfig StepConfig
var d PipelineDefaults
@@ -118,7 +130,7 @@ func (c *Config) GetStepConfig(flagValues map[string]interface{}, paramJSON stri
}
}
c.ApplyAliasConfig(parameters, filters, stageName, stepName, stepAliases)
c.ApplyAliasConfig(parameters, secrets, filters, stageName, stepName, stepAliases)
// consider custom defaults defined in config.yml
if c.CustomDefaults != nil && len(c.CustomDefaults) > 0 {
@@ -143,7 +155,7 @@ func (c *Config) GetStepConfig(flagValues map[string]interface{}, paramJSON stri
// read defaults & merge general -> steps (-> general -> steps ...)
for _, def := range d.Defaults {
def.ApplyAliasConfig(parameters, filters, stageName, stepName, stepAliases)
def.ApplyAliasConfig(parameters, secrets, filters, stageName, stepName, stepAliases)
stepConfig.mixIn(def.General, filters.General)
stepConfig.mixIn(def.Steps[stepName], filters.Steps)
}
@@ -162,14 +174,17 @@ func (c *Config) GetStepConfig(flagValues map[string]interface{}, paramJSON stri
// if parameters are provided in JSON format merge them
if len(paramJSON) != 0 {
var params map[string]interface{}
json.Unmarshal([]byte(paramJSON), &params)
err := json.Unmarshal([]byte(paramJSON), &params)
if err != nil {
log.Entry().Warnf("failed to parse parameters from environment: %v", err)
} else {
//apply aliases
for _, p := range parameters {
params = setParamValueFromAlias(params, filters.Parameters, p.Name, p.Aliases)
}
//apply aliases
for _, p := range parameters {
params = setParamValueFromAlias(params, filters.Parameters, p)
stepConfig.mixIn(params, filters.Parameters)
}
stepConfig.mixIn(params, filters.Parameters)
}
// merge command line flags
@@ -201,7 +216,10 @@ func GetStepConfigWithJSON(flagValues map[string]interface{}, stepConfigJSON str
stepConfigMap := map[string]interface{}{}
json.Unmarshal([]byte(stepConfigJSON), &stepConfigMap)
err := json.Unmarshal([]byte(stepConfigJSON), &stepConfigMap)
if err != nil {
log.Entry().Warnf("invalid stepConfig JSON: %v", err)
}
stepConfig.mixIn(stepConfigMap, filters.All)
@@ -232,7 +250,10 @@ func OpenPiperFile(name string) (io.ReadCloser, error) {
// support http(s) urls next to file path - url cannot be protected
client := http.Client{}
response, err := client.SendRequest("GET", name, nil, nil, nil)
return response.Body, err
if err != nil {
return nil, err
}
return response.Body, nil
}
func envValues(filter []string) map[string]interface{} {
+24 -8
View File
@@ -156,8 +156,14 @@ steps:
ResourceRef: []ResourceReference{{Name: "commonPipelineEnvironment", Param: "test_pe1"}},
},
}
secretMetadata := []StepSecrets{
{
Name: "sd1",
Type: "jenkins",
},
}
stepMeta := StepData{Spec: StepSpec{Inputs: StepInputs{Parameters: parameterMetadata}}}
stepMeta := StepData{Spec: StepSpec{Inputs: StepInputs{Parameters: parameterMetadata, Secrets: secretMetadata}}}
dir, err := ioutil.TempDir("", "")
if err != nil {
@@ -170,7 +176,7 @@ steps:
piperenv.SetParameter(filepath.Join(dir, "commonPipelineEnvironment"), "test_pe1", "pe1_val")
stepAliases := []Alias{{Name: "stepAlias"}}
stepConfig, err := c.GetStepConfig(flags, paramJSON, myConfig, defaults, filters, parameterMetadata, stepMeta.GetResourceParameters(dir, "commonPipelineEnvironment"), "stage1", "step1", stepAliases)
stepConfig, err := c.GetStepConfig(flags, paramJSON, myConfig, defaults, filters, parameterMetadata, secretMetadata, stepMeta.GetResourceParameters(dir, "commonPipelineEnvironment"), "stage1", "step1", stepAliases)
assert.Equal(t, nil, err, "error occured but none expected")
@@ -217,7 +223,7 @@ steps:
c.openFile = customDefaultsOpenFileMock
stepConfig, err := c.GetStepConfig(nil, "", ioutil.NopCloser(strings.NewReader(testConfDefaults)), nil, StepFilters{General: []string{"p0"}}, nil, nil, "stage1", "step1", []Alias{})
stepConfig, err := c.GetStepConfig(nil, "", ioutil.NopCloser(strings.NewReader(testConfDefaults)), nil, StepFilters{General: []string{"p0"}}, nil, nil, nil, "stage1", "step1", []Alias{})
assert.NoError(t, err, "Error occured but no error expected")
assert.Equal(t, "p0_custom_default", stepConfig.Config["p0"])
@@ -230,7 +236,7 @@ steps:
stepParams := []StepParameters{StepParameters{Name: "p0", Scope: []string{"GENERAL"}, Type: "string", Default: "p0_step_default", Aliases: []Alias{{Name: "p0_alias"}}}}
testConf := "general:\n p1: p1_conf"
stepConfig, err := c.GetStepConfig(nil, "", ioutil.NopCloser(strings.NewReader(testConf)), nil, StepFilters{General: []string{"p0", "p1"}}, stepParams, nil, "stage1", "step1", []Alias{})
stepConfig, err := c.GetStepConfig(nil, "", ioutil.NopCloser(strings.NewReader(testConf)), nil, StepFilters{General: []string{"p0", "p1"}}, stepParams, nil, nil, "stage1", "step1", []Alias{})
assert.NoError(t, err, "Error occured but no error expected")
assert.Equal(t, "p0_step_default", stepConfig.Config["p0"])
@@ -240,7 +246,7 @@ steps:
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, StepFilters{}, []StepParameters{}, nil, "stage1", "step1", []Alias{})
_, err := c.GetStepConfig(nil, "", myConfig, nil, StepFilters{}, []StepParameters{}, nil, nil, "stage1", "step1", []Alias{})
assert.EqualError(t, err, "failed to parse custom pipeline configuration: error unmarshalling \"invalid config\": error unmarshaling JSON: json: cannot unmarshal string into Go value of type config.Config", "default error expected")
})
@@ -248,7 +254,7 @@ steps:
var c Config
myConfig := ioutil.NopCloser(strings.NewReader(""))
myDefaults := []io.ReadCloser{ioutil.NopCloser(strings.NewReader("invalid defaults"))}
_, err := c.GetStepConfig(nil, "", myConfig, myDefaults, StepFilters{}, []StepParameters{}, nil, "stage1", "step1", []Alias{})
_, err := c.GetStepConfig(nil, "", myConfig, myDefaults, StepFilters{}, []StepParameters{}, nil, nil, "stage1", "step1", []Alias{})
assert.EqualError(t, err, "failed to read default configuration: error unmarshalling \"invalid defaults\": error unmarshaling JSON: json: cannot unmarshal string into Go value of type config.Config", "default error expected")
})
@@ -338,11 +344,19 @@ func TestApplyAliasConfig(t *testing.T) {
Name: "p9",
},
}
s := []StepSecrets{
{
Name: "s1",
Aliases: []Alias{
{Name: "s1_alias"},
},
},
}
filters := StepFilters{
General: []string{"p1", "p2"},
Stages: []string{"p4"},
Steps: []string{"p6", "p8"},
Steps: []string{"p6", "p8", "s1"},
}
c := Config{
@@ -371,13 +385,14 @@ func TestApplyAliasConfig(t *testing.T) {
"p7": "p7_stepAlias",
"p8_alias": "p8_stepAlias",
"p9": "p9_stepAlias",
"s1_alias": "s1_stepAlias",
},
},
}
stepAliases := []Alias{{Name: "stepAlias1"}}
c.ApplyAliasConfig(p, filters, "stage1", "step1", stepAliases)
c.ApplyAliasConfig(p, s, filters, "stage1", "step1", stepAliases)
t.Run("Global", func(t *testing.T) {
assert.Nil(t, c.General["p0"])
@@ -396,6 +411,7 @@ func TestApplyAliasConfig(t *testing.T) {
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"])
})
}
+7 -6
View File
@@ -79,9 +79,10 @@ type StepResources struct {
// StepSecrets defines the secrets to be provided by the step context, e.g. Jenkins pipeline
type StepSecrets struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Type string `json:"type,omitempty"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Type string `json:"type,omitempty"`
Aliases []Alias `json:"aliases,omitempty"`
}
// StepOutputs defines the outputs of a step step, typically one or multiple resources
@@ -101,12 +102,12 @@ type Container struct {
Shell string `json:"shell"`
WorkingDir string `json:"workingDir"`
Conditions []Condition `json:"conditions,omitempty"`
Options []Option `json:"options,omitempt"`
Options []Option `json:"options,omitempty"`
//VolumeMounts []VolumeMount `json:"volumeMounts,omitempty"`
}
// ToDo: Add the missing Volumes part to enable the volume mount completly
// VolumeMount defines an mount path
// ToDo: Add the missing Volumes part to enable the volume mount completely
// VolumeMount defines a mount path
// type VolumeMount struct {
// MountPath string `json:"mountPath"`
// Name string `json:"name"`