diff --git a/pkg/apis/pipeline/v1alpha1/resource_paths.go b/pkg/apis/pipeline/v1alpha1/resource_paths.go new file mode 100644 index 00000000000..ddeef1c3567 --- /dev/null +++ b/pkg/apis/pipeline/v1alpha1/resource_paths.go @@ -0,0 +1,37 @@ +/* + Copyright 2019 The Tekton Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package v1alpha1 + +import "path/filepath" + +// InputResourcePath returns the path where the given input resource +// will get mounted in a Pod +func InputResourcePath(r ResourceDeclaration) string { + return path("/workspace", r) +} + +// OutputResourcePath returns the path to the output resouce in a Pod +func OutputResourcePath(r ResourceDeclaration) string { + return path("/workspace/output", r) +} + +func path(root string, r ResourceDeclaration) string { + if r.TargetPath != "" { + return filepath.Join("/workspace", r.TargetPath) + } + return filepath.Join(root, r.Name) +} diff --git a/pkg/apis/pipeline/v1alpha1/resource_paths_test.go b/pkg/apis/pipeline/v1alpha1/resource_paths_test.go new file mode 100644 index 00000000000..0fa0a0112a4 --- /dev/null +++ b/pkg/apis/pipeline/v1alpha1/resource_paths_test.go @@ -0,0 +1,81 @@ +/* + Copyright 2019 The Tekton Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package v1alpha1_test + +import ( + "testing" + + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" +) + +func TestInputResourcePath(t *testing.T) { + tcs := []struct { + name string + resource v1alpha1.ResourceDeclaration + expected string + }{{ + name: "default_path", + resource: v1alpha1.ResourceDeclaration{ + Name: "foo", + }, + expected: "/workspace/foo", + }, { + name: "with target path", + resource: v1alpha1.ResourceDeclaration{ + Name: "foo", + TargetPath: "bar", + }, + expected: "/workspace/bar", + }} + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + if actual := v1alpha1.InputResourcePath(tc.resource); actual != tc.expected { + t.Errorf("Unexpected input resource path: %s", actual) + } + }) + } +} + +func TestOutputResourcePath(t *testing.T) { + tcs := []struct { + name string + resource v1alpha1.ResourceDeclaration + expected string + }{{ + name: "default_path", + resource: v1alpha1.ResourceDeclaration{ + Name: "foo", + }, + expected: "/workspace/output/foo", + }, { + name: "with target path", + resource: v1alpha1.ResourceDeclaration{ + Name: "foo", + TargetPath: "bar", + }, + expected: "/workspace/bar", + }} + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + if actual := v1alpha1.OutputResourcePath(tc.resource); actual != tc.expected { + t.Errorf("Unexpected output resource path: %s", actual) + } + }) + } +} diff --git a/pkg/reconciler/pipelinerun/resources/conditionresolution.go b/pkg/reconciler/pipelinerun/resources/conditionresolution.go index 5b977fa1797..eeafee3a8ff 100644 --- a/pkg/reconciler/pipelinerun/resources/conditionresolution.go +++ b/pkg/reconciler/pipelinerun/resources/conditionresolution.go @@ -110,7 +110,7 @@ func (rcc *ResolvedConditionCheck) ConditionToTaskSpec() (*v1alpha1.TaskSpec, er // convert param strings of type ${params.x} to ${inputs.params.x} convertParamTemplates(&t.Steps[0], rcc.Condition.Spec.Params) // convert resource strings of type ${resources.name.key} to ${inputs.resources.name.key} - err := convertResourceTemplateStrings(&t.Steps[0], rcc.ResolvedResources, rcc.Condition.Spec.Resources) + err := ApplyResourceSubstitution(&t.Steps[0], rcc.ResolvedResources, rcc.Condition.Spec.Resources) if err != nil { return nil, xerrors.Errorf("Failed to replace resource template strings %w", err) @@ -130,9 +130,9 @@ func convertParamTemplates(step *v1alpha1.Step, params []v1alpha1.ParamSpec) { v1alpha1.ApplyStepReplacements(step, replacements, map[string][]string{}) } -// Prepends inputs. to all resource template strings so that they can be replaced by -// taskrun variable substitution e.g. ${resources.name.key} to ${inputs.resources.name.key} -func convertResourceTemplateStrings(step *v1alpha1.Step, resolvedResources map[string]*v1alpha1.PipelineResource, conditionResources []v1alpha1.ResourceDeclaration) error { +// ApplyResources applies the substitution from values in resources which are referenced +// in spec as subitems of the replacementStr. +func ApplyResourceSubstitution(step *v1alpha1.Step, resolvedResources map[string]*v1alpha1.PipelineResource, conditionResources []v1alpha1.ResourceDeclaration) error { replacements := make(map[string]string) for _, cr := range conditionResources { if rSpec, ok := resolvedResources[cr.Name]; ok { @@ -140,9 +140,10 @@ func convertResourceTemplateStrings(step *v1alpha1.Step, resolvedResources map[s if err != nil { return xerrors.Errorf("Error trying to create resource: %w", err) } - for replaceKeys := range r.Replacements() { - replacements[fmt.Sprintf("resources.%s.%s", cr.Name, replaceKeys)] = fmt.Sprintf("$(inputs.resources.%s.%s)", cr.Name, replaceKeys) + for k, v := range r.Replacements() { + replacements[fmt.Sprintf("resources.%s.%s", cr.Name, k)] = v } + replacements[fmt.Sprintf("resources.%s.path", cr.Name)] = v1alpha1.InputResourcePath(cr) } } v1alpha1.ApplyStepReplacements(step, replacements, map[string][]string{}) diff --git a/pkg/reconciler/pipelinerun/resources/conditionresolution_test.go b/pkg/reconciler/pipelinerun/resources/conditionresolution_test.go index 3826ac36c8f..997ba148a05 100644 --- a/pkg/reconciler/pipelinerun/resources/conditionresolution_test.go +++ b/pkg/reconciler/pipelinerun/resources/conditionresolution_test.go @@ -216,8 +216,8 @@ func TestResolvedConditionCheck_ConditionToTaskSpec(t *testing.T) { }, { name: "with-input-params", cond: tb.Condition("bar", "foo", tb.ConditionSpec( - tb.ConditionSpecCheck("${params.name}", "${params.img}", - tb.WorkingDir("${params.not.replaced}")), + tb.ConditionSpecCheck("$(params.name)", "$(params.img)", + tb.WorkingDir("$(params.not.replaced)")), tb.ConditionParamSpec("name", v1alpha1.ParamTypeString), tb.ConditionParamSpec("img", v1alpha1.ParamTypeString), )), @@ -232,16 +232,16 @@ func TestResolvedConditionCheck_ConditionToTaskSpec(t *testing.T) { }}, }, Steps: []v1alpha1.Step{{Container: corev1.Container{ - Name: "${inputs.params.name}", - Image: "${inputs.params.img}", - WorkingDir: "${params.not.replaced}", + Name: "$(inputs.params.name)", + Image: "$(inputs.params.img)", + WorkingDir: "$(params.not.replaced)", }}}, }, }, { name: "with-resources", cond: tb.Condition("bar", "foo", tb.ConditionSpec( tb.ConditionSpecCheck("name", "ubuntu", - tb.Args("${resources.git-resource.revision}")), + tb.Args("$(resources.git-resource.revision)")), tb.ConditionResource("git-resource", v1alpha1.PipelineResourceTypeGit), )), resolvedResources: map[string]*v1alpha1.PipelineResource{ @@ -261,7 +261,7 @@ func TestResolvedConditionCheck_ConditionToTaskSpec(t *testing.T) { Steps: []v1alpha1.Step{{Container: corev1.Container{ Name: "name", Image: "ubuntu", - Args: []string{"${inputs.resources.git-resource.revision}"}, + Args: []string{"master"}, }}}, }, }} diff --git a/pkg/reconciler/taskrun/resources/apply.go b/pkg/reconciler/taskrun/resources/apply.go index 456763eb3cc..730fb9c519d 100644 --- a/pkg/reconciler/taskrun/resources/apply.go +++ b/pkg/reconciler/taskrun/resources/apply.go @@ -18,7 +18,6 @@ package resources import ( "fmt" - "path/filepath" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" ) @@ -67,25 +66,18 @@ func ApplyResources(spec *v1alpha1.TaskSpec, resolvedResources map[string]v1alph // We always add replacements for 'path' if spec.Inputs != nil { for _, r := range spec.Inputs.Resources { - replacements[fmt.Sprintf("inputs.resources.%s.path", r.Name)] = path("/workspace", r) + replacements[fmt.Sprintf("inputs.resources.%s.path", r.Name)] = v1alpha1.InputResourcePath(r.ResourceDeclaration) } } if spec.Outputs != nil { for _, r := range spec.Outputs.Resources { - replacements[fmt.Sprintf("outputs.resources.%s.path", r.Name)] = path("/workspace/output", r) + replacements[fmt.Sprintf("outputs.resources.%s.path", r.Name)] = v1alpha1.OutputResourcePath(r.ResourceDeclaration) } } return ApplyReplacements(spec, replacements, map[string][]string{}) } -func path(root string, r v1alpha1.TaskResource) string { - if r.TargetPath != "" { - return filepath.Join("/workspace", r.TargetPath) - } - return filepath.Join(root, r.Name) -} - // ApplyReplacements replaces placeholders for declared parameters with the specified replacements. func ApplyReplacements(spec *v1alpha1.TaskSpec, stringReplacements map[string]string, arrayReplacements map[string][]string) *v1alpha1.TaskSpec { spec = spec.DeepCopy()