-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: incorrect templating not producing error #765
Changes from 1 commit
8f5dcbc
e818db1
454f4c9
d8ef177
93e68d0
1b10032
43eaa8b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,67 +132,110 @@ func validateInputParameterVariables(steps []corev1.Container, inputs *Inputs) * | |
parameterNames[p.Name] = struct{}{} | ||
} | ||
} | ||
return validateVariables(steps, "params", parameterNames) | ||
return validateVariables(steps, "params", "inputs.", parameterNames) | ||
} | ||
|
||
func validateResourceVariables(steps []corev1.Container, inputs *Inputs, outputs *Outputs) *apis.FieldError { | ||
resourceNames := map[string]struct{}{} | ||
inputVars, err := getInputResourceVariables(inputs) | ||
if err != nil { | ||
return err | ||
} | ||
outputVars, err := getOutputResourceVariables(outputs) | ||
if err != nil { | ||
return err | ||
} | ||
err = validateVariables(steps, "resources", "inputs.", inputVars) | ||
if err != nil { | ||
return err | ||
} | ||
return validateVariables(steps, "resources", "outputs.", outputVars) | ||
} | ||
|
||
func getInputResourceVariables(inputs *Inputs) (map[string]struct{}, *apis.FieldError) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm curious why you chose to use two separate functions for input & output here - it seems like it would be possible to write a single function to handle both with a signature like: func getResourceVariables(resources []TaskResource, pathPrefix string) I might be misreading but it looks like the only line of difference between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're totally right! There was plenty of duplicate code there. I went ahead and made these changes. Thanks for the suggestion. |
||
vars := map[string]struct{}{} | ||
if inputs != nil { | ||
for _, r := range inputs.Resources { | ||
resourceNames[r.Name] = struct{}{} | ||
attrs, err := AttributesFromType(r.Type) | ||
if err != nil { | ||
return nil, &apis.FieldError{ | ||
Message: fmt.Sprintf("invalid resource type %s", r.Type), | ||
Paths: []string{"taskspec.inputs.resources." + r.Name}, | ||
Details: err.Error(), | ||
} | ||
} | ||
for _, a := range attrs { | ||
rv := r.Name + "." + a | ||
vars[rv] = struct{}{} | ||
} | ||
} | ||
} | ||
return vars, nil | ||
} | ||
|
||
func getOutputResourceVariables(outputs *Outputs) (map[string]struct{}, *apis.FieldError) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think it's worth having unit tests for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This changed slightly and has been reduced to one function, |
||
vars := map[string]struct{}{} | ||
if outputs != nil { | ||
for _, r := range outputs.Resources { | ||
resourceNames[r.Name] = struct{}{} | ||
attrs, err := AttributesFromType(r.Type) | ||
if err != nil { | ||
return nil, &apis.FieldError{ | ||
Message: fmt.Sprintf("invalid resource type %s", r.Type), | ||
Paths: []string{"taskspec.outputs.resources." + r.Name}, | ||
Details: err.Error(), | ||
} | ||
} | ||
for _, a := range attrs { | ||
rv := r.Name + "." + a | ||
vars[rv] = struct{}{} | ||
} | ||
} | ||
} | ||
return validateVariables(steps, "resources", resourceNames) | ||
return vars, nil | ||
} | ||
|
||
func validateVariables(steps []corev1.Container, prefix string, vars map[string]struct{}) *apis.FieldError { | ||
func validateVariables(steps []corev1.Container, prefix, contextPrefix string, vars map[string]struct{}) *apis.FieldError { | ||
for _, step := range steps { | ||
if err := validateTaskVariable("name", step.Name, prefix, vars); err != nil { | ||
if err := validateTaskVariable("name", step.Name, prefix, contextPrefix, vars); err != nil { | ||
return err | ||
} | ||
if err := validateTaskVariable("image", step.Image, prefix, vars); err != nil { | ||
if err := validateTaskVariable("image", step.Image, prefix, contextPrefix, vars); err != nil { | ||
return err | ||
} | ||
if err := validateTaskVariable("workingDir", step.WorkingDir, prefix, vars); err != nil { | ||
if err := validateTaskVariable("workingDir", step.WorkingDir, prefix, contextPrefix, vars); err != nil { | ||
return err | ||
} | ||
for i, cmd := range step.Command { | ||
if err := validateTaskVariable(fmt.Sprintf("command[%d]", i), cmd, prefix, vars); err != nil { | ||
if err := validateTaskVariable(fmt.Sprintf("command[%d]", i), cmd, prefix, contextPrefix, vars); err != nil { | ||
return err | ||
} | ||
} | ||
for i, arg := range step.Args { | ||
if err := validateTaskVariable(fmt.Sprintf("arg[%d]", i), arg, prefix, vars); err != nil { | ||
if err := validateTaskVariable(fmt.Sprintf("arg[%d]", i), arg, prefix, contextPrefix, vars); err != nil { | ||
return err | ||
} | ||
} | ||
for _, env := range step.Env { | ||
if err := validateTaskVariable(fmt.Sprintf("env[%s]", env.Name), env.Value, prefix, vars); err != nil { | ||
if err := validateTaskVariable(fmt.Sprintf("env[%s]", env.Name), env.Value, prefix, contextPrefix, vars); err != nil { | ||
return err | ||
} | ||
} | ||
for i, v := range step.VolumeMounts { | ||
if err := validateTaskVariable(fmt.Sprintf("volumeMount[%d].Name", i), v.Name, prefix, vars); err != nil { | ||
if err := validateTaskVariable(fmt.Sprintf("volumeMount[%d].Name", i), v.Name, prefix, contextPrefix, vars); err != nil { | ||
return err | ||
} | ||
if err := validateTaskVariable(fmt.Sprintf("volumeMount[%d].MountPath", i), v.MountPath, prefix, vars); err != nil { | ||
if err := validateTaskVariable(fmt.Sprintf("volumeMount[%d].MountPath", i), v.MountPath, prefix, contextPrefix, vars); err != nil { | ||
return err | ||
} | ||
if err := validateTaskVariable(fmt.Sprintf("volumeMount[%d].SubPath", i), v.SubPath, prefix, vars); err != nil { | ||
if err := validateTaskVariable(fmt.Sprintf("volumeMount[%d].SubPath", i), v.SubPath, prefix, contextPrefix, vars); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func validateTaskVariable(name, value, prefix string, vars map[string]struct{}) *apis.FieldError { | ||
return templating.ValidateVariable(name, value, prefix, "(?:inputs|outputs).", "step", "taskspec.steps", vars) | ||
func validateTaskVariable(name, value, prefix, contextPrefix string, vars map[string]struct{}) *apis.FieldError { | ||
return templating.ValidateVariable(name, value, prefix, contextPrefix, "step", "taskspec.steps", vars) | ||
} | ||
|
||
func checkForDuplicates(resources []TaskResource, path string) *apis.FieldError { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,10 +47,7 @@ func extractVariablesFromString(s, prefix string) ([]string, bool) { | |
vars := make([]string, len(matches)) | ||
for i, match := range matches { | ||
groups := matchGroups(match, re) | ||
// foo -> foo | ||
// foo.bar -> foo | ||
// foo.bar.baz -> foo | ||
vars[i] = strings.SplitN(groups["var"], ".", 2)[0] | ||
vars[i] = groups["var"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm having a hard time figuring out if the logic has remained the same here or has been changed to make an intentional difference to behaviour. Would you mind just quickly describing what this change is? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I intentionally made this change. I added a new test to the templating package which hopefully provides additional insight as to why this was needed. This new test would fail without this change.
Since the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK got it, thankyou, I understand the original issue and this fix more clearly now! |
||
} | ||
return vars, true | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could have some unit tests for
AttributesFromType
too :DThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Glad you recommended this! Ended up running into an issue where this function was not working for one of the types (
PipelineResourceTypeStorage
). I included a fairly kludgy solution and a comment to help illustrate the problem.I do not have more time to look at this at the moment, but will find time soon to try to come up with a more elegant solution.