Skip to content

Commit 78a928f

Browse files
committed
feat: add --ignore-missing option
Signed-off-by: chansuke <moonset20@gmail.com>
1 parent 8793d88 commit 78a928f

File tree

3 files changed

+50
-15
lines changed

3 files changed

+50
-15
lines changed

cmd/argo/commands/lint.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ func NewLintCommand() *cobra.Command {
2424
AllowedValues: []string{"pretty", "simple"},
2525
Value: "pretty",
2626
}
27-
offline bool
27+
offline bool
28+
ignoreMissing bool
2829
)
2930

3031
command := &cobra.Command{
@@ -40,20 +41,21 @@ func NewLintCommand() *cobra.Command {
4041
cat manifests.yaml | argo lint --kinds=workflows,cronworkflows -`,
4142
Args: cobra.MinimumNArgs(1),
4243
RunE: func(cmd *cobra.Command, args []string) error {
43-
return runLint(cmd.Context(), args, offline, lintKinds, output.String(), strict)
44+
return runLint(cmd.Context(), args, offline, lintKinds, output.String(), strict, ignoreMissing)
4445
},
4546
}
4647

4748
command.Flags().StringSliceVar(&lintKinds, "kinds", []string{"all"}, fmt.Sprintf("Which kinds will be linted. Can be: %s", strings.Join(allKinds, "|")))
4849
command.Flags().VarP(&output, "output", "o", "Linting results output format. "+output.Usage())
4950
command.Flags().BoolVar(&strict, "strict", true, "Perform strict workflow validation")
5051
command.Flags().BoolVar(&offline, "offline", false, "perform offline linting. For resources referencing other resources, the references will be resolved from the provided args")
52+
command.Flags().BoolVar(&ignoreMissing, "ignore-missing", false, "ignore errors for missing resources, such as references to non-existent templates")
5153
command.Flags().BoolVar(&common.NoColor, "no-color", false, "Disable colorized output")
5254

5355
return command
5456
}
5557

56-
func runLint(ctx context.Context, args []string, offline bool, lintKinds []string, output string, strict bool) error {
58+
func runLint(ctx context.Context, args []string, offline bool, lintKinds []string, output string, strict bool, ignoreMissing bool) error {
5759
client.Offline = offline
5860
client.OfflineFiles = args
5961
ctx, apiClient, err := client.NewAPIClient(ctx)
@@ -69,6 +71,7 @@ func runLint(ctx context.Context, args []string, offline bool, lintKinds []strin
6971
Strict: strict,
7072
DefaultNamespace: client.Namespace(),
7173
Printer: os.Stdout,
74+
IgnoreMissing: ignoreMissing,
7275
}
7376
return lint.RunLint(ctx, apiClient, lintKinds, output, offline, ops)
7477
}

cmd/argo/commands/lint_test.go

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ import (
1111
"github.com/stretchr/testify/require"
1212
)
1313

14+
// Helper function to call the runLint function with the new ignoreMissing parameter
15+
func testRunLint(ctx context.Context, args []string, offline bool, lintKinds []string, output string, strict bool) error {
16+
// Default ignoreMissing to false for backward compatibility
17+
return runLint(ctx, args, offline, lintKinds, output, strict, false)
18+
}
19+
1420
func Test_OfflineLint(t *testing.T) {
1521
dir := t.TempDir()
1622

@@ -90,7 +96,7 @@ spec:
9096
var fatal bool
9197
logrus.StandardLogger().ExitFunc = func(int) { fatal = true }
9298

93-
err = runLint(context.Background(), []string{workflowPath}, true, nil, "pretty", true)
99+
err = testRunLint(context.Background(), []string{workflowPath}, true, nil, "pretty", true)
94100

95101
require.NoError(t, err)
96102
assert.True(t, fatal, "should have exited")
@@ -101,7 +107,7 @@ spec:
101107
var fatal bool
102108
logrus.StandardLogger().ExitFunc = func(int) { fatal = true }
103109

104-
err = runLint(context.Background(), []string{workflowPath, clusterWftmplPath}, true, nil, "pretty", true)
110+
err = testRunLint(context.Background(), []string{workflowPath, clusterWftmplPath}, true, nil, "pretty", true)
105111

106112
require.NoError(t, err)
107113
assert.True(t, fatal, "should have exited")
@@ -112,7 +118,7 @@ spec:
112118
var fatal bool
113119
logrus.StandardLogger().ExitFunc = func(int) { fatal = true }
114120

115-
err = runLint(context.Background(), []string{workflowPath, wftmplPath}, true, nil, "pretty", true)
121+
err = testRunLint(context.Background(), []string{workflowPath, wftmplPath}, true, nil, "pretty", true)
116122

117123
require.NoError(t, err)
118124
assert.True(t, fatal, "should have exited")
@@ -123,7 +129,7 @@ spec:
123129
var fatal bool
124130
logrus.StandardLogger().ExitFunc = func(int) { fatal = true }
125131

126-
err = runLint(context.Background(), []string{wftmplPath}, true, nil, "pretty", true)
132+
err = testRunLint(context.Background(), []string{wftmplPath}, true, nil, "pretty", true)
127133

128134
require.NoError(t, err)
129135
assert.False(t, fatal, "should not have exited")
@@ -134,7 +140,7 @@ spec:
134140
var fatal bool
135141
logrus.StandardLogger().ExitFunc = func(int) { fatal = true }
136142

137-
err = runLint(context.Background(), []string{clusterWftmplPath}, true, nil, "pretty", true)
143+
err = testRunLint(context.Background(), []string{clusterWftmplPath}, true, nil, "pretty", true)
138144

139145
require.NoError(t, err)
140146
assert.False(t, fatal, "should not have exited")
@@ -145,7 +151,7 @@ spec:
145151
var fatal bool
146152
logrus.StandardLogger().ExitFunc = func(int) { fatal = true }
147153

148-
err = runLint(context.Background(), []string{workflowPath, wftmplPath, clusterWftmplPath}, true, nil, "pretty", true)
154+
err = testRunLint(context.Background(), []string{workflowPath, wftmplPath, clusterWftmplPath}, true, nil, "pretty", true)
149155

150156
require.NoError(t, err)
151157
assert.False(t, fatal, "should not have exited")
@@ -156,7 +162,7 @@ spec:
156162
var fatal bool
157163
logrus.StandardLogger().ExitFunc = func(int) { fatal = true }
158164

159-
err = runLint(context.Background(), []string{dir}, true, nil, "pretty", true)
165+
err = testRunLint(context.Background(), []string{dir}, true, nil, "pretty", true)
160166

161167
require.NoError(t, err)
162168
assert.False(t, fatal, "should not have exited")
@@ -173,7 +179,7 @@ spec:
173179
require.NoError(t, err)
174180
defer func() { _ = os.Stdin.Close() }() // close previously opened path to avoid errors trying to remove the file.
175181

176-
err = runLint(context.Background(), []string{workflowPath, wftmplPath, "-"}, true, nil, "pretty", true)
182+
err = testRunLint(context.Background(), []string{workflowPath, wftmplPath, "-"}, true, nil, "pretty", true)
177183

178184
require.NoError(t, err)
179185
assert.False(t, fatal, "should not have exited")
@@ -205,7 +211,7 @@ spec:
205211
var fatal bool
206212
logrus.StandardLogger().ExitFunc = func(int) { fatal = true }
207213

208-
err = runLint(context.Background(), []string{workflowCaseSensitivePath}, true, nil, "pretty", true)
214+
err = testRunLint(context.Background(), []string{workflowCaseSensitivePath}, true, nil, "pretty", true)
209215

210216
require.NoError(t, err)
211217
assert.True(t, fatal, "should have exited")
@@ -216,7 +222,7 @@ spec:
216222
var fatal bool
217223
logrus.StandardLogger().ExitFunc = func(int) { fatal = true }
218224

219-
err = runLint(context.Background(), []string{workflowCaseSensitivePath}, true, nil, "pretty", false)
225+
err = testRunLint(context.Background(), []string{workflowCaseSensitivePath}, true, nil, "pretty", false)
220226

221227
require.NoError(t, err)
222228
assert.False(t, fatal, "should not have exited")
@@ -276,10 +282,21 @@ spec:
276282
defer func() { logrus.StandardLogger().ExitFunc = nil }()
277283
var fatal bool
278284
logrus.StandardLogger().ExitFunc = func(int) { fatal = true }
279-
err = runLint(context.Background(), []string{workflowMultiDocsPath}, true, nil, "pretty", false)
285+
err = testRunLint(context.Background(), []string{workflowMultiDocsPath}, true, nil, "pretty", false)
280286

281287
require.NoError(t, err)
282288
assert.False(t, fatal, "should not have exited")
283289
})
284290

291+
t.Run("linting a workflow with missing references and ignore-missing flag", func(t *testing.T) {
292+
defer func() { logrus.StandardLogger().ExitFunc = nil }()
293+
var fatal bool
294+
logrus.StandardLogger().ExitFunc = func(int) { fatal = true }
295+
296+
// Use the actual runLint function with ignoreMissing set to true
297+
err = runLint(context.Background(), []string{workflowPath}, true, nil, "pretty", true, true)
298+
299+
require.NoError(t, err)
300+
assert.False(t, fatal, "should not have exited with ignore-missing flag")
301+
})
285302
}

cmd/argo/lint/lint.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type LintOptions struct {
3333
DefaultNamespace string
3434
Formatter Formatter
3535
ServiceClients ServiceClients
36+
IgnoreMissing bool
3637

3738
// Printer if not nil the lint result is written to this writer after each
3839
// file is linted.
@@ -214,7 +215,12 @@ func lintData(ctx context.Context, src string, data []byte, opts *LintOptions) *
214215
}
215216

216217
if err != nil {
217-
res.Errs = append(res.Errs, fmt.Errorf("in %s: %w", objName, err))
218+
// If IgnoreMissing is set, filter out errors related to missing resources
219+
if opts.IgnoreMissing && isMissingResourceError(err) {
220+
log.Debugf("ignoring missing resource error in %s: %v", objName, err)
221+
} else {
222+
res.Errs = append(res.Errs, fmt.Errorf("in %s: %w", objName, err))
223+
}
218224
}
219225
}
220226

@@ -277,6 +283,15 @@ func getObjectName(kind string, obj metav1.Object, objIndex int) string {
277283
return fmt.Sprintf(`"%s" (%s)`, name, kind)
278284
}
279285

286+
// isMissingResourceError checks if the error is related to missing resources
287+
func isMissingResourceError(err error) bool {
288+
errStr := err.Error()
289+
return strings.Contains(errStr, "couldn't find workflow template") ||
290+
strings.Contains(errStr, "couldn't find cluster workflow template") ||
291+
strings.Contains(errStr, "not found") ||
292+
strings.Contains(errStr, "doesn't exist")
293+
}
294+
280295
func getLintClients(client apiclient.Client, kinds []string) (ServiceClients, error) {
281296
res := ServiceClients{}
282297
var err error

0 commit comments

Comments
 (0)