Skip to content

Commit

Permalink
Enable Param Substitution in StepAction resolver reference params
Browse files Browse the repository at this point in the history
This PR fixes #7865.
  • Loading branch information
chitrangpatel authored and tekton-robot committed Apr 12, 2024
1 parent 969a98f commit b70d30f
Show file tree
Hide file tree
Showing 3 changed files with 307 additions and 4 deletions.
13 changes: 10 additions & 3 deletions examples/v1/taskruns/alpha/stepaction-git-resolver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@ kind: TaskRun
metadata:
generateName: step-action-run-
spec:
params:
- name: pathInRepo
value: basic_step.yaml
- name: revision
value: main
- name: repoUrl
value: https://github.com/chitrangpatel/repo1M.git
TaskSpec:
steps:
- name: action-runner
ref:
resolver: git
params:
- name: url
value: https://github.com/chitrangpatel/repo1M.git
value: $(params.repoUrl)
- name: revision
value: main
value: $(params.revision)
- name: pathInRepo
value: basic_step.yaml
value: $(params.pathInRepo)
43 changes: 42 additions & 1 deletion pkg/reconciler/taskrun/resources/taskref.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ func GetStepActionFunc(tekton clientset.Interface, k8s kubernetes.Interface, req
// Return an inline function that implements GetStepAction by calling Resolver.Get with the specified StepAction type and
// casting it to a StepAction.
return func(ctx context.Context, name string) (*v1alpha1.StepAction, *v1.RefSource, error) {
// TODO(#7259): support params replacements for resolver params
// Perform params replacements for StepAction resolver params
ApplyParameterSubstitutionInResolverParams(tr, step)
resolver := resolution.NewResolver(requester, tr, string(step.Ref.Resolver), trName, namespace, step.Ref.Params)
return resolveStepAction(ctx, resolver, name, namespace, k8s, tekton)
}
Expand All @@ -146,6 +147,46 @@ func GetStepActionFunc(tekton clientset.Interface, k8s kubernetes.Interface, req
return local.GetStepAction
}

// ApplyParameterSubstitutionInResolverParams applies parameter substitutions in resolver params for Step Ref.
func ApplyParameterSubstitutionInResolverParams(tr *v1.TaskRun, step *v1.Step) {
stringReplacements := make(map[string]string)
arrayReplacements := make(map[string][]string)
objectReplacements := make(map[string]map[string]string)
if tr.Spec.TaskSpec != nil {
defaultSR, defaultAR, defaultOR := replacementsFromDefaultParams(tr.Spec.TaskSpec.Params)
stringReplacements, arrayReplacements, objectReplacements = extendReplacements(stringReplacements, arrayReplacements, objectReplacements, defaultSR, defaultAR, defaultOR)
}
paramSR, paramAR, paramOR := replacementsFromParams(tr.Spec.Params)
stringReplacements, arrayReplacements, objectReplacements = extendReplacements(stringReplacements, arrayReplacements, objectReplacements, paramSR, paramAR, paramOR)
step.Ref.Params = step.Ref.Params.ReplaceVariables(stringReplacements, arrayReplacements, objectReplacements)
}

func extendReplacements(stringReplacements map[string]string, arrayReplacements map[string][]string, objectReplacements map[string]map[string]string, stringReplacementsToAdd map[string]string, arrayReplacementsToAdd map[string][]string, objectReplacementsToAdd map[string]map[string]string) (map[string]string, map[string][]string, map[string]map[string]string) {
for k, v := range stringReplacementsToAdd {
stringReplacements[k] = v
}
for k, v := range arrayReplacementsToAdd {
arrayReplacements[k] = v
}
objectReplacements = extendObjectReplacements(objectReplacements, objectReplacementsToAdd)
return stringReplacements, arrayReplacements, objectReplacements
}

func extendObjectReplacements(objectReplacements map[string]map[string]string, objectReplacementsToAdd map[string]map[string]string) map[string]map[string]string {
for k, v := range objectReplacementsToAdd {
for key, val := range v {
if objectReplacements != nil {
if objectReplacements[k] != nil {
objectReplacements[k][key] = val
} else {
objectReplacements[k] = v
}
}
}
}
return objectReplacements
}

// resolveTask accepts an impl of remote.Resolver and attempts to
// fetch a task with given name and verify the v1beta1 task if trusted resources is enabled.
// An error is returned if the remoteresource doesn't work
Expand Down
255 changes: 255 additions & 0 deletions pkg/reconciler/taskrun/resources/taskref_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,261 @@ func TestLocalTaskRef(t *testing.T) {
}
}

