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
}