diff --git a/cmd/fleetctl/gitops.go b/cmd/fleetctl/gitops.go index fc9e3c7a8374..a7db6be73ddb 100644 --- a/cmd/fleetctl/gitops.go +++ b/cmd/fleetctl/gitops.go @@ -82,15 +82,19 @@ func gitopsCommand() *cli.Command { } // We need to extract the controls from no-team.yml to be able to apply them when applying the global app config. - var noTeamControls spec.Controls + var ( + noTeamControls spec.Controls + noTeamPresent bool + ) for _, flFilename := range flFilenames.Value() { if filepath.Base(flFilename) == "no-team.yml" { baseDir := filepath.Dir(flFilename) - config, err := spec.GitOpsFromFile(flFilename, baseDir, appConfig, logf) + config, err := spec.GitOpsFromFile(flFilename, baseDir, appConfig, func(format string, a ...interface{}) {}) if err != nil { return err } noTeamControls = config.Controls + noTeamPresent = true break } } @@ -145,7 +149,7 @@ func gitopsCommand() *cli.Command { // name.) Because teams can be created/deleted during the same gitops run, we // grab some information to help us determine allowed/restricted actions and // when to perform the associations. - if isGlobalConfig && totalFilenames > 1 { + if isGlobalConfig && totalFilenames > 1 && !(totalFilenames == 2 && noTeamPresent) { abmTeams, hasMissingABMTeam, usesLegacyABMConfig, err = checkABMTeamAssignments(config, fleetClient) if err != nil { return err @@ -192,6 +196,7 @@ func gitopsCommand() *cli.Command { } } } + if flDryRun { incomingSecrets := fleetClient.GetGitOpsSecrets(config) for _, secret := range incomingSecrets { @@ -201,6 +206,7 @@ func gitopsCommand() *cli.Command { secrets[secret] = struct{}{} } } + assumptions, err := fleetClient.DoGitOps(c.Context, config, flFilename, logf, flDryRun, teamDryRunAssumptions, appConfig) if err != nil { return err @@ -349,7 +355,7 @@ func applyABMTokenAssignmentIfNeeded( if usesLegacyConfig { appleBMDefaultTeam := abmTeamNames[0] if !slices.Contains(teamNames, appleBMDefaultTeam) { - return fmt.Errorf("apple_bm_default_team %s not found in team configs", appleBMDefaultTeam) + return fmt.Errorf("apple_bm_default_team team %q not found in team configs", appleBMDefaultTeam) } appConfigUpdate = map[string]map[string]any{ "mdm": { @@ -359,7 +365,7 @@ func applyABMTokenAssignmentIfNeeded( } else { for _, abmTeam := range abmTeamNames { if !slices.Contains(teamNames, abmTeam) { - return fmt.Errorf("apple_business_manager team %s not found in team configs", abmTeam) + return fmt.Errorf("apple_business_manager team %q not found in team configs", abmTeam) } } diff --git a/cmd/fleetctl/gitops_test.go b/cmd/fleetctl/gitops_test.go index 0f6c33b061c4..64cb9fda19cc 100644 --- a/cmd/fleetctl/gitops_test.go +++ b/cmd/fleetctl/gitops_test.go @@ -2399,7 +2399,6 @@ software: ipadTeam, }, dryRunAssertion: func(t *testing.T, appCfg *fleet.AppConfig, ds fleet.Datastore, out string, err error) { - t.Log(out) require.ErrorContains(t, err, "mdm.apple_bm_default_team has been deprecated") assert.NotContains(t, out, "[!] gitops dry run succeeded") }, @@ -2420,10 +2419,10 @@ software: workstations, }, dryRunAssertion: func(t *testing.T, appCfg *fleet.AppConfig, ds fleet.Datastore, out string, err error) { - assert.ErrorContains(t, err, "apple_business_manager team 📱🏢 Company-owned iPhones not found in team configs") + assert.ErrorContains(t, err, "apple_business_manager team \"📱🏢 Company-owned iPhones\" not found in team configs") }, realRunAssertion: func(t *testing.T, appCfg *fleet.AppConfig, ds fleet.Datastore, out string, err error) { - assert.ErrorContains(t, err, "apple_business_manager team 📱🏢 Company-owned iPhones not found in team configs") + assert.ErrorContains(t, err, "apple_business_manager team \"📱🏢 Company-owned iPhones\" not found in team configs") }, }, { diff --git a/pkg/spec/gitops.go b/pkg/spec/gitops.go index a5938e2b9eef..9e4adc22687e 100644 --- a/pkg/spec/gitops.go +++ b/pkg/spec/gitops.go @@ -358,7 +358,7 @@ func parseAgentOptions(top map[string]json.RawMessage, result *GitOps, baseDir s agentOptionsRaw, ok := top["agent_options"] if result.IsNoTeam() { if ok { - logFn("[!] 'agent_options' is not supported for \"No team\". This key will be ignored.") + logFn("[!] 'agent_options' is not supported for \"No team\". This key will be ignored.\n") } return multiError } else if !ok { @@ -570,7 +570,7 @@ func parseQueries(top map[string]json.RawMessage, result *GitOps, baseDir string queriesRaw, ok := top["queries"] if result.IsNoTeam() { if ok { - logFn("[!] 'queries' is not supported for \"No team\". This key will be ignored.") + logFn("[!] 'queries' is not supported for \"No team\". This key will be ignored.\n") } return multiError } else if !ok { @@ -660,7 +660,12 @@ func parseSoftware(top map[string]json.RawMessage, result *GitOps, baseDir strin if err := json.Unmarshal(softwareRaw, &software); err != nil { var typeErr *json.UnmarshalTypeError if errors.As(err, &typeErr) { - return multierror.Append(multiError, fmt.Errorf("Couldn't edit software. %q must be a %s, found %s", typeErr.Field, typeErr.Type.String(), typeErr.Value)) + typeErrField := typeErr.Field + if typeErrField == "" { + // UnmarshalTypeError.Field is empty when trying to set an invalid type on the root node. + typeErrField = "software" + } + return multierror.Append(multiError, fmt.Errorf("Couldn't edit software. %q must be a %s, found %s", typeErrField, typeErr.Type.String(), typeErr.Value)) } return multierror.Append(multiError, fmt.Errorf("failed to unmarshall softwarespec: %v", err)) } diff --git a/server/service/client.go b/server/service/client.go index 6be25f00834a..8924707784f1 100644 --- a/server/service/client.go +++ b/server/service/client.go @@ -1502,9 +1502,13 @@ func (c *Client) DoGitOps( return nil, err } - err = c.doGitOpsQueries(config, logFn, dryRun) - if err != nil { - return nil, err + // We currently don't support queries for "No team" thus + // we just do GitOps for queries for global and team files. + if !config.IsNoTeam() { + err = c.doGitOpsQueries(config, logFn, dryRun) + if err != nil { + return nil, err + } } return teamAssumptions, nil diff --git a/server/service/client_policies.go b/server/service/client_policies.go index a8425bebf573..089e6a2d477d 100644 --- a/server/service/client_policies.go +++ b/server/service/client_policies.go @@ -2,6 +2,7 @@ package service import ( "fmt" + "github.com/fleetdm/fleet/v4/server/fleet" )