diff --git a/api/v1beta1/openstackconfiggenerator_types.go b/api/v1beta1/openstackconfiggenerator_types.go index bc128845..241406dd 100644 --- a/api/v1beta1/openstackconfiggenerator_types.go +++ b/api/v1beta1/openstackconfiggenerator_types.go @@ -60,6 +60,25 @@ type OpenStackConfigGeneratorSpec struct { EnableFencing bool `json:"enableFencing"` // TripleoRoleOverride - map of TripleO role name to temporary role override to support a multi-rhel environment (valid for 17.1 only) TripleoRoleOverride map[string]TripleoRoleOverrideSpec `json:"tripleoRoleOverride,omitempty"` + // +kubebuilder:validation:Optional + Debug OpenStackConfigGeneratorAdvancedSettings `json:"debug,omitempty"` +} + +// OpenStackConfigGeneratorAdvancedSettings - +// The main intention of these parameters are for debugging purposes to generate playbooks without the need of a full deployed environment. +type OpenStackConfigGeneratorAdvancedSettings struct { + // +kubebuilder:validation:Optional + // SkipWaiting enables the user to control if the OpenStackConfigGenerator should wait for all openstackbaremetalsets and openstackvmsets + // to be Ready before start to generate the playbooks. + SkipWaiting *bool `json:"skipWaiting,omitempty"` + // +kubebuilder:validation:Optional + // TripleoDeployConfigOverride allows to point to an existing configmap which has the files which are usually generated by the operator. + // Note: the configmap must provide a tripleo parameter file named `rendered-tripleo-config.yaml` + TripleoDeployConfigOverride *string `json:"tripleoDeployConfigOverride,omitempty"` + // +kubebuilder:validation:Optional + // OpenStackRelease to overwrite OSPrelease auto detection from the OpenStackControlPlane CR + // Note: needs to be set when SkipWaiting is used + OpenStackRelease string `json:"openStackRelease,omitempty"` } // OpenStackConfigGeneratorStatus defines the observed state of OpenStackConfigGenerator diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index d6874baf..6b2e5996 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -899,6 +899,31 @@ func (in *OpenStackConfigGenerator) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenStackConfigGeneratorAdvancedSettings) DeepCopyInto(out *OpenStackConfigGeneratorAdvancedSettings) { + *out = *in + if in.SkipWaiting != nil { + in, out := &in.SkipWaiting, &out.SkipWaiting + *out = new(bool) + **out = **in + } + if in.TripleoDeployConfigOverride != nil { + in, out := &in.TripleoDeployConfigOverride, &out.TripleoDeployConfigOverride + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackConfigGeneratorAdvancedSettings. +func (in *OpenStackConfigGeneratorAdvancedSettings) DeepCopy() *OpenStackConfigGeneratorAdvancedSettings { + if in == nil { + return nil + } + out := new(OpenStackConfigGeneratorAdvancedSettings) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OpenStackConfigGeneratorDefaults) DeepCopyInto(out *OpenStackConfigGeneratorDefaults) { *out = *in @@ -967,6 +992,7 @@ func (in *OpenStackConfigGeneratorSpec) DeepCopyInto(out *OpenStackConfigGenerat (*out)[key] = *val.DeepCopy() } } + in.Debug.DeepCopyInto(&out.Debug) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackConfigGeneratorSpec. diff --git a/config/crd/bases/osp-director.openstack.org_openstackconfiggenerators.yaml b/config/crd/bases/osp-director.openstack.org_openstackconfiggenerators.yaml index 9c628cd8..0a218155 100644 --- a/config/crd/bases/osp-director.openstack.org_openstackconfiggenerators.yaml +++ b/config/crd/bases/osp-director.openstack.org_openstackconfiggenerators.yaml @@ -46,6 +46,28 @@ spec: description: OpenStackConfigGeneratorSpec defines the desired state of OpenStackConfigGenerator properties: + debug: + description: OpenStackConfigGeneratorAdvancedSettings - The main intention + of these parameters are for debugging purposes to generate playbooks + without the need of a full deployed environment. + properties: + openStackRelease: + description: 'OpenStackRelease to overwrite OSPrelease auto detection + from the OpenStackControlPlane CR Note: needs to be set when + SkipWaiting is used' + type: string + skipWaiting: + description: SkipWaiting enables the user to control if the OpenStackConfigGenerator + should wait for all openstackbaremetalsets and openstackvmsets + to be Ready before start to generate the playbooks. + type: boolean + tripleoDeployConfigOverride: + description: 'TripleoDeployConfigOverride allows to point to an + existing configmap which has the files which are usually generated + by the operator. Note: the configmap must provide a tripleo + parameter file named `rendered-tripleo-config.yaml`' + type: string + type: object enableFencing: description: 'EnableFencing allows the automatic creation of required heat environment files to enable fencing. Note: - Production OSP diff --git a/controllers/openstackconfiggenerator_controller.go b/controllers/openstackconfiggenerator_controller.go index d1c0a7ce..c9d25e21 100644 --- a/controllers/openstackconfiggenerator_controller.go +++ b/controllers/openstackconfiggenerator_controller.go @@ -162,48 +162,65 @@ func (r *OpenStackConfigGeneratorReconciler) Reconcile(ctx context.Context, req envVars := make(map[string]common.EnvSetter) templateParameters := make(map[string]interface{}) cmLabels := common.GetLabels(instance, openstackconfiggenerator.AppLabel, map[string]string{}) + var controlPlane ospdirectorv1beta2.OpenStackControlPlane + var OSPVersion shared.OSPVersion - // - // Get OSPVersion from OSControlPlane status - // - // unified OSPVersion from ControlPlane CR - // which means also get either 16.2 or 17.0 for upstream versions - controlPlane, ctrlResult, err := ospdirectorv1beta2.GetControlPlane(r.Client, instance) - if err != nil { - cond.Message = err.Error() - cond.Reason = shared.ControlPlaneReasonNetNotFound - cond.Type = shared.ConfigGeneratorCondTypeError - err = common.WrapErrorForObject(cond.Message, instance, err) + if instance.Spec.Debug.SkipWaiting == nil || + (instance.Spec.Debug.SkipWaiting != nil && !*instance.Spec.Debug.SkipWaiting) { + var ctrlResult reconcile.Result + // + // Get OSPVersion from OSControlPlane status + // + // unified OSPVersion from ControlPlane CR + // which means also get either 16.2 or 17.0 for upstream versions + controlPlane, ctrlResult, err = ospdirectorv1beta2.GetControlPlane(r.Client, instance) + if err != nil { + cond.Message = err.Error() + cond.Reason = shared.ControlPlaneReasonNetNotFound + cond.Type = shared.ConfigGeneratorCondTypeError + err = common.WrapErrorForObject(cond.Message, instance, err) - return ctrlResult, err - } - OSPVersion, err := shared.GetOSPVersion(string(controlPlane.Status.OSPVersion)) - if err != nil { - cond.Message = err.Error() - cond.Reason = shared.ControlPlaneReasonNotSupportedVersion - cond.Type = shared.ConfigGeneratorCondTypeError - err = common.WrapErrorForObject(cond.Message, instance, err) + return ctrlResult, err + } + OSPVersion, err = shared.GetOSPVersion(string(controlPlane.Status.OSPVersion)) + if err != nil { + cond.Message = err.Error() + cond.Reason = shared.ControlPlaneReasonNotSupportedVersion + cond.Type = shared.ConfigGeneratorCondTypeError + err = common.WrapErrorForObject(cond.Message, instance, err) - return ctrlResult, err - } + return ctrlResult, err + } - templateParameters["OSPVersion"] = OSPVersion + // + // wait for the controlplane VMs to be provisioned + // + if controlPlane.Status.ProvisioningStatus.State != shared.ProvisioningState(shared.ControlPlaneProvisioned) { + cond.Message = fmt.Sprintf("Control plane %s VMs are not yet provisioned. Requeing...", controlPlane.Name) + cond.Reason = shared.ConfigGeneratorCondReasonCMNotFound + cond.Type = shared.ConfigGeneratorCondTypeWaiting + common.LogForObject( + r, + cond.Message, + instance, + ) - // - // wait for the controlplane VMs to be provisioned - // - if controlPlane.Status.ProvisioningStatus.State != shared.ProvisioningState(shared.ControlPlaneProvisioned) { - cond.Message = fmt.Sprintf("Control plane %s VMs are not yet provisioned. Requeing...", controlPlane.Name) - cond.Reason = shared.ConfigGeneratorCondReasonCMNotFound - cond.Type = shared.ConfigGeneratorCondTypeWaiting - common.LogForObject( - r, - cond.Message, - instance, - ) + return ctrl.Result{RequeueAfter: 10 * time.Second}, nil + } + } + + if instance.Spec.Debug.OpenStackRelease != "" { + OSPVersion, err = shared.GetOSPVersion(instance.Spec.Debug.OpenStackRelease) + if err != nil { + cond.Message = err.Error() + cond.Reason = shared.ControlPlaneReasonNotSupportedVersion + cond.Type = shared.ConfigGeneratorCondTypeError + err = common.WrapErrorForObject(cond.Message, instance, err) - return ctrl.Result{RequeueAfter: 10 * time.Second}, nil + return ctrl.Result{}, err + } } + templateParameters["OSPVersion"] = OSPVersion // // check if heat-env-config (customizations provided by administrator) exist if it does not exist, requeue @@ -272,18 +289,36 @@ func (r *OpenStackConfigGeneratorReconciler) Reconcile(ctx context.Context, req // // render OOO environment, create TripleoDeployCM and read the tripleo-deploy-config CM // - tripleoDeployCM, err := r.createTripleoDeployCM( - ctx, - instance, - cond, - &envVars, - cmLabels, - OSPVersion, - &controlPlane, - tripleoTarballCM, - ) - if err != nil { - return ctrl.Result{}, err + var tripleoDeployCM *corev1.ConfigMap + if instance.Spec.Debug.TripleoDeployConfigOverride == nil || + (instance.Spec.Debug.TripleoDeployConfigOverride != nil && *instance.Spec.Debug.TripleoDeployConfigOverride == "") { + tripleoDeployCM, err = r.createTripleoDeployCM( + ctx, + instance, + cond, + &envVars, + cmLabels, + OSPVersion, + &controlPlane, + tripleoTarballCM, + ) + if err != nil { + return ctrl.Result{}, err + } + } else { + tripleoDeployCM, _, err = common.GetConfigMapAndHashWithName(ctx, r, *instance.Spec.Debug.TripleoDeployConfigOverride, instance.Namespace) + if err != nil { + if k8s_errors.IsNotFound(err) { + cond.Message = "TripleoDeployConfigOverride config map not found, requeuing and waiting. Requeing..." + cond.Reason = shared.ConfigGeneratorCondReasonCMNotFound + cond.Type = shared.ConfigGeneratorCondTypeWaiting + err = common.WrapErrorForObject(cond.Message, instance, err) + + return ctrl.Result{RequeueAfter: 10 * time.Second}, err + } + // Error reading the object - requeue the request. + return ctrl.Result{}, err + } } tripleoDeployFiles := tripleoDeployCM.Data