diff --git a/changes/42522-labels-not-supported-in-no-team b/changes/42522-labels-not-supported-in-no-team new file mode 100644 index 0000000000..5dbb372e08 --- /dev/null +++ b/changes/42522-labels-not-supported-in-no-team @@ -0,0 +1 @@ +- Improved `fleetctl gitops` to warn when `labels:` is specified in no-team/unassigned files, where it is not supported. diff --git a/pkg/spec/gitops.go b/pkg/spec/gitops.go index a34f33262d..6f6a79c88c 100644 --- a/pkg/spec/gitops.go +++ b/pkg/spec/gitops.go @@ -525,7 +525,11 @@ func GitOpsFromFile(filePath, baseDir string, appConfig *fleet.EnrichedAppConfig // Get the labels. LabelsPresent tracks whether the key was in the YAML. if _, ok := top["labels"]; ok { result.LabelsPresent = true - multiError = parseLabels(top, result, baseDir, logFn, filePath, multiError) + if result.IsNoTeam() { + logFn("[!] 'labels' is not supported in %s. This key will be ignored.\n", filepath.Base(filePath)) + } else { + multiError = parseLabels(top, result, baseDir, logFn, filePath, multiError) + } } // Get other top-level entities. multiError = parseControls(top, result, logFn, filePath, multiError) diff --git a/pkg/spec/gitops_test.go b/pkg/spec/gitops_test.go index 3755909e17..4052d72262 100644 --- a/pkg/spec/gitops_test.go +++ b/pkg/spec/gitops_test.go @@ -2414,6 +2414,52 @@ labels: }) } +func TestLabelsIgnoredInNoTeamFile(t *testing.T) { + t.Parallel() + + t.Run("no-team.yml", func(t *testing.T) { + t.Parallel() + + config := "name: No team\nlabels:\n - name: test-label\n query: \"SELECT 1;\"\n description: test\nsoftware:\npolicies:\n" + noTeamPath, noTeamBasePath := createNamedFileOnTempDir(t, "no-team.yml", config) + + var logMessages []string + captureLogf := func(format string, a ...any) { + logMessages = append(logMessages, fmt.Sprintf(format, a...)) + } + + gitops, err := GitOpsFromFile(noTeamPath, noTeamBasePath, nil, captureLogf) + require.NoError(t, err) + + // LabelsPresent should be true (the key was in the YAML), but labels should not be parsed. + assert.True(t, gitops.LabelsPresent, "labels should be marked as present when explicitly set in no-team file") + assert.Empty(t, gitops.Labels, "labels should not be parsed in no-team file") + + // A warning should have been logged. + assert.Contains(t, strings.Join(logMessages, "\n"), "'labels' is not supported in no-team.yml") + }) + + t.Run("unassigned.yml", func(t *testing.T) { + t.Parallel() + + config := "name: Unassigned\nlabels:\n - name: test-label\n query: \"SELECT 1;\"\n description: test\nsoftware:\npolicies:\n" + unassignedPath, unassignedBasePath := createNamedFileOnTempDir(t, "unassigned.yml", config) + + var logMessages []string + captureLogf := func(format string, a ...any) { + logMessages = append(logMessages, fmt.Sprintf(format, a...)) + } + + gitops, err := GitOpsFromFile(unassignedPath, unassignedBasePath, nil, captureLogf) + require.NoError(t, err) + + assert.True(t, gitops.LabelsPresent, "labels should be marked as present when explicitly set in unassigned file") + assert.Empty(t, gitops.Labels, "labels should not be parsed in unassigned file") + + assert.Contains(t, strings.Join(logMessages, "\n"), "'labels' is not supported in unassigned.yml") + }) +} + func TestParsePoliciesGlob(t *testing.T) { t.Parallel()