Skip to content

Commit d1b280e

Browse files
authored
fix: skip validate dynamic templateref (argoproj#14850)
Signed-off-by: Tianchu Zhao <evantczhao@gmail.com>
1 parent 2ecd971 commit d1b280e

3 files changed

Lines changed: 174 additions & 0 deletions

File tree

workflow/validate/validate.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,10 @@ func (tctx *templateValidationCtx) validateTemplateHolder(ctx context.Context, t
574574
tmplCtx, resolvedTmpl, _, err := tmplCtx.ResolveTemplate(ctx, tmplHolder)
575575
if err != nil {
576576
if argoerr, ok := err.(errors.ArgoError); ok && argoerr.Code() == errors.CodeNotFound {
577+
if tmplRef != nil && strings.Contains(tmplRef.Template, "placeholder") {
578+
// placeholder indicate this is a dynamic template, skip validation
579+
return nil, nil
580+
}
577581
if tmplRef != nil {
578582
return nil, errors.Errorf(errors.CodeBadRequest, "template reference %s.%s not found", tmplRef.Name, tmplRef.Template)
579583
}

workflow/validate/validate_dag_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/stretchr/testify/require"
77

8+
wfv1 "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
89
"github.com/argoproj/argo-workflows/v3/util/logging"
910
)
1011

@@ -1124,3 +1125,102 @@ func TestFailDAGArgParamValueFromPathInTask(t *testing.T) {
11241125
err := validate(logging.TestContext(t.Context()), failDagArgParamValueFromPathInTask)
11251126
require.ErrorContains(t, err, "valueFrom only allows: default, configMapKeyRef and supplied")
11261127
}
1128+
1129+
var dagWithItemTemplateRefTmpl = `
1130+
apiVersion: argoproj.io/v1alpha1
1131+
kind: WorkflowTemplate
1132+
metadata:
1133+
name: 363-test-tmp
1134+
namespace: default
1135+
spec:
1136+
templates:
1137+
- name: 363-test-tmp
1138+
nodeSelector:
1139+
nodegroup: arm-spot
1140+
inputs:
1141+
parameters:
1142+
- name: path
1143+
- name: service
1144+
- name: build_arg
1145+
- name: run_on
1146+
- name: arch
1147+
- name: docker_org
1148+
container:
1149+
image: alpine
1150+
command:
1151+
- sh
1152+
- -c
1153+
- |
1154+
echo "path: {{inputs.parameters.path}}"
1155+
echo "service: {{inputs.parameters.service}}"
1156+
echo "build_arg: {{inputs.parameters.build_arg}}"
1157+
echo "run_on: {{inputs.parameters.run_on}}"
1158+
echo "arch: {{inputs.parameters.arch}}"
1159+
echo "docker_org: {{inputs.parameters.docker_org}}"
1160+
`
1161+
1162+
var dagWithItemTemplateRefWf = `
1163+
apiVersion: argoproj.io/v1alpha1
1164+
kind: Workflow
1165+
metadata:
1166+
generateName: 363-test-
1167+
namespace: default
1168+
spec:
1169+
activeDeadlineSeconds: 10800
1170+
entrypoint: main
1171+
serviceAccountName: ci
1172+
1173+
templates:
1174+
- name: main
1175+
dag:
1176+
tasks:
1177+
- name: withitems
1178+
templateRef:
1179+
name: 363-test-tmp
1180+
template: 363-test-tmp
1181+
arguments:
1182+
parameters:
1183+
- name: path
1184+
value: "{{item.path}}"
1185+
- name: service
1186+
value: "{{item.service}}"
1187+
- name: build_arg
1188+
value: "{{item.arg}}"
1189+
- name: run_on
1190+
value: "{{item.run_on}}"
1191+
- name: arch
1192+
value: "{{item.arch}}"
1193+
- name: docker_org
1194+
value: "{{item.docker_org}}"
1195+
withItems:
1196+
- {
1197+
path: "services",
1198+
service: "id",
1199+
arg: "",
1200+
run_on: "arm-spot",
1201+
arch: "arm64",
1202+
docker_org: "pipekit13",
1203+
}
1204+
- {
1205+
path: "services",
1206+
service: "events-handler",
1207+
arg: "",
1208+
run_on: "arm-spot",
1209+
arch: "arm64",
1210+
docker_org: "pipekit13",
1211+
}
1212+
`
1213+
1214+
func TestDagWithItemTemplateRefTmpl(t *testing.T) {
1215+
ctx := logging.TestContext(t.Context())
1216+
wf := wfv1.MustUnmarshalWorkflow(dagWithItemTemplateRefWf)
1217+
wftmpl := wfv1.MustUnmarshalWorkflowTemplate(dagWithItemTemplateRefTmpl)
1218+
1219+
err := createWorkflowTemplate(ctx, wftmpl)
1220+
require.NoError(t, err)
1221+
1222+
err = ValidateWorkflow(ctx, wftmplGetter, cwftmplGetter, wf, nil, ValidateOpts{})
1223+
require.NoError(t, err)
1224+
1225+
_ = deleteWorkflowTemplate(ctx, wftmpl.Name)
1226+
}

workflow/validate/validate_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3365,3 +3365,73 @@ func TestShouldCheckValidationToSpacedParameters(t *testing.T) {
33653365
// Do not allow leading or trailing spaces in parameters
33663366
require.ErrorContains(t, err, "failed to resolve {{ workflow.thisdoesnotexist }}")
33673367
}
3368+
3369+
var dynamicWorkflowTemplateARefB = `
3370+
apiVersion: argoproj.io/v1alpha1
3371+
kind: WorkflowTemplate
3372+
metadata:
3373+
name: workflow-template-a
3374+
spec:
3375+
templates:
3376+
- name: template-a
3377+
inputs:
3378+
parameters:
3379+
- name: message
3380+
steps:
3381+
- - name: step-a
3382+
templateRef:
3383+
name: workflow-template-b
3384+
template: "{{ inputs.parameters.message }}"
3385+
`
3386+
3387+
var dynamicWorkflowTemplateRefB = `
3388+
apiVersion: argoproj.io/v1alpha1
3389+
kind: WorkflowTemplate
3390+
metadata:
3391+
name: workflow-template-b
3392+
spec:
3393+
templates:
3394+
- name: template-b
3395+
container:
3396+
image: docker/whalesay
3397+
command: [cowsay]
3398+
args: ["hello from template"]
3399+
`
3400+
3401+
var dynamicTemplateRefWorkflow = `
3402+
apiVersion: argoproj.io/v1alpha1
3403+
kind: Workflow
3404+
metadata:
3405+
generateName: dynamic-workflow-
3406+
spec:
3407+
entrypoint: whalesay
3408+
templates:
3409+
- name: whalesay
3410+
steps:
3411+
- - name: whalesay
3412+
templateRef:
3413+
name: workflow-template-a
3414+
template: template-a
3415+
arguments:
3416+
parameters:
3417+
- name: message
3418+
value: "template-b"
3419+
`
3420+
3421+
func TestDynamicWorkflowTemplateRef(t *testing.T) {
3422+
ctx := logging.TestContext(t.Context())
3423+
wf := wfv1.MustUnmarshalWorkflow(dynamicTemplateRefWorkflow)
3424+
wftmplA := wfv1.MustUnmarshalWorkflowTemplate(dynamicWorkflowTemplateARefB)
3425+
wftmplB := wfv1.MustUnmarshalWorkflowTemplate(dynamicWorkflowTemplateRefB)
3426+
3427+
err := createWorkflowTemplate(ctx, wftmplA)
3428+
require.NoError(t, err)
3429+
err = createWorkflowTemplate(ctx, wftmplB)
3430+
require.NoError(t, err)
3431+
3432+
err = ValidateWorkflow(ctx, wftmplGetter, cwftmplGetter, wf, nil, ValidateOpts{})
3433+
require.NoError(t, err)
3434+
3435+
_ = deleteWorkflowTemplate(ctx, wftmplA.Name)
3436+
_ = deleteWorkflowTemplate(ctx, wftmplB.Name)
3437+
}

0 commit comments

Comments
 (0)