func()

in agentendpoint/config_task.go [368:453]


func (c *configTask) run(ctx context.Context) error {
	clog.Infof(ctx, "Beginning ApplyConfigTask.")
	clog.Debugf(ctx, "ApplyConfigTask:\n%s", pretty.Format(c.Task.ApplyConfigTask))
	c.StartedAt = time.Now()

	rcsErrMsg := "Error reporting continuing state"
	if err := c.reportContinuingState(ctx, agentendpointpb.ApplyConfigTaskProgress_STARTED); err != nil {
		return c.handleErrorState(ctx, rcsErrMsg, err)
	}

	if len(c.Task.GetOsPolicies()) == 0 {
		clog.Infof(ctx, "No OSPolicies to apply.")
		return c.reportCompletedState(ctx, "", agentendpointpb.ApplyConfigTaskOutput_SUCCEEDED)
	}

	// We need to generate base results first thing, each execution step
	// just adds on.
	c.generateBaseResults()
	defer c.cleanup(ctx)

	if err := c.reportContinuingState(ctx, agentendpointpb.ApplyConfigTaskProgress_APPLYING_CONFIG); err != nil {
		return c.handleErrorState(ctx, rcsErrMsg, err)
	}

	c.policies = map[string]*policy{}
	for i, osPolicy := range c.Task.GetOsPolicies() {
		ctx := clog.WithLabels(ctx, map[string]string{"os_policy_assignment": osPolicy.GetOsPolicyAssignment(), "os_policy_id": osPolicy.GetId()})
		clog.Infof(ctx, "Executing policy %q", osPolicy.GetId())

		pResult := c.results[i]
		plcy := &policy{resources: map[string]*resource{}}
		c.policies[osPolicy.GetId()] = plcy
		var policyMR *config.ManagedResources

		var validateOnly bool
		if osPolicy.GetMode() == agentendpointpb.OSPolicy_VALIDATION {
			clog.Infof(ctx, "Policy running in VALIDATION mode, not running enforcement action for any resources.")
			validateOnly = true
		}

		for i, configResource := range osPolicy.GetResources() {
			rCompliance := pResult.GetOsPolicyResourceCompliances()[i]
			plcy.resources[configResource.GetId()] = newResource(configResource)
			res := plcy.resources[configResource.GetId()]
			if hasError := validateConfigResource(ctx, res, policyMR, rCompliance, configResource); hasError {
				res.validateOrCheckError = true
				break
			}
			if hasError := checkConfigResourceState(ctx, res, rCompliance, configResource); hasError {
				res.validateOrCheckError = true
				break
			}

			// Skip enforcement actions in VALIDATION mode.
			if validateOnly {
				continue
			}

			// Only errors in validate and check state constitute a serious error,
			// for enforce if any action is taken we still want to run post check.
			// We do however stop further execution of this polcy on enforce error.
			enforcementActionTaken, hasError := enforceConfigResourceState(ctx, res, rCompliance, configResource)
			if enforcementActionTaken {
				// On any change we trigger post check for all previous resouces,
				// even if there was an error.
				c.markPostCheckRequired()
			}
			// Still record output even if there was an error during enforcement.
			res.PopulateOutput(rCompliance)
			// Errors from enforcement are not classified as "serious" becasue we want post check to run for this resource.
			if hasError {
				break
			}
		}
		c.managedResources = append(c.managedResources, policyMR)
	}

	// Run any post checks that we need to.
	c.postCheckState(ctx)

	if err := c.reportCompletedState(ctx, "", agentendpointpb.ApplyConfigTaskOutput_SUCCEEDED); err != nil {
		return err
	}
	clog.Infof(ctx, "Successfully completed ApplyConfigTask")
	return nil
}