diff --git a/deploy/crds/tf.galleybytes.com_terraforms_crd.yaml b/deploy/crds/tf.galleybytes.com_terraforms_crd.yaml index e9a061aad0cdda32d4a9b1a9867052f6ce8d9517..1c29c91255a9d8f1e89a6964b2560610936a9778 100644 --- a/deploy/crds/tf.galleybytes.com_terraforms_crd.yaml +++ b/deploy/crds/tf.galleybytes.com_terraforms_crd.yaml @@ -797,16 +797,21 @@ spec: description: TerraformStatus defines the observed state of Terraform properties: lastCompletedGeneration: + description: LastCompletedGeneration shows the generation of the last + completed workflow. This is not relevant for remotely executed workflows. format: int64 type: integer outputs: additionalProperties: type: string + description: Outputs terraform outputs, when opt-in, will be added + to this `status.outputs` field as key/value pairs type: object phase: + description: Phase is the current phase of the workflow type: string - plugins: - description: Plugins is a list of plugins that have been executed + pluginsStarted: + description: PluginsStarted is a list of plugins that have been executed by the controller. Will get refreshed each generation. items: type: string @@ -821,7 +826,7 @@ spec: nil. type: string stage: - description: Stage is the current task of the workflow. + description: Stage stores information about the current stage properties: generation: description: Generation is the generation of the resource when @@ -871,65 +876,11 @@ spec: - reason - state type: object - stages: - items: - description: Stage is the current task of the workflow. - properties: - generation: - description: Generation is the generation of the resource when - the task got started. - format: int64 - type: integer - interruptible: - description: Interruptible is set to false when the pod should - not be terminated such as when doing a terraform apply. - type: boolean - message: - description: Message stores the last message displayed in the - logs. It is stored and checked by the controller to reduce - the noise in the logs by only displying the message once. - type: string - podName: - description: PodName is the pod assigned to execute the stage. - type: string - podType: - description: TaskType is which task is currently running. - type: string - podUID: - description: PodUID is the pod uid of the pod assigned to execute - the stage. - type: string - reason: - description: Reason is a message of what is happening with the - pod. The controller uses this field when certain reasons occur - to make scheduling decisions. - type: string - startTime: - description: StartTime is when the task got created by the controller, - not when a pod got started. - format: date-time - type: string - state: - description: State is the phase of the task pod. - type: string - stopTime: - description: StopTime is when the task went into a stopped phase. - format: date-time - type: string - required: - - generation - - interruptible - - podType - - reason - - state - type: object - type: array required: - lastCompletedGeneration - phase - podNamePrefix - stage - - stages type: object type: object served: true diff --git a/pkg/apis/tf/v1beta1/terraform_types.go b/pkg/apis/tf/v1beta1/terraform_types.go index bfb9bd68852fd0dd9d9fe1ea47bd7d57181092d7..ca49fa0a1215b9883fbe0ebbb93a9aaf4eacc5d7 100644 --- a/pkg/apis/tf/v1beta1/terraform_types.go +++ b/pkg/apis/tf/v1beta1/terraform_types.go @@ -626,20 +626,28 @@ type TerraformStatus struct { // Another case for the pod name prefix is when rapidly deleteing a resource // and recreating it, the chance of recycling existing resources is reduced // to virtually nil. - PodNamePrefix string `json:"podNamePrefix"` - Phase StatusPhase `json:"phase"` - LastCompletedGeneration int64 `json:"lastCompletedGeneration"` - Outputs map[string]string `json:"outputs,omitempty"` - Stages []Stage `json:"stages"` - Stage Stage `json:"stage"` + PodNamePrefix string `json:"podNamePrefix"` + + // Phase is the current phase of the workflow + Phase StatusPhase `json:"phase"` + + // LastCompletedGeneration shows the generation of the last completed workflow. This is not relevant for remotely + // executed workflows. + LastCompletedGeneration int64 `json:"lastCompletedGeneration"` + + // Outputs terraform outputs, when opt-in, will be added to this `status.outputs` field as key/value pairs + Outputs map[string]string `json:"outputs,omitempty"` + + // Stage stores information about the current stage + Stage Stage `json:"stage"` // // RerunAttempt number is increased if a new pod is detected for the same stage. // CurrentAttempt int64 `json:"currentAttempt"` - // Plugins is a list of plugins that have been executed by the controller. Will get + // PluginsStarted is a list of plugins that have been executed by the controller. Will get // refreshed each generation. // +optional - Plugins []TaskName `json:"plugins,omitempty"` + PluginsStarted []TaskName `json:"pluginsStarted,omitempty"` } type Exported string diff --git a/pkg/apis/tf/v1beta1/zz_generated.deepcopy.go b/pkg/apis/tf/v1beta1/zz_generated.deepcopy.go index 075e939ffaafa4b10d0a5078abf1c2c9ee3b4cc9..4a1e70082c64b32c97162d8a43e8450f39029cab 100644 --- a/pkg/apis/tf/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/tf/v1beta1/zz_generated.deepcopy.go @@ -574,16 +574,9 @@ func (in *TerraformStatus) DeepCopyInto(out *TerraformStatus) { (*out)[key] = val } } - if in.Stages != nil { - in, out := &in.Stages, &out.Stages - *out = make([]Stage, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } in.Stage.DeepCopyInto(&out.Stage) - if in.Plugins != nil { - in, out := &in.Plugins, &out.Plugins + if in.PluginsStarted != nil { + in, out := &in.PluginsStarted, &out.PluginsStarted *out = make([]TaskName, len(*in)) copy(*out, *in) } diff --git a/pkg/apis/tf/v1beta1/zz_generated.openapi.go b/pkg/apis/tf/v1beta1/zz_generated.openapi.go index 106fda4a8273835fe9f85d43ed3d147cf72dab6b..94da219a7d25300f8802f0a212cb6bc719fc1e34 100644 --- a/pkg/apis/tf/v1beta1/zz_generated.openapi.go +++ b/pkg/apis/tf/v1beta1/zz_generated.openapi.go @@ -1117,21 +1117,24 @@ func schema_pkg_apis_tf_v1beta1_TerraformStatus(ref common.ReferenceCallback) co }, "phase": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Phase is the current phase of the workflow", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "lastCompletedGeneration": { SchemaProps: spec.SchemaProps{ - Default: 0, - Type: []string{"integer"}, - Format: "int64", + Description: "LastCompletedGeneration shows the generation of the last completed workflow. This is not relevant for remotely executed workflows.", + Default: 0, + Type: []string{"integer"}, + Format: "int64", }, }, "outputs": { SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, + Description: "Outputs terraform outputs, when opt-in, will be added to this `status.outputs` field as key/value pairs", + Type: []string{"object"}, AdditionalProperties: &spec.SchemaOrBool{ Allows: true, Schema: &spec.Schema{ @@ -1144,28 +1147,16 @@ func schema_pkg_apis_tf_v1beta1_TerraformStatus(ref common.ReferenceCallback) co }, }, }, - "stages": { - SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/galleybytes/terraform-operator/pkg/apis/tf/v1beta1.Stage"), - }, - }, - }, - }, - }, "stage": { SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/galleybytes/terraform-operator/pkg/apis/tf/v1beta1.Stage"), + Description: "Stage stores information about the current stage", + Default: map[string]interface{}{}, + Ref: ref("github.com/galleybytes/terraform-operator/pkg/apis/tf/v1beta1.Stage"), }, }, - "plugins": { + "pluginsStarted": { SchemaProps: spec.SchemaProps{ - Description: "Plugins is a list of plugins that have been executed by the controller. Will get refreshed each generation.", + Description: "PluginsStarted is a list of plugins that have been executed by the controller. Will get refreshed each generation.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ @@ -1179,7 +1170,7 @@ func schema_pkg_apis_tf_v1beta1_TerraformStatus(ref common.ReferenceCallback) co }, }, }, - Required: []string{"podNamePrefix", "phase", "lastCompletedGeneration", "stages", "stage"}, + Required: []string{"podNamePrefix", "phase", "lastCompletedGeneration", "stage"}, }, }, Dependencies: []string{ diff --git a/pkg/controllers/terraform_controller.go b/pkg/controllers/terraform_controller.go index 7f17340ebdc008a59c6e1a0daaf3936d32487b50..81ff8cf418d7e3aa3034a39bc1a9107229bc304e 100644 --- a/pkg/controllers/terraform_controller.go +++ b/pkg/controllers/terraform_controller.go @@ -562,7 +562,6 @@ func (r *ReconcileTerraform) Reconcile(ctx context.Context, request reconcile.Re utils.TruncateResourceName(tf.Name, 220), utils.StringWithCharset(8, utils.AlphaNum), ) - tf.Status.Stages = []tfv1beta1.Stage{} tf.Status.LastCompletedGeneration = 0 tf.Status.Phase = tfv1beta1.PhaseInitializing @@ -583,7 +582,7 @@ func (r *ReconcileTerraform) Reconcile(ctx context.Context, request reconcile.Re return reconcile.Result{}, fmt.Errorf("failed to create a new stage") } tf.Status.Stage = *stage - tf.Status.Plugins = []tfv1beta1.TaskName{} + tf.Status.PluginsStarted = []tfv1beta1.TaskName{} err := r.updateStatusWithRetry(ctx, tf, &tf.Status, reqLogger) if err != nil { @@ -748,7 +747,7 @@ func (r *ReconcileTerraform) Reconcile(ctx context.Context, request reconcile.Re // By now, the task pod exists and the controller has to check and update on the status of the pod. for pluginTaskName, pluginConfig := range tf.Spec.Plugins { - if tfv1beta1.ListContainsTask(tf.Status.Plugins, pluginTaskName) { + if tfv1beta1.ListContainsTask(tf.Status.PluginsStarted, pluginTaskName) { continue } @@ -862,7 +861,7 @@ func (r ReconcileTerraform) getTerraformResource(ctx context.Context, namespaced func newStage(tf *tfv1beta1.Terraform, taskType tfv1beta1.TaskName, reason string, interruptible tfv1beta1.Interruptible, stageState tfv1beta1.StageState) *tfv1beta1.Stage { if reason == "GENERATION_CHANGE" { - tf.Status.Plugins = []tfv1beta1.TaskName{} + tf.Status.PluginsStarted = []tfv1beta1.TaskName{} tf.Status.Phase = tfv1beta1.PhaseInitializing } startTime := metav1.NewTime(time.Now()) @@ -1357,7 +1356,7 @@ func (r ReconcileTerraform) createPluginPod(ctx context.Context, logger logr.Log logger.Info(fmt.Sprintf("Starting the plugin job '%s'", pluginTaskName.String())) } }() - tf.Status.Plugins = append(tf.Status.Plugins, pluginTaskName) + tf.Status.PluginsStarted = append(tf.Status.PluginsStarted, pluginTaskName) err := r.updateStatusWithRetry(ctx, tf, &tf.Status, logger) if err != nil { logger.V(1).Info(err.Error()) @@ -1443,8 +1442,8 @@ func (r ReconcileTerraform) updateStatusWithRetry(ctx context.Context, tf *tfv1b return fmt.Errorf("failed to get latest terraform while validating status: %s", updatedResourceErr) } - if !tfv1beta1.TaskListsAreEqual(tf.Status.Plugins, desiredStatus.Plugins) { - logger.V(7).Info(fmt.Sprintf("Failed to confirm the status update because plugins did not equal. Have %s and Want %s", tf.Status.Plugins, desiredStatus.Plugins)) + if !tfv1beta1.TaskListsAreEqual(tf.Status.PluginsStarted, desiredStatus.PluginsStarted) { + logger.V(7).Info(fmt.Sprintf("Failed to confirm the status update because plugins did not equal. Have %s and Want %s", tf.Status.PluginsStarted, desiredStatus.PluginsStarted)) } else if stageItem := tf.Status.Stage.IsEqual(desiredStatus.Stage); stageItem != "" { logger.V(7).Info(fmt.Sprintf("Failed to confirm the status update because stage item %s did not equal", stageItem))