func TestStepActionResolverParamReplacements(t *testing.T) {
testcases := []struct {
name string
namespace string
taskrun *v1.TaskRun
want *v1.Step
}{{
name: "default taskspec parms",
namespace: "default",
taskrun: &v1.TaskRun{
ObjectMeta: metav1.ObjectMeta{Name: "some-tr"},
Spec: v1.TaskRunSpec{
TaskSpec: &v1.TaskSpec{
Params: []v1.ParamSpec{{
Name: "resolver-param",
Default: v1.NewStructuredValues("foo/bar"),
}},
Steps: []v1.Step{{
Ref: &v1.Ref{
ResolverRef: v1.ResolverRef{
Resolver: "git",
Params: []v1.Param{{
Name: "pathInRepo",
Value: *v1.NewStructuredValues("$(params.resolver-param)"),
}},
},
},
}},
},
},
},
want: &v1.Step{
Ref: &v1.Ref{
ResolverRef: v1.ResolverRef{
Resolver: "git",
Params: []v1.Param{{
Name: "pathInRepo",
Value: *v1.NewStructuredValues("foo/bar"),
}},
},
},
},
}, {
name: "default taskspec array parms",
namespace: "default",
taskrun: &v1.TaskRun{
ObjectMeta: metav1.ObjectMeta{Name: "some-tr"},
Spec: v1.TaskRunSpec{
TaskSpec: &v1.TaskSpec{
Params: []v1.ParamSpec{{
Name: "resolver-param",
Type: v1.ParamTypeArray,
Default: v1.NewStructuredValues("foo/bar", "bar/baz"),
}},
Steps: []v1.Step{{
Ref: &v1.Ref{
ResolverRef: v1.ResolverRef{
Resolver: "git",
Params: []v1.Param{{
Name: "pathInRepo",
Value: *v1.NewStructuredValues("$(params.resolver-param[0])"),
}},
},
},
}},
},
},
},
want: &v1.Step{
Ref: &v1.Ref{
ResolverRef: v1.ResolverRef{
Resolver: "git",
Params: []v1.Param{{
Name: "pathInRepo",
Value: *v1.NewStructuredValues("foo/bar"),
}},
},
},
},
}, {
name: "default taskspec object parms",
namespace: "default",
taskrun: &v1.TaskRun{
ObjectMeta: metav1.ObjectMeta{Name: "some-tr"},
Spec: v1.TaskRunSpec{
TaskSpec: &v1.TaskSpec{
Params: []v1.ParamSpec{{
Name: "resolver-param",
Type: v1.ParamTypeObject,
Properties: map[string]v1.PropertySpec{
"key1": {},
},
Default: v1.NewObject(map[string]string{
"key1": "foo/bar",
}),
}},
Steps: []v1.Step{{
Ref: &v1.Ref{
ResolverRef: v1.ResolverRef{
Resolver: "git",
Params: []v1.Param{{
Name: "pathInRepo",
Value: *v1.NewStructuredValues("$(params.resolver-param.key1)"),
}},
},
},
}},
},
},
},
want: &v1.Step{
Ref: &v1.Ref{
ResolverRef: v1.ResolverRef{
Resolver: "git",
Params: []v1.Param{{
Name: "pathInRepo",
Value: *v1.NewStructuredValues("foo/bar"),
}},
},
},
},
}, {
name: "default and taskrun params",
namespace: "default",
taskrun: &v1.TaskRun{
ObjectMeta: metav1.ObjectMeta{Name: "some-tr"},
Spec: v1.TaskRunSpec{
Params: []v1.Param{{
Name: "resolver-param",
Value: *v1.NewStructuredValues("foo/bar/baz"),
}},
TaskSpec: &v1.TaskSpec{
Params: []v1.ParamSpec{{
Name: "resolver-param",
Default: v1.NewStructuredValues("foo/bar"),
}},
Steps: []v1.Step{{
Ref: &v1.Ref{
ResolverRef: v1.ResolverRef{
Resolver: "git",
Params: []v1.Param{{
Name: "pathInRepo",
Value: *v1.NewStructuredValues("$(params.resolver-param)"),
}},
},
},
}},
},
},
},
want: &v1.Step{
Ref: &v1.Ref{
ResolverRef: v1.ResolverRef{
Resolver: "git",
Params: []v1.Param{{
Name: "pathInRepo",
Value: *v1.NewStructuredValues("foo/bar/baz"),
}},
},
},
},
}, {
name: "default and taskrun object parms",
namespace: "default",
taskrun: &v1.TaskRun{
ObjectMeta: metav1.ObjectMeta{Name: "some-tr"},
Spec: v1.TaskRunSpec{
Params: v1.Params{{
Name: "resolver-param",
Value: *v1.NewObject(map[string]string{"key1": "foo/bar/baz"}),
}},
TaskSpec: &v1.TaskSpec{
Params: []v1.ParamSpec{{
Name: "resolver-param",
Type: v1.ParamTypeObject,
Properties: map[string]v1.PropertySpec{
"key1": {},
},
Default: v1.NewObject(map[string]string{
"key1": "foo/bar",
}),
}},
Steps: []v1.Step{{
Ref: &v1.Ref{
ResolverRef: v1.ResolverRef{
Resolver: "git",
Params: []v1.Param{{
Name: "pathInRepo",
Value: *v1.NewStructuredValues("$(params.resolver-param.key1)"),
}},
},
},
}},
},
},
},
want: &v1.Step{
Ref: &v1.Ref{
ResolverRef: v1.ResolverRef{
Resolver: "git",
Params: []v1.Param{{
Name: "pathInRepo",
Value: *v1.NewStructuredValues("foo/bar/baz"),
}},
},
},
},
}, {
name: "taskrun params",
namespace: "default",
taskrun: &v1.TaskRun{
ObjectMeta: metav1.ObjectMeta{Name: "some-tr"},
Spec: v1.TaskRunSpec{
Params: []v1.Param{{
Name: "resolver-param",
Value: *v1.NewStructuredValues("foo/bar/baz"),
}},
TaskSpec: &v1.TaskSpec{
Steps: []v1.Step{{
Ref: &v1.Ref{
ResolverRef: v1.ResolverRef{
Resolver: "git",
Params: []v1.Param{{
Name: "pathInRepo",
Value: *v1.NewStructuredValues("$(params.resolver-param)"),
}},
},
},
}},
},
},
},
want: &v1.Step{
Ref: &v1.Ref{
ResolverRef: v1.ResolverRef{
Resolver: "git",
Params: []v1.Param{{
Name: "pathInRepo",
Value: *v1.NewStructuredValues("foo/bar/baz"),
}},
},
},
},
}}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
step := &tc.taskrun.Spec.TaskSpec.Steps[0]
resources.ApplyParameterSubstitutionInResolverParams(tc.taskrun, step)
if d := cmp.Diff(tc.want, step); tc.want != nil && d != "" {
t.Error(diff.PrintWantGot(d))
}
})
}
}

func TestStepActionRef(t *testing.T) {
testcases := []struct {
name string
Expand Down

0 comments on commit b70d30f

Please sign in to comment.