diff --git a/.rhdh/bundle/manifests/rhdh-operator.csv.yaml b/.rhdh/bundle/manifests/rhdh-operator.csv.yaml index 4b028830..09329808 100644 --- a/.rhdh/bundle/manifests/rhdh-operator.csv.yaml +++ b/.rhdh/bundle/manifests/rhdh-operator.csv.yaml @@ -7,7 +7,7 @@ metadata: alm-examples: |- [ { - "apiVersion": "rhdh.redhat.com/v1alpha1", + "apiVersion": "rhdh.redhat.com/v1alpha2", "kind": "Backstage", "metadata": { "name": "developer-hub" @@ -57,6 +57,14 @@ spec: kind: Backstage name: backstages.rhdh.redhat.com version: v1alpha1 + - description: Backstage is the Schema for the Red Hat Developer Hub backstages API. + It comes with pre-built plug-ins, configuration settings, and deployment mechanisms, + which can help streamline the process of setting up a self-managed internal + developer portal for adopters who are just starting out. + displayName: Red Hat Developer Hub + kind: Backstage + name: backstages.rhdh.redhat.com + version: v1alpha2 description: | Red Hat Developer Hub is an enterprise-grade platform for building developer portals, containing a supported and opinionated framework. By implementing a unified and open platform designed to maximize developer skills, ease onboarding, and increase development productivity, focus can be centered on what really matters: writing great code. Red Hat Developer Hub also offers Software Templates to simplify the development process, which can reduce friction and frustration for development teams, boosting their productivity and increasing an organization's competitive advantage. diff --git a/PROJECT b/PROJECT index b119bbc8..db3c7202 100644 --- a/PROJECT +++ b/PROJECT @@ -13,6 +13,6 @@ resources: controller: true domain: rhdh.redhat.com kind: Backstage - path: redhat-developer/red-hat-developer-hub-operator/api/v1alpha1 - version: v1alpha1 + path: redhat-developer/red-hat-developer-hub-operator/api/v1alpha2 + version: v1alpha2 version: "3" diff --git a/api/v1alpha1/backstage_types.go b/api/v1alpha1/backstage_types.go index 5fd7d794..0facd95a 100644 --- a/api/v1alpha1/backstage_types.go +++ b/api/v1alpha1/backstage_types.go @@ -197,6 +197,7 @@ type BackstageStatus struct { //+kubebuilder:object:root=true //+kubebuilder:subresource:status +//+kubebuilder:deprecatedversion:warning="Since 1.3.0 spec.application.image, spec.application.replicas, spec.application.imagePullSecrets are deprecated in favor of corresponding spec.deployment fields" // Backstage is the Schema for the backstages API type Backstage struct { diff --git a/api/v1alpha2/backstage_types.go b/api/v1alpha2/backstage_types.go new file mode 100644 index 00000000..a1288242 --- /dev/null +++ b/api/v1alpha2/backstage_types.go @@ -0,0 +1,310 @@ +// +// Copyright (c) 2023 Red Hat, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha2 + +import ( + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" +) + +type BackstageConditionReason string + +type BackstageConditionType string + +const ( + BackstageConditionTypeDeployed BackstageConditionType = "Deployed" + + BackstageConditionReasonDeployed BackstageConditionReason = "Deployed" + BackstageConditionReasonFailed BackstageConditionReason = "DeployFailed" + BackstageConditionReasonInProgress BackstageConditionReason = "DeployInProgress" +) + +// BackstageSpec defines the desired state of Backstage +type BackstageSpec struct { + // Configuration for Backstage. Optional. + Application *Application `json:"application,omitempty"` + + // Raw Runtime RuntimeObjects configuration. For Advanced scenarios. + RawRuntimeConfig *RuntimeConfig `json:"rawRuntimeConfig,omitempty"` + + // Configuration for database access. Optional. + Database *Database `json:"database,omitempty"` + + // Valid fragment of Deployment to be merged with default/raw configuration. + // Set the Deployment's metadata and|or spec fields you want to override or add. + // Optional. + // +kubebuilder:pruning:PreserveUnknownFields + Deployment *BackstageDeployment `json:"deployment,omitempty"` +} + +type BackstageDeployment struct { + // Valid fragment of Deployment to be merged with default/raw configuration. + // Set the Deployment's metadata and|or spec fields you want to override or add. + // Optional. + // +kubebuilder:pruning:PreserveUnknownFields + Patch *apiextensionsv1.JSON `json:"patch,omitempty"` +} + +type RuntimeConfig struct { + // Name of ConfigMap containing Backstage runtime objects configuration + BackstageConfigName string `json:"backstageConfig,omitempty"` + // Name of ConfigMap containing LocalDb (PostgreSQL) runtime objects configuration + LocalDbConfigName string `json:"localDbConfig,omitempty"` +} + +type Database struct { + // Control the creation of a local PostgreSQL DB. Set to false if using for example an external Database for Backstage. + // +optional + //+kubebuilder:default=true + EnableLocalDb *bool `json:"enableLocalDb,omitempty"` + + // Name of the secret for database authentication. Optional. + // For a local database deployment (EnableLocalDb=true), a secret will be auto generated if it does not exist. + // The secret shall include information used for the database access. + // An example for PostgreSQL DB access: + // "POSTGRES_PASSWORD": "rl4s3Fh4ng3M4" + // "POSTGRES_PORT": "5432" + // "POSTGRES_USER": "postgres" + // "POSTGRESQL_ADMIN_PASSWORD": "rl4s3Fh4ng3M4" + // "POSTGRES_HOST": "backstage-psql-bs1" # For local database, set to "backstage-psql-". + AuthSecretName string `json:"authSecretName,omitempty"` +} + +type Application struct { + // References to existing app-configs ConfigMap objects, that will be mounted as files in the specified mount path. + // Each element can be a reference to any ConfigMap or Secret, + // and will be mounted inside the main application container under a specified mount directory. + // Additionally, each file will be passed as a `--config /mount/path/to/configmap/key` to the + // main container args in the order of the entries defined in the AppConfigs list. + // But bear in mind that for a single ConfigMap element containing several filenames, + // the order in which those files will be appended to the main container args cannot be guaranteed. + // So if you want to pass multiple app-config files, it is recommended to pass one ConfigMap per app-config file. + // +optional + AppConfig *AppConfig `json:"appConfig,omitempty"` + + // Reference to an existing ConfigMap for Dynamic Plugins. + // A new one will be generated with the default config if not set. + // The ConfigMap object must have an existing key named: 'dynamic-plugins.yaml'. + // +optional + DynamicPluginsConfigMapName string `json:"dynamicPluginsConfigMapName,omitempty"` + + // References to existing Config objects to use as extra config files. + // They will be mounted as files in the specified mount path. + // Each element can be a reference to any ConfigMap or Secret. + // +optional + ExtraFiles *ExtraFiles `json:"extraFiles,omitempty"` + + // Extra environment variables + // +optional + ExtraEnvs *ExtraEnvs `json:"extraEnvs,omitempty"` + + // Number of desired replicas to set in the Backstage Deployment. + // Defaults to 1. + // +optional + //+kubebuilder:default=1 + Replicas *int32 `json:"replicas,omitempty"` + + // Custom image to use in all containers (including Init Containers). + // It is your responsibility to make sure the image is from trusted sources and has been validated for security compliance + // +optional + Image *string `json:"image,omitempty"` + + // Image Pull Secrets to use in all containers (including Init Containers) + // +optional + ImagePullSecrets []string `json:"imagePullSecrets,omitempty"` + + // Route configuration. Used for OpenShift only. + Route *Route `json:"route,omitempty"` +} + +type AppConfig struct { + // Mount path for all app-config files listed in the ConfigMapRefs field + // +optional + // +kubebuilder:default=/opt/app-root/src + MountPath string `json:"mountPath,omitempty"` + + // List of ConfigMaps storing the app-config files. Will be mounted as files under the MountPath specified. + // For each item in this array, if a key is not specified, it means that all keys in the ConfigMap will be mounted as files. + // Otherwise, only the specified key will be mounted as a file. + // Bear in mind not to put sensitive data in those ConfigMaps. Instead, your app-config content can reference + // environment variables (which you can set with the ExtraEnvs field) and/or include extra files (see the ExtraFiles field). + // More details on https://backstage.io/docs/conf/writing/. + // +optional + ConfigMaps []ObjectKeyRef `json:"configMaps,omitempty"` +} + +type ExtraFiles struct { + // Mount path for all extra configuration files listed in the Items field + // +optional + // +kubebuilder:default=/opt/app-root/src + MountPath string `json:"mountPath,omitempty"` + + // List of references to ConfigMaps objects mounted as extra files under the MountPath specified. + // For each item in this array, if a key is not specified, it means that all keys in the ConfigMap will be mounted as files. + // Otherwise, only the specified key will be mounted as a file. + // +optional + ConfigMaps []ObjectKeyRef `json:"configMaps,omitempty"` + + // List of references to Secrets objects mounted as extra files under the MountPath specified. + // For each item in this array, a key must be specified that will be mounted as a file. + // +optional + Secrets []ObjectKeyRef `json:"secrets,omitempty"` +} + +type ExtraEnvs struct { + // List of references to ConfigMaps objects to inject as additional environment variables. + // For each item in this array, if a key is not specified, it means that all keys in the ConfigMap will be injected as additional environment variables. + // Otherwise, only the specified key will be injected as an additional environment variable. + // +optional + ConfigMaps []ObjectKeyRef `json:"configMaps,omitempty"` + + // List of references to Secrets objects to inject as additional environment variables. + // For each item in this array, if a key is not specified, it means that all keys in the Secret will be injected as additional environment variables. + // Otherwise, only the specified key will be injected as environment variable. + // +optional + Secrets []ObjectKeyRef `json:"secrets,omitempty"` + + // List of name and value pairs to add as environment variables. + // +optional + Envs []Env `json:"envs,omitempty"` +} + +type ObjectKeyRef struct { + // Name of the object + // We support only ConfigMaps and Secrets. + //+kubebuilder:validation:Required + Name string `json:"name"` + + // Key in the object + // +optional + Key string `json:"key,omitempty"` +} + +type Env struct { + // Name of the environment variable + //+kubebuilder:validation:Required + Name string `json:"name"` + + // Value of the environment variable + //+kubebuilder:validation:Required + Value string `json:"value"` +} + +// BackstageStatus defines the observed state of Backstage +type BackstageStatus struct { + // Conditions is the list of conditions describing the state of the runtime + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +//+kubebuilder:storageversion + +// Backstage is the Schema for the backstages API +type Backstage struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec BackstageSpec `json:"spec,omitempty"` + Status BackstageStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// BackstageList contains a list of Backstage +type BackstageList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Backstage `json:"items"` +} + +// Route specifies configuration parameters for OpenShift Route for Backstage. +// Only a secured edge route is supported for Backstage. +type Route struct { + // Control the creation of a Route on OpenShift. + // +optional + //+kubebuilder:default=true + Enabled *bool `json:"enabled,omitempty"` + + // Host is an alias/DNS that points to the service. Optional. + // Ignored if Enabled is false. + // If not specified a route name will typically be automatically + // chosen. Must follow DNS952 subdomain conventions. + // +optional + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:Pattern=`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$` + Host string `json:"host,omitempty" protobuf:"bytes,1,opt,name=host"` + + // Subdomain is a DNS subdomain that is requested within the ingress controller's + // domain (as a subdomain). + // Ignored if Enabled is false. + // Example: subdomain `frontend` automatically receives the router subdomain + // `apps.mycluster.com` to have a full hostname `frontend.apps.mycluster.com`. + // +optional + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:Pattern=`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$` + Subdomain string `json:"subdomain,omitempty"` + + // The tls field provides the ability to configure certificates for the route. + // Ignored if Enabled is false. + // +optional + TLS *TLS `json:"tls,omitempty"` +} + +type TLS struct { + // certificate provides certificate contents. This should be a single serving certificate, not a certificate + // chain. Do not include a CA certificate. + Certificate string `json:"certificate,omitempty"` + + // ExternalCertificateSecretName provides certificate contents as a secret reference. + // This should be a single serving certificate, not a certificate + // chain. Do not include a CA certificate. The secret referenced should + // be present in the same namespace as that of the Route. + // Forbidden when `certificate` is set. + // +optional + ExternalCertificateSecretName string `json:"externalCertificateSecretName,omitempty"` + + // key provides key file contents + Key string `json:"key,omitempty"` + + // caCertificate provides the cert authority certificate contents + CACertificate string `json:"caCertificate,omitempty"` +} + +func init() { + SchemeBuilder.Register(&Backstage{}, &BackstageList{}) +} + +// IsLocalDbEnabled returns true if Local database is configured and enabled +func (s *BackstageSpec) IsLocalDbEnabled() bool { + if s.Database == nil { + return true + } + return ptr.Deref(s.Database.EnableLocalDb, true) +} + +// IsRouteEnabled returns value of Application.Route.Enabled if defined or true by default +func (s *BackstageSpec) IsRouteEnabled() bool { + if s.Application != nil && s.Application.Route != nil { + return ptr.Deref(s.Application.Route.Enabled, true) + } + return true +} + +func (s *BackstageSpec) IsAuthSecretSpecified() bool { + return s.Database != nil && s.Database.AuthSecretName != "" +} diff --git a/api/v1alpha2/groupversion_info.go b/api/v1alpha2/groupversion_info.go new file mode 100644 index 00000000..fb8c4342 --- /dev/null +++ b/api/v1alpha2/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2023 Red Hat Inc.. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1alpha2 contains API Schema definitions for the v1alpha2 API group +// +kubebuilder:object:generate=true +// +groupName=rhdh.redhat.com +package v1alpha2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "rhdh.redhat.com", Version: "v1alpha2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/v1alpha2/zz_generated.deepcopy.go b/api/v1alpha2/zz_generated.deepcopy.go new file mode 100644 index 00000000..280d13d4 --- /dev/null +++ b/api/v1alpha2/zz_generated.deepcopy.go @@ -0,0 +1,394 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2023 Red Hat Inc.. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AppConfig) DeepCopyInto(out *AppConfig) { + *out = *in + if in.ConfigMaps != nil { + in, out := &in.ConfigMaps, &out.ConfigMaps + *out = make([]ObjectKeyRef, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppConfig. +func (in *AppConfig) DeepCopy() *AppConfig { + if in == nil { + return nil + } + out := new(AppConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Application) DeepCopyInto(out *Application) { + *out = *in + if in.AppConfig != nil { + in, out := &in.AppConfig, &out.AppConfig + *out = new(AppConfig) + (*in).DeepCopyInto(*out) + } + if in.ExtraFiles != nil { + in, out := &in.ExtraFiles, &out.ExtraFiles + *out = new(ExtraFiles) + (*in).DeepCopyInto(*out) + } + if in.ExtraEnvs != nil { + in, out := &in.ExtraEnvs, &out.ExtraEnvs + *out = new(ExtraEnvs) + (*in).DeepCopyInto(*out) + } + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + if in.Image != nil { + in, out := &in.Image, &out.Image + *out = new(string) + **out = **in + } + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Route != nil { + in, out := &in.Route, &out.Route + *out = new(Route) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Application. +func (in *Application) DeepCopy() *Application { + if in == nil { + return nil + } + out := new(Application) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Backstage) DeepCopyInto(out *Backstage) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backstage. +func (in *Backstage) DeepCopy() *Backstage { + if in == nil { + return nil + } + out := new(Backstage) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Backstage) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackstageDeployment) DeepCopyInto(out *BackstageDeployment) { + *out = *in + if in.Patch != nil { + in, out := &in.Patch, &out.Patch + *out = new(v1.JSON) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackstageDeployment. +func (in *BackstageDeployment) DeepCopy() *BackstageDeployment { + if in == nil { + return nil + } + out := new(BackstageDeployment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackstageList) DeepCopyInto(out *BackstageList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Backstage, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackstageList. +func (in *BackstageList) DeepCopy() *BackstageList { + if in == nil { + return nil + } + out := new(BackstageList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BackstageList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackstageSpec) DeepCopyInto(out *BackstageSpec) { + *out = *in + if in.Application != nil { + in, out := &in.Application, &out.Application + *out = new(Application) + (*in).DeepCopyInto(*out) + } + if in.RawRuntimeConfig != nil { + in, out := &in.RawRuntimeConfig, &out.RawRuntimeConfig + *out = new(RuntimeConfig) + **out = **in + } + if in.Database != nil { + in, out := &in.Database, &out.Database + *out = new(Database) + (*in).DeepCopyInto(*out) + } + if in.Deployment != nil { + in, out := &in.Deployment, &out.Deployment + *out = new(BackstageDeployment) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackstageSpec. +func (in *BackstageSpec) DeepCopy() *BackstageSpec { + if in == nil { + return nil + } + out := new(BackstageSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackstageStatus) DeepCopyInto(out *BackstageStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackstageStatus. +func (in *BackstageStatus) DeepCopy() *BackstageStatus { + if in == nil { + return nil + } + out := new(BackstageStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Database) DeepCopyInto(out *Database) { + *out = *in + if in.EnableLocalDb != nil { + in, out := &in.EnableLocalDb, &out.EnableLocalDb + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Database. +func (in *Database) DeepCopy() *Database { + if in == nil { + return nil + } + out := new(Database) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Env) DeepCopyInto(out *Env) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Env. +func (in *Env) DeepCopy() *Env { + if in == nil { + return nil + } + out := new(Env) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtraEnvs) DeepCopyInto(out *ExtraEnvs) { + *out = *in + if in.ConfigMaps != nil { + in, out := &in.ConfigMaps, &out.ConfigMaps + *out = make([]ObjectKeyRef, len(*in)) + copy(*out, *in) + } + if in.Secrets != nil { + in, out := &in.Secrets, &out.Secrets + *out = make([]ObjectKeyRef, len(*in)) + copy(*out, *in) + } + if in.Envs != nil { + in, out := &in.Envs, &out.Envs + *out = make([]Env, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtraEnvs. +func (in *ExtraEnvs) DeepCopy() *ExtraEnvs { + if in == nil { + return nil + } + out := new(ExtraEnvs) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtraFiles) DeepCopyInto(out *ExtraFiles) { + *out = *in + if in.ConfigMaps != nil { + in, out := &in.ConfigMaps, &out.ConfigMaps + *out = make([]ObjectKeyRef, len(*in)) + copy(*out, *in) + } + if in.Secrets != nil { + in, out := &in.Secrets, &out.Secrets + *out = make([]ObjectKeyRef, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtraFiles. +func (in *ExtraFiles) DeepCopy() *ExtraFiles { + if in == nil { + return nil + } + out := new(ExtraFiles) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectKeyRef) DeepCopyInto(out *ObjectKeyRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectKeyRef. +func (in *ObjectKeyRef) DeepCopy() *ObjectKeyRef { + if in == nil { + return nil + } + out := new(ObjectKeyRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Route) DeepCopyInto(out *Route) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(TLS) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Route. +func (in *Route) DeepCopy() *Route { + if in == nil { + return nil + } + out := new(Route) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuntimeConfig) DeepCopyInto(out *RuntimeConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuntimeConfig. +func (in *RuntimeConfig) DeepCopy() *RuntimeConfig { + if in == nil { + return nil + } + out := new(RuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLS) DeepCopyInto(out *TLS) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLS. +func (in *TLS) DeepCopy() *TLS { + if in == nil { + return nil + } + out := new(TLS) + in.DeepCopyInto(out) + return out +} diff --git a/bundle/manifests/backstage-operator.clusterserviceversion.yaml b/bundle/manifests/backstage-operator.clusterserviceversion.yaml index 14725ce4..b6396b6a 100644 --- a/bundle/manifests/backstage-operator.clusterserviceversion.yaml +++ b/bundle/manifests/backstage-operator.clusterserviceversion.yaml @@ -5,7 +5,7 @@ metadata: alm-examples: |- [ { - "apiVersion": "rhdh.redhat.com/v1alpha1", + "apiVersion": "rhdh.redhat.com/v1alpha2", "kind": "Backstage", "metadata": { "labels": { @@ -21,7 +21,7 @@ metadata: } ] capabilities: Seamless Upgrades - createdAt: "2024-07-02T14:30:16Z" + createdAt: "2024-07-08T12:45:16Z" operatorframework.io/suggested-namespace: backstage-system operators.operatorframework.io/builder: operator-sdk-v1.33.0 operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 @@ -37,10 +37,12 @@ spec: kind: Backstage name: backstages.rhdh.redhat.com version: v1alpha1 - description: | - Operator to deploy Backstage on Kubernetes - - The telemetry data collection feature is enabled by default. In the default configuration of the operator, telemetry data will be sent to Red Hat by using the `backstage-plugin-analytics-provider-segment` plugin. To disable this and to learn what data is being collected, see https://github.com/janus-idp/backstage-showcase/blob/main/showcase-docs/getting-started.md#telemetry-collection + - description: Backstage is the Schema for the backstages API + displayName: Backstage + kind: Backstage + name: backstages.rhdh.redhat.com + version: v1alpha2 + description: Operator to deploy Backstage on Kubernetes displayName: Red Hat Developer Hub Operator icon: - base64data: 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 diff --git a/bundle/manifests/rhdh.redhat.com_backstages.yaml b/bundle/manifests/rhdh.redhat.com_backstages.yaml index ebbb9bfb..8acba889 100644 --- a/bundle/manifests/rhdh.redhat.com_backstages.yaml +++ b/bundle/manifests/rhdh.redhat.com_backstages.yaml @@ -14,7 +14,11 @@ spec: singular: backstage scope: Namespaced versions: - - name: v1alpha1 + - deprecated: true + deprecationWarning: Since 1.3.0 spec.application.image, spec.application.replicas, + spec.application.imagePullSecrets are deprecated in favor of corresponding spec.deployment + fields + name: v1alpha1 schema: openAPIV3Schema: description: Backstage is the Schema for the backstages API @@ -373,6 +377,380 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - name: v1alpha2 + schema: + openAPIV3Schema: + description: Backstage is the Schema for the backstages API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: BackstageSpec defines the desired state of Backstage + properties: + application: + description: Configuration for Backstage. Optional. + properties: + appConfig: + description: References to existing app-configs ConfigMap objects, + that will be mounted as files in the specified mount path. Each + element can be a reference to any ConfigMap or Secret, and will + be mounted inside the main application container under a specified + mount directory. Additionally, each file will be passed as a + `--config /mount/path/to/configmap/key` to the main container + args in the order of the entries defined in the AppConfigs list. + But bear in mind that for a single ConfigMap element containing + several filenames, the order in which those files will be appended + to the main container args cannot be guaranteed. So if you want + to pass multiple app-config files, it is recommended to pass + one ConfigMap per app-config file. + properties: + configMaps: + description: List of ConfigMaps storing the app-config files. + Will be mounted as files under the MountPath specified. + For each item in this array, if a key is not specified, + it means that all keys in the ConfigMap will be mounted + as files. Otherwise, only the specified key will be mounted + as a file. Bear in mind not to put sensitive data in those + ConfigMaps. Instead, your app-config content can reference + environment variables (which you can set with the ExtraEnvs + field) and/or include extra files (see the ExtraFiles field). + More details on https://backstage.io/docs/conf/writing/. + items: + properties: + key: + description: Key in the object + type: string + name: + description: Name of the object We support only ConfigMaps + and Secrets. + type: string + required: + - name + type: object + type: array + mountPath: + default: /opt/app-root/src + description: Mount path for all app-config files listed in + the ConfigMapRefs field + type: string + type: object + dynamicPluginsConfigMapName: + description: 'Reference to an existing ConfigMap for Dynamic Plugins. + A new one will be generated with the default config if not set. + The ConfigMap object must have an existing key named: ''dynamic-plugins.yaml''.' + type: string + extraEnvs: + description: Extra environment variables + properties: + configMaps: + description: List of references to ConfigMaps objects to inject + as additional environment variables. For each item in this + array, if a key is not specified, it means that all keys + in the ConfigMap will be injected as additional environment + variables. Otherwise, only the specified key will be injected + as an additional environment variable. + items: + properties: + key: + description: Key in the object + type: string + name: + description: Name of the object We support only ConfigMaps + and Secrets. + type: string + required: + - name + type: object + type: array + envs: + description: List of name and value pairs to add as environment + variables. + items: + properties: + name: + description: Name of the environment variable + type: string + value: + description: Value of the environment variable + type: string + required: + - name + - value + type: object + type: array + secrets: + description: List of references to Secrets objects to inject + as additional environment variables. For each item in this + array, if a key is not specified, it means that all keys + in the Secret will be injected as additional environment + variables. Otherwise, only the specified key will be injected + as environment variable. + items: + properties: + key: + description: Key in the object + type: string + name: + description: Name of the object We support only ConfigMaps + and Secrets. + type: string + required: + - name + type: object + type: array + type: object + extraFiles: + description: References to existing Config objects to use as extra + config files. They will be mounted as files in the specified + mount path. Each element can be a reference to any ConfigMap + or Secret. + properties: + configMaps: + description: List of references to ConfigMaps objects mounted + as extra files under the MountPath specified. For each item + in this array, if a key is not specified, it means that + all keys in the ConfigMap will be mounted as files. Otherwise, + only the specified key will be mounted as a file. + items: + properties: + key: + description: Key in the object + type: string + name: + description: Name of the object We support only ConfigMaps + and Secrets. + type: string + required: + - name + type: object + type: array + mountPath: + default: /opt/app-root/src + description: Mount path for all extra configuration files + listed in the Items field + type: string + secrets: + description: List of references to Secrets objects mounted + as extra files under the MountPath specified. For each item + in this array, a key must be specified that will be mounted + as a file. + items: + properties: + key: + description: Key in the object + type: string + name: + description: Name of the object We support only ConfigMaps + and Secrets. + type: string + required: + - name + type: object + type: array + type: object + image: + description: Custom image to use in all containers (including + Init Containers). It is your responsibility to make sure the + image is from trusted sources and has been validated for security + compliance + type: string + imagePullSecrets: + description: Image Pull Secrets to use in all containers (including + Init Containers) + items: + type: string + type: array + replicas: + default: 1 + description: Number of desired replicas to set in the Backstage + Deployment. Defaults to 1. + format: int32 + type: integer + route: + description: Route configuration. Used for OpenShift only. + properties: + enabled: + default: true + description: Control the creation of a Route on OpenShift. + type: boolean + host: + description: Host is an alias/DNS that points to the service. + Optional. Ignored if Enabled is false. If not specified + a route name will typically be automatically chosen. Must + follow DNS952 subdomain conventions. + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + subdomain: + description: 'Subdomain is a DNS subdomain that is requested + within the ingress controller''s domain (as a subdomain). + Ignored if Enabled is false. Example: subdomain `frontend` + automatically receives the router subdomain `apps.mycluster.com` + to have a full hostname `frontend.apps.mycluster.com`.' + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + tls: + description: The tls field provides the ability to configure + certificates for the route. Ignored if Enabled is false. + properties: + caCertificate: + description: caCertificate provides the cert authority + certificate contents + type: string + certificate: + description: certificate provides certificate contents. + This should be a single serving certificate, not a certificate + chain. Do not include a CA certificate. + type: string + externalCertificateSecretName: + description: ExternalCertificateSecretName provides certificate + contents as a secret reference. This should be a single + serving certificate, not a certificate chain. Do not + include a CA certificate. The secret referenced should + be present in the same namespace as that of the Route. + Forbidden when `certificate` is set. + type: string + key: + description: key provides key file contents + type: string + type: object + type: object + type: object + database: + description: Configuration for database access. Optional. + properties: + authSecretName: + description: 'Name of the secret for database authentication. + Optional. For a local database deployment (EnableLocalDb=true), + a secret will be auto generated if it does not exist. The secret + shall include information used for the database access. An example + for PostgreSQL DB access: "POSTGRES_PASSWORD": "rl4s3Fh4ng3M4" + "POSTGRES_PORT": "5432" "POSTGRES_USER": "postgres" "POSTGRESQL_ADMIN_PASSWORD": + "rl4s3Fh4ng3M4" "POSTGRES_HOST": "backstage-psql-bs1" # For + local database, set to "backstage-psql-".' + type: string + enableLocalDb: + default: true + description: Control the creation of a local PostgreSQL DB. Set + to false if using for example an external Database for Backstage. + type: boolean + type: object + deployment: + description: Valid fragment of Deployment to be merged with default/raw + configuration. Set the Deployment's metadata and|or spec fields + you want to override or add. Optional. + properties: + patch: + description: Valid fragment of Deployment to be merged with default/raw + configuration. Set the Deployment's metadata and|or spec fields + you want to override or add. Optional. + x-kubernetes-preserve-unknown-fields: true + type: object + x-kubernetes-preserve-unknown-fields: true + rawRuntimeConfig: + description: Raw Runtime RuntimeObjects configuration. For Advanced + scenarios. + properties: + backstageConfig: + description: Name of ConfigMap containing Backstage runtime objects + configuration + type: string + localDbConfig: + description: Name of ConfigMap containing LocalDb (PostgreSQL) + runtime objects configuration + type: string + type: object + type: object + status: + description: BackstageStatus defines the observed state of Backstage + properties: + conditions: + description: Conditions is the list of conditions describing the state + of the runtime + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/config/crd/bases/rhdh.redhat.com_backstages.yaml b/config/crd/bases/rhdh.redhat.com_backstages.yaml index 2b990068..e42a54e1 100644 --- a/config/crd/bases/rhdh.redhat.com_backstages.yaml +++ b/config/crd/bases/rhdh.redhat.com_backstages.yaml @@ -15,7 +15,11 @@ spec: singular: backstage scope: Namespaced versions: - - name: v1alpha1 + - deprecated: true + deprecationWarning: Since 1.3.0 spec.application.image, spec.application.replicas, + spec.application.imagePullSecrets are deprecated in favor of corresponding spec.deployment + fields + name: v1alpha1 schema: openAPIV3Schema: description: Backstage is the Schema for the backstages API @@ -374,6 +378,380 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - name: v1alpha2 + schema: + openAPIV3Schema: + description: Backstage is the Schema for the backstages API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: BackstageSpec defines the desired state of Backstage + properties: + application: + description: Configuration for Backstage. Optional. + properties: + appConfig: + description: References to existing app-configs ConfigMap objects, + that will be mounted as files in the specified mount path. Each + element can be a reference to any ConfigMap or Secret, and will + be mounted inside the main application container under a specified + mount directory. Additionally, each file will be passed as a + `--config /mount/path/to/configmap/key` to the main container + args in the order of the entries defined in the AppConfigs list. + But bear in mind that for a single ConfigMap element containing + several filenames, the order in which those files will be appended + to the main container args cannot be guaranteed. So if you want + to pass multiple app-config files, it is recommended to pass + one ConfigMap per app-config file. + properties: + configMaps: + description: List of ConfigMaps storing the app-config files. + Will be mounted as files under the MountPath specified. + For each item in this array, if a key is not specified, + it means that all keys in the ConfigMap will be mounted + as files. Otherwise, only the specified key will be mounted + as a file. Bear in mind not to put sensitive data in those + ConfigMaps. Instead, your app-config content can reference + environment variables (which you can set with the ExtraEnvs + field) and/or include extra files (see the ExtraFiles field). + More details on https://backstage.io/docs/conf/writing/. + items: + properties: + key: + description: Key in the object + type: string + name: + description: Name of the object We support only ConfigMaps + and Secrets. + type: string + required: + - name + type: object + type: array + mountPath: + default: /opt/app-root/src + description: Mount path for all app-config files listed in + the ConfigMapRefs field + type: string + type: object + dynamicPluginsConfigMapName: + description: 'Reference to an existing ConfigMap for Dynamic Plugins. + A new one will be generated with the default config if not set. + The ConfigMap object must have an existing key named: ''dynamic-plugins.yaml''.' + type: string + extraEnvs: + description: Extra environment variables + properties: + configMaps: + description: List of references to ConfigMaps objects to inject + as additional environment variables. For each item in this + array, if a key is not specified, it means that all keys + in the ConfigMap will be injected as additional environment + variables. Otherwise, only the specified key will be injected + as an additional environment variable. + items: + properties: + key: + description: Key in the object + type: string + name: + description: Name of the object We support only ConfigMaps + and Secrets. + type: string + required: + - name + type: object + type: array + envs: + description: List of name and value pairs to add as environment + variables. + items: + properties: + name: + description: Name of the environment variable + type: string + value: + description: Value of the environment variable + type: string + required: + - name + - value + type: object + type: array + secrets: + description: List of references to Secrets objects to inject + as additional environment variables. For each item in this + array, if a key is not specified, it means that all keys + in the Secret will be injected as additional environment + variables. Otherwise, only the specified key will be injected + as environment variable. + items: + properties: + key: + description: Key in the object + type: string + name: + description: Name of the object We support only ConfigMaps + and Secrets. + type: string + required: + - name + type: object + type: array + type: object + extraFiles: + description: References to existing Config objects to use as extra + config files. They will be mounted as files in the specified + mount path. Each element can be a reference to any ConfigMap + or Secret. + properties: + configMaps: + description: List of references to ConfigMaps objects mounted + as extra files under the MountPath specified. For each item + in this array, if a key is not specified, it means that + all keys in the ConfigMap will be mounted as files. Otherwise, + only the specified key will be mounted as a file. + items: + properties: + key: + description: Key in the object + type: string + name: + description: Name of the object We support only ConfigMaps + and Secrets. + type: string + required: + - name + type: object + type: array + mountPath: + default: /opt/app-root/src + description: Mount path for all extra configuration files + listed in the Items field + type: string + secrets: + description: List of references to Secrets objects mounted + as extra files under the MountPath specified. For each item + in this array, a key must be specified that will be mounted + as a file. + items: + properties: + key: + description: Key in the object + type: string + name: + description: Name of the object We support only ConfigMaps + and Secrets. + type: string + required: + - name + type: object + type: array + type: object + image: + description: Custom image to use in all containers (including + Init Containers). It is your responsibility to make sure the + image is from trusted sources and has been validated for security + compliance + type: string + imagePullSecrets: + description: Image Pull Secrets to use in all containers (including + Init Containers) + items: + type: string + type: array + replicas: + default: 1 + description: Number of desired replicas to set in the Backstage + Deployment. Defaults to 1. + format: int32 + type: integer + route: + description: Route configuration. Used for OpenShift only. + properties: + enabled: + default: true + description: Control the creation of a Route on OpenShift. + type: boolean + host: + description: Host is an alias/DNS that points to the service. + Optional. Ignored if Enabled is false. If not specified + a route name will typically be automatically chosen. Must + follow DNS952 subdomain conventions. + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + subdomain: + description: 'Subdomain is a DNS subdomain that is requested + within the ingress controller''s domain (as a subdomain). + Ignored if Enabled is false. Example: subdomain `frontend` + automatically receives the router subdomain `apps.mycluster.com` + to have a full hostname `frontend.apps.mycluster.com`.' + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + tls: + description: The tls field provides the ability to configure + certificates for the route. Ignored if Enabled is false. + properties: + caCertificate: + description: caCertificate provides the cert authority + certificate contents + type: string + certificate: + description: certificate provides certificate contents. + This should be a single serving certificate, not a certificate + chain. Do not include a CA certificate. + type: string + externalCertificateSecretName: + description: ExternalCertificateSecretName provides certificate + contents as a secret reference. This should be a single + serving certificate, not a certificate chain. Do not + include a CA certificate. The secret referenced should + be present in the same namespace as that of the Route. + Forbidden when `certificate` is set. + type: string + key: + description: key provides key file contents + type: string + type: object + type: object + type: object + database: + description: Configuration for database access. Optional. + properties: + authSecretName: + description: 'Name of the secret for database authentication. + Optional. For a local database deployment (EnableLocalDb=true), + a secret will be auto generated if it does not exist. The secret + shall include information used for the database access. An example + for PostgreSQL DB access: "POSTGRES_PASSWORD": "rl4s3Fh4ng3M4" + "POSTGRES_PORT": "5432" "POSTGRES_USER": "postgres" "POSTGRESQL_ADMIN_PASSWORD": + "rl4s3Fh4ng3M4" "POSTGRES_HOST": "backstage-psql-bs1" # For + local database, set to "backstage-psql-".' + type: string + enableLocalDb: + default: true + description: Control the creation of a local PostgreSQL DB. Set + to false if using for example an external Database for Backstage. + type: boolean + type: object + deployment: + description: Valid fragment of Deployment to be merged with default/raw + configuration. Set the Deployment's metadata and|or spec fields + you want to override or add. Optional. + properties: + patch: + description: Valid fragment of Deployment to be merged with default/raw + configuration. Set the Deployment's metadata and|or spec fields + you want to override or add. Optional. + x-kubernetes-preserve-unknown-fields: true + type: object + x-kubernetes-preserve-unknown-fields: true + rawRuntimeConfig: + description: Raw Runtime RuntimeObjects configuration. For Advanced + scenarios. + properties: + backstageConfig: + description: Name of ConfigMap containing Backstage runtime objects + configuration + type: string + localDbConfig: + description: Name of ConfigMap containing LocalDb (PostgreSQL) + runtime objects configuration + type: string + type: object + type: object + status: + description: BackstageStatus defines the observed state of Backstage + properties: + conditions: + description: Conditions is the list of conditions describing the state + of the runtime + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/config/manifests/bases/backstage-operator.clusterserviceversion.yaml b/config/manifests/bases/backstage-operator.clusterserviceversion.yaml index ea3d00d2..85f05436 100644 --- a/config/manifests/bases/backstage-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/backstage-operator.clusterserviceversion.yaml @@ -17,10 +17,12 @@ spec: kind: Backstage name: backstages.rhdh.redhat.com version: v1alpha1 - description: | - Operator to deploy Backstage on Kubernetes - - The telemetry data collection feature is enabled by default. In the default configuration of the operator, telemetry data will be sent to Red Hat by using the `backstage-plugin-analytics-provider-segment` plugin. To disable this and to learn what data is being collected, see https://github.com/janus-idp/backstage-showcase/blob/main/showcase-docs/getting-started.md#telemetry-collection + - description: Backstage is the Schema for the backstages API + displayName: Backstage + kind: Backstage + name: backstages.rhdh.redhat.com + version: v1alpha2 + description: Operator to deploy Backstage on Kubernetes displayName: Red Hat Developer Hub Operator icon: - base64data: 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 @@ -56,4 +58,4 @@ spec: provider: name: Red Hat Inc. url: https://www.redhat.com/ - version: 0.2.0 + version: 0.3.0 diff --git a/config/samples/_v1alpha1_backstage.yaml b/config/samples/_v1alpha2_backstage.yaml similarity index 90% rename from config/samples/_v1alpha1_backstage.yaml rename to config/samples/_v1alpha2_backstage.yaml index 1b6a82cf..17e804b5 100644 --- a/config/samples/_v1alpha1_backstage.yaml +++ b/config/samples/_v1alpha2_backstage.yaml @@ -1,4 +1,4 @@ -apiVersion: rhdh.redhat.com/v1alpha1 +apiVersion: rhdh.redhat.com/v1alpha2 kind: Backstage metadata: labels: diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index f66b0cd5..7dc86ec2 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -1,4 +1,4 @@ ## Append samples you want in your CSV to this file as resources ## resources: -- _v1alpha1_backstage.yaml +- _v1alpha2_backstage.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/controllers/backstage_controller.go b/controllers/backstage_controller.go index 115f8960..5c14fc6a 100644 --- a/controllers/backstage_controller.go +++ b/controllers/backstage_controller.go @@ -41,7 +41,7 @@ import ( "redhat-developer/red-hat-developer-hub-operator/pkg/model" - bs "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bs "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" diff --git a/controllers/preprocessor_test.go b/controllers/preprocessor_test.go index 51e2db3a..9b7ed275 100644 --- a/controllers/preprocessor_test.go +++ b/controllers/preprocessor_test.go @@ -17,7 +17,7 @@ package controller import ( "context" "os" - "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/model" "testing" @@ -30,15 +30,15 @@ import ( func updateConfigMap(t *testing.T) BackstageReconciler { ctx := context.TODO() - bs := v1alpha1.Backstage{ + bs := v1alpha2.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs1", Namespace: "ns1", }, - Spec: v1alpha1.BackstageSpec{ - Application: &v1alpha1.Application{ - AppConfig: &v1alpha1.AppConfig{ - ConfigMaps: []v1alpha1.ObjectKeyRef{{Name: "cm1"}}, + Spec: v1alpha2.BackstageSpec{ + Application: &v1alpha2.Application{ + AppConfig: &v1alpha2.AppConfig{ + ConfigMaps: []v1alpha2.ObjectKeyRef{{Name: "cm1"}}, }, }, }, diff --git a/controllers/spec_preprocessor.go b/controllers/spec_preprocessor.go index 12b33099..fd52f545 100644 --- a/controllers/spec_preprocessor.go +++ b/controllers/spec_preprocessor.go @@ -26,7 +26,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" - bs "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bs "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/model" diff --git a/examples/bs-existing-secret.yaml b/examples/bs-existing-secret.yaml index 2395c4cd..d4069195 100644 --- a/examples/bs-existing-secret.yaml +++ b/examples/bs-existing-secret.yaml @@ -1,4 +1,4 @@ -apiVersion: rhdh.redhat.com/v1alpha1 +apiVersion: rhdh.redhat.com/v1alpha2 kind: Backstage metadata: name: bs-existing-secret diff --git a/examples/bs-route-disabled.yaml b/examples/bs-route-disabled.yaml index dd35530c..25ecbee9 100644 --- a/examples/bs-route-disabled.yaml +++ b/examples/bs-route-disabled.yaml @@ -1,4 +1,4 @@ -apiVersion: rhdh.redhat.com/v1alpha1 +apiVersion: rhdh.redhat.com/v1alpha2 kind: Backstage metadata: name: bs-route-disabled diff --git a/examples/bs-route.yaml b/examples/bs-route.yaml index 8ec5838f..e9f03790 100644 --- a/examples/bs-route.yaml +++ b/examples/bs-route.yaml @@ -1,4 +1,4 @@ -apiVersion: rhdh.redhat.com/v1alpha1 +apiVersion: rhdh.redhat.com/v1alpha2 kind: Backstage metadata: name: bs-route diff --git a/examples/bs1.yaml b/examples/bs1.yaml index a1b7a90f..458933da 100644 --- a/examples/bs1.yaml +++ b/examples/bs1.yaml @@ -1,4 +1,4 @@ -apiVersion: rhdh.redhat.com/v1alpha1 +apiVersion: rhdh.redhat.com/v1alpha2 kind: Backstage metadata: name: bs1 diff --git a/examples/rhdh-cr-with-app-configs.yaml b/examples/rhdh-cr-with-app-configs.yaml index ff255c5d..ece40664 100644 --- a/examples/rhdh-cr-with-app-configs.yaml +++ b/examples/rhdh-cr-with-app-configs.yaml @@ -1,4 +1,4 @@ -apiVersion: rhdh.redhat.com/v1alpha1 +apiVersion: rhdh.redhat.com/v1alpha2 kind: Backstage metadata: name: bs-app-config diff --git a/examples/rhdh-cr.yaml b/examples/rhdh-cr.yaml index 5c8adf4e..7f915474 100644 --- a/examples/rhdh-cr.yaml +++ b/examples/rhdh-cr.yaml @@ -1,4 +1,4 @@ -apiVersion: rhdh.redhat.com/v1alpha1 +apiVersion: rhdh.redhat.com/v1alpha2 kind: Backstage metadata: name: my-rhdh diff --git a/examples/showcase-cr.yaml b/examples/showcase-cr.yaml index 4d2fa6bd..c8d86446 100644 --- a/examples/showcase-cr.yaml +++ b/examples/showcase-cr.yaml @@ -1,4 +1,4 @@ -apiVersion: rhdh.redhat.com/v1alpha1 +apiVersion: rhdh.redhat.com/v1alpha2 kind: Backstage metadata: name: bs-showcase diff --git a/go.mod b/go.mod index ef6655a8..2ba10ab2 100644 --- a/go.mod +++ b/go.mod @@ -8,24 +8,28 @@ require ( github.com/openshift/api v0.0.0-20240419172957-f39cf2ef93fd github.com/stretchr/testify v1.9.0 k8s.io/api v0.29.4 + k8s.io/apiextensions-apiserver v0.29.2 k8s.io/apimachinery v0.29.4 k8s.io/client-go v0.29.4 k8s.io/utils v0.0.0-20240310230437-4693a0247e57 sigs.k8s.io/controller-runtime v0.17.3 + sigs.k8s.io/kustomize/kyaml v0.17.1 + sigs.k8s.io/yaml v1.4.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.8.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-errors/errors v1.4.2 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-openapi/swag v0.22.4 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -34,7 +38,7 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.3.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -47,7 +51,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect @@ -69,11 +73,9 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.29.2 // indirect k8s.io/component-base v0.29.2 // indirect k8s.io/klog/v2 v2.110.1 // indirect k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 2df7f759..52efd064 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,9 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= @@ -19,6 +20,8 @@ github.com/evanphx/json-patch/v5 v5.8.0 h1:lRj6N9Nci7MvzrXuX6HFzU8XjmhPiXPlsKEy1 github.com/evanphx/json-patch/v5 v5.8.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -28,8 +31,9 @@ github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -49,8 +53,8 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -81,6 +85,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= @@ -93,8 +99,9 @@ github.com/openshift/api v0.0.0-20240419172957-f39cf2ef93fd h1:DztdAsKaNJjfL12Ly github.com/openshift/api v0.0.0-20240419172957-f39cf2ef93fd/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= @@ -103,8 +110,8 @@ github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lne github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -117,6 +124,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= +github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -207,6 +216,8 @@ sigs.k8s.io/controller-runtime v0.17.3 h1:65QmN7r3FWgTxDMz9fvGnO1kbf2nu+acg9p2R9 sigs.k8s.io/controller-runtime v0.17.3/go.mod h1:N0jpP5Lo7lMTF9aL56Z/B2oWBJjey6StQM0jRbKQXtY= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ= +sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/integration_tests/config-refresh_test.go b/integration_tests/config-refresh_test.go index d8feb801..92fed3e8 100644 --- a/integration_tests/config-refresh_test.go +++ b/integration_tests/config-refresh_test.go @@ -29,7 +29,7 @@ import ( "redhat-developer/red-hat-developer-hub-operator/pkg/model" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "k8s.io/apimachinery/pkg/types" @@ -67,16 +67,16 @@ var _ = When("create backstage with external configuration", func() { generateConfigMap(ctx, k8sClient, appConfig1, ns, map[string]string{"key11": "app:", "key12": "app:"}, nil, nil) generateSecret(ctx, k8sClient, secretEnv1, ns, map[string]string{"sec11": "val11"}, nil, nil) - bs := bsv1alpha1.BackstageSpec{ - Application: &bsv1alpha1.Application{ - AppConfig: &bsv1alpha1.AppConfig{ + bs := bsv1.BackstageSpec{ + Application: &bsv1.Application{ + AppConfig: &bsv1.AppConfig{ MountPath: "/my/mount/path", - ConfigMaps: []bsv1alpha1.ObjectKeyRef{ + ConfigMaps: []bsv1.ObjectKeyRef{ {Name: appConfig1}, }, }, - ExtraEnvs: &bsv1alpha1.ExtraEnvs{ - Secrets: []bsv1alpha1.ObjectKeyRef{ + ExtraEnvs: &bsv1.ExtraEnvs{ + Secrets: []bsv1.ObjectKeyRef{ {Name: secretEnv1, Key: "sec11"}, }, }, diff --git a/integration_tests/cr-config_test.go b/integration_tests/cr-config_test.go index 0c98a691..d92dbae3 100644 --- a/integration_tests/cr-config_test.go +++ b/integration_tests/cr-config_test.go @@ -30,7 +30,7 @@ import ( "redhat-developer/red-hat-developer-hub-operator/pkg/model" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "k8s.io/apimachinery/pkg/types" @@ -74,38 +74,38 @@ var _ = When("create backstage with CR configured", func() { secretEnv1 := generateSecret(ctx, k8sClient, "secret-env1", ns, map[string]string{"sec11": "val11", "sec12": "val12"}, nil, nil) _ = generateSecret(ctx, k8sClient, "secret-env2", ns, map[string]string{"sec21": "val21", "sec22": "val22"}, nil, nil) - bs := bsv1alpha1.BackstageSpec{ - Application: &bsv1alpha1.Application{ - AppConfig: &bsv1alpha1.AppConfig{ + bs := bsv1.BackstageSpec{ + Application: &bsv1.Application{ + AppConfig: &bsv1.AppConfig{ MountPath: "/my/mount/path", - ConfigMaps: []bsv1alpha1.ObjectKeyRef{ + ConfigMaps: []bsv1.ObjectKeyRef{ {Name: appConfig1}, {Name: appConfig2, Key: "key21"}, {Name: appConfig3}, }, }, - ExtraFiles: &bsv1alpha1.ExtraFiles{ + ExtraFiles: &bsv1.ExtraFiles{ MountPath: "/my/file/path", - ConfigMaps: []bsv1alpha1.ObjectKeyRef{ + ConfigMaps: []bsv1.ObjectKeyRef{ {Name: cmFile1}, {Name: cmFile2, Key: "cm21"}, {Name: cmFile3}, }, - Secrets: []bsv1alpha1.ObjectKeyRef{ + Secrets: []bsv1.ObjectKeyRef{ {Name: secretFile1, Key: "sec11"}, {Name: secretFile2, Key: "sec21"}, {Name: secretFile3, Key: "sec.31"}, }, }, - ExtraEnvs: &bsv1alpha1.ExtraEnvs{ - ConfigMaps: []bsv1alpha1.ObjectKeyRef{ + ExtraEnvs: &bsv1.ExtraEnvs{ + ConfigMaps: []bsv1.ObjectKeyRef{ {Name: cmEnv1}, {Name: cmEnv2, Key: "cm21"}, }, - Secrets: []bsv1alpha1.ObjectKeyRef{ + Secrets: []bsv1.ObjectKeyRef{ {Name: secretEnv1, Key: "sec11"}, }, - Envs: []bsv1alpha1.Env{ + Envs: []bsv1.Env{ {Name: "env1", Value: "val1"}, }, }, @@ -179,10 +179,10 @@ var _ = When("create backstage with CR configured", func() { appConfig := generateConfigMap(ctx, k8sClient, "app-config1", ns, map[string]string{"key11": "app:", "key12": "app:"}, nil, nil) - bs := bsv1alpha1.BackstageSpec{ - Application: &bsv1alpha1.Application{ - AppConfig: &bsv1alpha1.AppConfig{ - ConfigMaps: []bsv1alpha1.ObjectKeyRef{ + bs := bsv1.BackstageSpec{ + Application: &bsv1.Application{ + AppConfig: &bsv1.AppConfig{ + ConfigMaps: []bsv1.ObjectKeyRef{ {Name: appConfig}, }, }, @@ -208,7 +208,7 @@ var _ = When("create backstage with CR configured", func() { It("creates default Backstage and then update CR ", func() { - backstageName := createAndReconcileBackstage(ctx, ns, bsv1alpha1.BackstageSpec{}, "") + backstageName := createAndReconcileBackstage(ctx, ns, bsv1.BackstageSpec{}, "") Eventually(func(g Gomega) { By("creating Deployment with replicas=1 by default") @@ -223,10 +223,10 @@ var _ = When("create backstage with CR configured", func() { By("updating Backstage") imageName := "quay.io/my-org/my-awesome-image:1.2.3" ips := []string{"some-image-pull-secret-1", "some-image-pull-secret-2"} - update := &bsv1alpha1.Backstage{} + update := &bsv1.Backstage{} err := k8sClient.Get(ctx, types.NamespacedName{Name: backstageName, Namespace: ns}, update) Expect(err).To(Not(HaveOccurred())) - update.Spec.Application = &bsv1alpha1.Application{} + update.Spec.Application = &bsv1.Application{} update.Spec.Application.Replicas = ptr.To(int32(2)) update.Spec.Application.Image = ptr.To(imageName) update.Spec.Application.ImagePullSecrets = ips @@ -250,6 +250,50 @@ var _ = When("create backstage with CR configured", func() { }, time.Minute, time.Second).Should(Succeed()) }) + + It("creates Backstage deployment with spec.deployment ", func() { + + bs2 := &bsv1.Backstage{} + + err := utils.ReadYamlFile("testdata/spec-deployment.yaml", bs2) + Expect(err).To(Not(HaveOccurred())) + + backstageName := createAndReconcileBackstage(ctx, ns, bs2.Spec, "") + + Eventually(func(g Gomega) { + By("creating Deployment ") + deploy := &appsv1.Deployment{} + err := k8sClient.Get(ctx, types.NamespacedName{Namespace: ns, Name: model.DeploymentName(backstageName)}, deploy) + g.Expect(err).To(Not(HaveOccurred())) + var bscontainer corev1.Container + for _, c := range deploy.Spec.Template.Spec.Containers { + + if c.Name == "backstage-backend" { + bscontainer = c + break + } + } + + g.Expect(bscontainer).NotTo(BeNil()) + g.Expect(bscontainer.Image).To(HaveValue(Equal("busybox"))) + + var bsvolume corev1.Volume + for _, v := range deploy.Spec.Template.Spec.Volumes { + + if v.Name == "dynamic-plugins-root" { + bsvolume = v + break + } + } + + g.Expect(bsvolume).NotTo(BeNil()) + g.Expect(bsvolume.Ephemeral).NotTo(BeNil()) + g.Expect(*bsvolume.Ephemeral.VolumeClaimTemplate.Spec.StorageClassName).To(Equal("special")) + + }, 10*time.Second, time.Second).Should(Succeed()) + + }) + }) // Duplicated files in different CMs diff --git a/integration_tests/db_test.go b/integration_tests/db_test.go index 7ee45983..ffdaff6d 100644 --- a/integration_tests/db_test.go +++ b/integration_tests/db_test.go @@ -19,9 +19,8 @@ import ( "fmt" "time" - "redhat-developer/red-hat-developer-hub-operator/pkg/model" - "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/utils/ptr" corev1 "k8s.io/api/core/v1" @@ -30,7 +29,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + "redhat-developer/red-hat-developer-hub-operator/pkg/model" + + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "k8s.io/apimachinery/pkg/types" @@ -55,7 +56,7 @@ var _ = When("create backstage with CR configured", func() { }) It("creates default Backstage and then update CR to not to use local DB", func() { - backstageName := createAndReconcileBackstage(ctx, ns, bsv1alpha1.BackstageSpec{}, "") + backstageName := createAndReconcileBackstage(ctx, ns, bsv1.BackstageSpec{}, "") Eventually(func(g Gomega) { By("creating Deployment with database.enableLocalDb=true by default") @@ -72,10 +73,10 @@ var _ = When("create backstage with CR configured", func() { }, time.Minute, time.Second).Should(Succeed()) By("updating Backstage") - update := &bsv1alpha1.Backstage{} + update := &bsv1.Backstage{} err := k8sClient.Get(ctx, types.NamespacedName{Name: backstageName, Namespace: ns}, update) Expect(err).To(Not(HaveOccurred())) - update.Spec.Database = &bsv1alpha1.Database{} + update.Spec.Database = &bsv1.Database{} update.Spec.Database.EnableLocalDb = ptr.To(false) err = k8sClient.Update(ctx, update) Expect(err).To(Not(HaveOccurred())) @@ -102,8 +103,8 @@ var _ = When("create backstage with CR configured", func() { }) It("creates Backstage with disabled local DB and secret", func() { - backstageName := createAndReconcileBackstage(ctx, ns, bsv1alpha1.BackstageSpec{ - Database: &bsv1alpha1.Database{ + backstageName := createAndReconcileBackstage(ctx, ns, bsv1.BackstageSpec{ + Database: &bsv1.Database{ EnableLocalDb: ptr.To(false), AuthSecretName: "existing-secret", }, @@ -124,8 +125,8 @@ var _ = When("create backstage with CR configured", func() { }) It("creates Backstage with disabled local DB no secret", func() { - backstageName := createAndReconcileBackstage(ctx, ns, bsv1alpha1.BackstageSpec{ - Database: &bsv1alpha1.Database{ + backstageName := createAndReconcileBackstage(ctx, ns, bsv1.BackstageSpec{ + Database: &bsv1.Database{ EnableLocalDb: ptr.To(false), }, }, "") diff --git a/integration_tests/default-config_test.go b/integration_tests/default-config_test.go index 9f8820a0..a4e00aa0 100644 --- a/integration_tests/default-config_test.go +++ b/integration_tests/default-config_test.go @@ -26,7 +26,7 @@ import ( appsv1 "k8s.io/api/apps/v1" "sigs.k8s.io/controller-runtime/pkg/reconcile" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" corev1 "k8s.io/api/core/v1" @@ -54,7 +54,7 @@ var _ = When("create default backstage", func() { It("creates runtime objects", func() { - backstageName := createAndReconcileBackstage(ctx, ns, bsv1alpha1.BackstageSpec{}, "") + backstageName := createAndReconcileBackstage(ctx, ns, bsv1.BackstageSpec{}, "") Eventually(func(g Gomega) { By("creating a secret for accessing the Database") @@ -104,7 +104,7 @@ var _ = When("create default backstage", func() { By("setting Backstage status (real cluster only)") Eventually(func(g Gomega) { - bs := &bsv1alpha1.Backstage{} + bs := &bsv1.Backstage{} err := k8sClient.Get(ctx, types.NamespacedName{Namespace: ns, Name: backstageName}, bs) g.Expect(err).ShouldNot(HaveOccurred()) @@ -132,8 +132,8 @@ var _ = When("create default backstage", func() { bsRaw := generateConfigMap(ctx, k8sClient, "bsraw", ns, bsConf, nil, nil) dbRaw := generateConfigMap(ctx, k8sClient, "dbraw", ns, dbConf, nil, nil) - backstageName := createAndReconcileBackstage(ctx, ns, bsv1alpha1.BackstageSpec{ - RawRuntimeConfig: &bsv1alpha1.RuntimeConfig{ + backstageName := createAndReconcileBackstage(ctx, ns, bsv1.BackstageSpec{ + RawRuntimeConfig: &bsv1.RuntimeConfig{ BackstageConfigName: bsRaw, LocalDbConfigName: dbRaw, }, @@ -169,8 +169,8 @@ var _ = When("create default backstage", func() { dbRaw := generateConfigMap(ctx, k8sClient, "dbraw", ns, dbConf, nil, nil) - backstageName := createAndReconcileBackstage(ctx, ns, bsv1alpha1.BackstageSpec{ - RawRuntimeConfig: &bsv1alpha1.RuntimeConfig{ + backstageName := createAndReconcileBackstage(ctx, ns, bsv1.BackstageSpec{ + RawRuntimeConfig: &bsv1.RuntimeConfig{ LocalDbConfigName: dbRaw, }, }, "") @@ -192,7 +192,7 @@ var _ = When("create default backstage", func() { }, time.Minute, time.Second).Should(Succeed()) By("updating CR to default config") - update := &bsv1alpha1.Backstage{} + update := &bsv1.Backstage{} err := k8sClient.Get(ctx, types.NamespacedName{Name: backstageName, Namespace: ns}, update) Expect(err).To(Not(HaveOccurred())) update.Spec.RawRuntimeConfig = nil diff --git a/integration_tests/rhdh-config_test.go b/integration_tests/rhdh-config_test.go index bb702e46..b2c877e8 100644 --- a/integration_tests/rhdh-config_test.go +++ b/integration_tests/rhdh-config_test.go @@ -24,7 +24,7 @@ import ( "redhat-developer/red-hat-developer-hub-operator/pkg/model" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" @@ -39,7 +39,7 @@ var _ = When("create default backstage", func() { ctx := context.Background() ns := createNamespace(ctx) - backstageName := createAndReconcileBackstage(ctx, ns, bsv1alpha1.BackstageSpec{}, "") + backstageName := createAndReconcileBackstage(ctx, ns, bsv1.BackstageSpec{}, "") Eventually(func(g Gomega) { deploy := &appsv1.Deployment{} diff --git a/integration_tests/route_test.go b/integration_tests/route_test.go index 404c0e5d..f9f59011 100644 --- a/integration_tests/route_test.go +++ b/integration_tests/route_test.go @@ -23,7 +23,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "k8s.io/apimachinery/pkg/types" @@ -53,9 +53,9 @@ var _ = When("create default backstage", func() { Skip("Skipped for non-Openshift cluster") } - backstageName := createAndReconcileBackstage(ctx, ns, bsv1alpha1.BackstageSpec{ - Application: &bsv1alpha1.Application{ - Route: &bsv1alpha1.Route{ + backstageName := createAndReconcileBackstage(ctx, ns, bsv1.BackstageSpec{ + Application: &bsv1.Application{ + Route: &bsv1.Route{ //Host: "localhost", //Enabled: ptr.To(true), Subdomain: "test", @@ -64,7 +64,7 @@ var _ = When("create default backstage", func() { }, "") Eventually(func() error { - found := &bsv1alpha1.Backstage{} + found := &bsv1.Backstage{} return k8sClient.Get(ctx, types.NamespacedName{Name: backstageName, Namespace: ns}, found) }, time.Minute, time.Second).Should(Succeed()) diff --git a/integration_tests/suite_test.go b/integration_tests/suite_test.go index 8d708b37..a7f6e725 100644 --- a/integration_tests/suite_test.go +++ b/integration_tests/suite_test.go @@ -50,7 +50,7 @@ import ( . "github.com/onsi/gomega" "k8s.io/apimachinery/pkg/util/rand" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" @@ -116,7 +116,7 @@ var _ = BeforeSuite(func() { Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) - err = bsv1alpha1.AddToScheme(scheme.Scheme) + err = bsv1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) //+kubebuilder:scaffold:scheme @@ -151,11 +151,11 @@ func generateRandName(name string) string { return "test-backstage-" + randString(5) } -func createBackstage(ctx context.Context, spec bsv1alpha1.BackstageSpec, ns string, name string) string { +func createBackstage(ctx context.Context, spec bsv1.BackstageSpec, ns string, name string) string { backstageName := generateRandName(name) - err := k8sClient.Create(ctx, &bsv1alpha1.Backstage{ + err := k8sClient.Create(ctx, &bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: backstageName, Namespace: ns, @@ -166,11 +166,11 @@ func createBackstage(ctx context.Context, spec bsv1alpha1.BackstageSpec, ns stri return backstageName } -func createAndReconcileBackstage(ctx context.Context, ns string, spec bsv1alpha1.BackstageSpec, name string) string { +func createAndReconcileBackstage(ctx context.Context, ns string, spec bsv1.BackstageSpec, name string) string { backstageName := createBackstage(ctx, spec, ns, name) Eventually(func() error { - found := &bsv1alpha1.Backstage{} + found := &bsv1.Backstage{} return k8sClient.Get(ctx, types.NamespacedName{Name: backstageName, Namespace: ns}, found) }, time.Minute, time.Second).Should(Succeed()) diff --git a/integration_tests/testdata/spec-deployment.yaml b/integration_tests/testdata/spec-deployment.yaml new file mode 100644 index 00000000..bd1b1e9c --- /dev/null +++ b/integration_tests/testdata/spec-deployment.yaml @@ -0,0 +1,17 @@ +apiVersion: rhdh.redhat.com/v1alpha2 +kind: Backstage +spec: + deployment: + patch: + spec: + template: + spec: + containers: + - name: backstage-backend + image: busybox + volumes: + - ephemeral: + volumeClaimTemplate: + spec: + storageClassName: "special" + name: dynamic-plugins-root \ No newline at end of file diff --git a/main.go b/main.go index 7a954211..abfc1831 100644 --- a/main.go +++ b/main.go @@ -34,7 +34,7 @@ import ( metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" - backstageiov1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + backstageiov1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" controller "redhat-developer/red-hat-developer-hub-operator/controllers" openshift "github.com/openshift/api/route/v1" diff --git a/pkg/model/appconfig.go b/pkg/model/appconfig.go index 93eaa0e9..9b544e12 100644 --- a/pkg/model/appconfig.go +++ b/pkg/model/appconfig.go @@ -19,7 +19,7 @@ import ( appsv1 "k8s.io/api/apps/v1" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" corev1 "k8s.io/api/core/v1" @@ -49,7 +49,7 @@ func AppConfigDefaultName(backstageName string) string { return utils.GenerateRuntimeObjectName(backstageName, "backstage-appconfig") } -func addAppConfigs(spec bsv1alpha1.BackstageSpec, deployment *appsv1.Deployment, model *BackstageModel) { +func addAppConfigs(spec bsv1.BackstageSpec, deployment *appsv1.Deployment, model *BackstageModel) { if spec.Application == nil || spec.Application.AppConfig == nil || spec.Application.AppConfig.ConfigMaps == nil { return @@ -89,7 +89,7 @@ func (b *AppConfig) EmptyObject() client.Object { } // implementation of RuntimeObject interface -func (b *AppConfig) addToModel(model *BackstageModel, _ bsv1alpha1.Backstage) (bool, error) { +func (b *AppConfig) addToModel(model *BackstageModel, _ bsv1.Backstage) (bool, error) { if b.ConfigMap != nil { model.setRuntimeObject(b) return true, nil @@ -98,7 +98,7 @@ func (b *AppConfig) addToModel(model *BackstageModel, _ bsv1alpha1.Backstage) (b } // implementation of RuntimeObject interface -func (b *AppConfig) validate(_ *BackstageModel, _ bsv1alpha1.Backstage) error { +func (b *AppConfig) validate(_ *BackstageModel, _ bsv1.Backstage) error { return nil } diff --git a/pkg/model/appconfig_test.go b/pkg/model/appconfig_test.go index 835a9931..da0b3d7e 100644 --- a/pkg/model/appconfig_test.go +++ b/pkg/model/appconfig_test.go @@ -19,7 +19,7 @@ import ( "redhat-developer/red-hat-developer-hub-operator/pkg/utils" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" corev1 "k8s.io/api/core/v1" @@ -54,16 +54,16 @@ var ( Data: map[string]string{"conf31.yaml": "", "conf32.yaml": ""}, } - appConfigTestBackstage = bsv1alpha1.Backstage{ + appConfigTestBackstage = bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Application: &bsv1alpha1.Application{ - AppConfig: &bsv1alpha1.AppConfig{ + Spec: bsv1.BackstageSpec{ + Application: &bsv1.Application{ + AppConfig: &bsv1.AppConfig{ MountPath: "/my/path", - ConfigMaps: []bsv1alpha1.ObjectKeyRef{}, + ConfigMaps: []bsv1.ObjectKeyRef{}, }, }, }, @@ -97,11 +97,11 @@ func TestSpecifiedAppConfig(t *testing.T) { bs := *appConfigTestBackstage.DeepCopy() bs.Spec.Application.AppConfig.ConfigMaps = append(bs.Spec.Application.AppConfig.ConfigMaps, - bsv1alpha1.ObjectKeyRef{Name: appConfigTestCm.Name}) + bsv1.ObjectKeyRef{Name: appConfigTestCm.Name}) bs.Spec.Application.AppConfig.ConfigMaps = append(bs.Spec.Application.AppConfig.ConfigMaps, - bsv1alpha1.ObjectKeyRef{Name: appConfigTestCm2.Name}) + bsv1.ObjectKeyRef{Name: appConfigTestCm2.Name}) bs.Spec.Application.AppConfig.ConfigMaps = append(bs.Spec.Application.AppConfig.ConfigMaps, - bsv1alpha1.ObjectKeyRef{Name: appConfigTestCm3.Name, Key: "conf31.yaml"}) + bsv1.ObjectKeyRef{Name: appConfigTestCm3.Name, Key: "conf31.yaml"}) testObj := createBackstageTest(bs).withDefaultConfig(true) testObj.externalConfig.AppConfigs = map[string]corev1.ConfigMap{appConfigTestCm.Name: appConfigTestCm, appConfigTestCm2.Name: appConfigTestCm2, @@ -127,7 +127,7 @@ func TestDefaultAndSpecifiedAppConfig(t *testing.T) { bs := *appConfigTestBackstage.DeepCopy() cms := &bs.Spec.Application.AppConfig.ConfigMaps - *cms = append(*cms, bsv1alpha1.ObjectKeyRef{Name: appConfigTestCm.Name}) + *cms = append(*cms, bsv1.ObjectKeyRef{Name: appConfigTestCm.Name}) testObj := createBackstageTest(bs).withDefaultConfig(true).addToDefaultConfig("app-config.yaml", "raw-app-config.yaml") diff --git a/pkg/model/configmapenvs.go b/pkg/model/configmapenvs.go index 205aaa13..6900da9a 100644 --- a/pkg/model/configmapenvs.go +++ b/pkg/model/configmapenvs.go @@ -15,7 +15,7 @@ package model import ( - "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" appsv1 "k8s.io/api/apps/v1" @@ -38,7 +38,7 @@ func init() { registerConfig("configmap-envs.yaml", ConfigMapEnvsFactory{}) } -func addConfigMapEnvs(spec v1alpha1.BackstageSpec, deployment *appsv1.Deployment, model *BackstageModel) { +func addConfigMapEnvs(spec v1alpha2.BackstageSpec, deployment *appsv1.Deployment, model *BackstageModel) { if spec.Application == nil || spec.Application.ExtraEnvs == nil || spec.Application.ExtraEnvs.ConfigMaps == nil { return @@ -72,7 +72,7 @@ func (p *ConfigMapEnvs) EmptyObject() client.Object { } // implementation of RuntimeObject interface -func (p *ConfigMapEnvs) addToModel(model *BackstageModel, _ v1alpha1.Backstage) (bool, error) { +func (p *ConfigMapEnvs) addToModel(model *BackstageModel, _ v1alpha2.Backstage) (bool, error) { if p.ConfigMap != nil { model.setRuntimeObject(p) return true, nil @@ -81,7 +81,7 @@ func (p *ConfigMapEnvs) addToModel(model *BackstageModel, _ v1alpha1.Backstage) } // implementation of RuntimeObject interface -func (p *ConfigMapEnvs) validate(_ *BackstageModel, _ v1alpha1.Backstage) error { +func (p *ConfigMapEnvs) validate(_ *BackstageModel, _ v1alpha2.Backstage) error { return nil } diff --git a/pkg/model/configmapenvs_test.go b/pkg/model/configmapenvs_test.go index aa3b4846..da62e10f 100644 --- a/pkg/model/configmapenvs_test.go +++ b/pkg/model/configmapenvs_test.go @@ -22,7 +22,7 @@ import ( corev1 "k8s.io/api/core/v1" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -31,13 +31,13 @@ import ( func TestDefaultConfigMapEnvFrom(t *testing.T) { - bs := bsv1alpha1.Backstage{ + bs := bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Database: &bsv1alpha1.Database{ + Spec: bsv1.BackstageSpec{ + Database: &bsv1.Database{ EnableLocalDb: ptr.To(false), }, }, @@ -60,22 +60,22 @@ func TestDefaultConfigMapEnvFrom(t *testing.T) { func TestSpecifiedConfigMapEnvs(t *testing.T) { - bs := bsv1alpha1.Backstage{ + bs := bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Application: &bsv1alpha1.Application{ - ExtraEnvs: &bsv1alpha1.ExtraEnvs{ - ConfigMaps: []bsv1alpha1.ObjectKeyRef{}, + Spec: bsv1.BackstageSpec{ + Application: &bsv1.Application{ + ExtraEnvs: &bsv1.ExtraEnvs{ + ConfigMaps: []bsv1.ObjectKeyRef{}, }, }, }, } bs.Spec.Application.ExtraEnvs.ConfigMaps = append(bs.Spec.Application.ExtraEnvs.ConfigMaps, - bsv1alpha1.ObjectKeyRef{Name: "mapName", Key: "ENV1"}) + bsv1.ObjectKeyRef{Name: "mapName", Key: "ENV1"}) testObj := createBackstageTest(bs).withDefaultConfig(true) testObj.externalConfig.ExtraEnvConfigMaps["mapName"] = corev1.ConfigMap{Data: map[string]string{"mapName": "ENV1"}} diff --git a/pkg/model/configmapfiles.go b/pkg/model/configmapfiles.go index 1977987a..78c17efa 100644 --- a/pkg/model/configmapfiles.go +++ b/pkg/model/configmapfiles.go @@ -17,7 +17,7 @@ package model import ( appsv1 "k8s.io/api/apps/v1" - "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" corev1 "k8s.io/api/core/v1" @@ -40,7 +40,7 @@ func init() { registerConfig("configmap-files.yaml", ConfigMapFilesFactory{}) } -func addConfigMapFiles(spec v1alpha1.BackstageSpec, deployment *appsv1.Deployment, model *BackstageModel) { +func addConfigMapFiles(spec v1alpha2.BackstageSpec, deployment *appsv1.Deployment, model *BackstageModel) { if spec.Application == nil || spec.Application.ExtraFiles == nil || spec.Application.ExtraFiles.ConfigMaps == nil { return @@ -80,7 +80,7 @@ func (p *ConfigMapFiles) EmptyObject() client.Object { } // implementation of RuntimeObject interface -func (p *ConfigMapFiles) addToModel(model *BackstageModel, _ v1alpha1.Backstage) (bool, error) { +func (p *ConfigMapFiles) addToModel(model *BackstageModel, _ v1alpha2.Backstage) (bool, error) { if p.ConfigMap != nil { model.setRuntimeObject(p) return true, nil @@ -89,7 +89,7 @@ func (p *ConfigMapFiles) addToModel(model *BackstageModel, _ v1alpha1.Backstage) } // implementation of RuntimeObject interface -func (p *ConfigMapFiles) validate(_ *BackstageModel, _ v1alpha1.Backstage) error { +func (p *ConfigMapFiles) validate(_ *BackstageModel, _ v1alpha2.Backstage) error { return nil } diff --git a/pkg/model/configmapfiles_test.go b/pkg/model/configmapfiles_test.go index 9dedb06a..2f0d711c 100644 --- a/pkg/model/configmapfiles_test.go +++ b/pkg/model/configmapfiles_test.go @@ -17,7 +17,7 @@ package model import ( "context" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -43,16 +43,16 @@ var ( // Data: map[string]string{"conf2.yaml": ""}, //} - configMapFilesTestBackstage = bsv1alpha1.Backstage{ + configMapFilesTestBackstage = bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Application: &bsv1alpha1.Application{ - ExtraFiles: &bsv1alpha1.ExtraFiles{ + Spec: bsv1.BackstageSpec{ + Application: &bsv1.Application{ + ExtraFiles: &bsv1.ExtraFiles{ MountPath: "/my/path", - ConfigMaps: []bsv1alpha1.ObjectKeyRef{}, + ConfigMaps: []bsv1.ObjectKeyRef{}, }, }, }, @@ -81,8 +81,8 @@ func TestSpecifiedConfigMapFiles(t *testing.T) { bs := *configMapFilesTestBackstage.DeepCopy() cmf := &bs.Spec.Application.ExtraFiles.ConfigMaps - *cmf = append(*cmf, bsv1alpha1.ObjectKeyRef{Name: appConfigTestCm.Name}) - *cmf = append(*cmf, bsv1alpha1.ObjectKeyRef{Name: appConfigTestCm2.Name}) + *cmf = append(*cmf, bsv1.ObjectKeyRef{Name: appConfigTestCm.Name}) + *cmf = append(*cmf, bsv1.ObjectKeyRef{Name: appConfigTestCm2.Name}) testObj := createBackstageTest(bs).withDefaultConfig(true) @@ -104,7 +104,7 @@ func TestDefaultAndSpecifiedConfigMapFiles(t *testing.T) { bs := *configMapFilesTestBackstage.DeepCopy() cmf := &bs.Spec.Application.ExtraFiles.ConfigMaps - *cmf = append(*cmf, bsv1alpha1.ObjectKeyRef{Name: appConfigTestCm.Name}) + *cmf = append(*cmf, bsv1.ObjectKeyRef{Name: appConfigTestCm.Name}) testObj := createBackstageTest(bs).withDefaultConfig(true).addToDefaultConfig("configmap-files.yaml", "raw-cm-files.yaml") diff --git a/pkg/model/db-secret.go b/pkg/model/db-secret.go index f6c3d7d3..99c8fe31 100644 --- a/pkg/model/db-secret.go +++ b/pkg/model/db-secret.go @@ -17,7 +17,7 @@ package model import ( "strconv" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" corev1 "k8s.io/api/core/v1" @@ -56,7 +56,7 @@ func (b *DbSecret) setObject(obj client.Object) { } // implementation of RuntimeObject interface -func (b *DbSecret) addToModel(model *BackstageModel, backstage bsv1alpha1.Backstage) (bool, error) { +func (b *DbSecret) addToModel(model *BackstageModel, backstage bsv1.Backstage) (bool, error) { // do not add if specified if backstage.Spec.IsAuthSecretSpecified() { @@ -78,7 +78,7 @@ func (b *DbSecret) EmptyObject() client.Object { } // implementation of RuntimeObject interface -func (b *DbSecret) validate(model *BackstageModel, backstage bsv1alpha1.Backstage) error { +func (b *DbSecret) validate(model *BackstageModel, backstage bsv1.Backstage) error { pswd, _ := utils.GeneratePassword(24) diff --git a/pkg/model/db-secret_test.go b/pkg/model/db-secret_test.go index 96f4ce1d..3d292a8b 100644 --- a/pkg/model/db-secret_test.go +++ b/pkg/model/db-secret_test.go @@ -21,20 +21,20 @@ import ( "k8s.io/utils/ptr" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/stretchr/testify/assert" ) -var dbSecretBackstage = &bsv1alpha1.Backstage{ +var dbSecretBackstage = &bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Database: &bsv1alpha1.Database{ + Spec: bsv1.BackstageSpec{ + Database: &bsv1.Database{ EnableLocalDb: ptr.To(false), }, }, diff --git a/pkg/model/db-service.go b/pkg/model/db-service.go index fb47c7c4..ba42a237 100644 --- a/pkg/model/db-service.go +++ b/pkg/model/db-service.go @@ -17,7 +17,7 @@ package model import ( "fmt" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" corev1 "k8s.io/api/core/v1" @@ -55,7 +55,7 @@ func (b *DbService) setObject(obj client.Object) { } // implementation of RuntimeObject interface -func (b *DbService) addToModel(model *BackstageModel, _ bsv1alpha1.Backstage) (bool, error) { +func (b *DbService) addToModel(model *BackstageModel, _ bsv1.Backstage) (bool, error) { if b.service == nil { if model.localDbEnabled { return false, fmt.Errorf("LocalDb Service not initialized, make sure there is db-service.yaml.yaml in default or raw configuration") @@ -82,7 +82,7 @@ func (b *DbService) EmptyObject() client.Object { } // implementation of RuntimeObject interface -func (b *DbService) validate(_ *BackstageModel, _ bsv1alpha1.Backstage) error { +func (b *DbService) validate(_ *BackstageModel, _ bsv1.Backstage) error { return nil } diff --git a/pkg/model/db-statefulset.go b/pkg/model/db-statefulset.go index c47bdec2..4e6a3dae 100644 --- a/pkg/model/db-statefulset.go +++ b/pkg/model/db-statefulset.go @@ -20,7 +20,7 @@ import ( corev1 "k8s.io/api/core/v1" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" appsv1 "k8s.io/api/apps/v1" @@ -60,7 +60,7 @@ func (b *DbStatefulSet) setObject(obj client.Object) { } // implementation of RuntimeObject interface -func (b *DbStatefulSet) addToModel(model *BackstageModel, _ bsv1alpha1.Backstage) (bool, error) { +func (b *DbStatefulSet) addToModel(model *BackstageModel, _ bsv1.Backstage) (bool, error) { if b.statefulSet == nil { if model.localDbEnabled { return false, fmt.Errorf("LocalDb StatefulSet not configured, make sure there is db-statefulset.yaml.yaml in default or raw configuration") @@ -90,14 +90,15 @@ func (b *DbStatefulSet) EmptyObject() client.Object { } // implementation of RuntimeObject interface -func (b *DbStatefulSet) validate(model *BackstageModel, backstage bsv1alpha1.Backstage) error { +func (b *DbStatefulSet) validate(model *BackstageModel, backstage bsv1.Backstage) error { // point ServiceName to localDb b.statefulSet.Spec.ServiceName = model.LocalDbService.service.Name - if backstage.Spec.Application != nil { + if backstage.Spec.Application != nil && backstage.Spec.Application.ImagePullSecrets != nil { utils.SetImagePullSecrets(b.podSpec(), backstage.Spec.Application.ImagePullSecrets) } + if backstage.Spec.IsAuthSecretSpecified() { utils.SetDbSecretEnvVar(b.container(), backstage.Spec.Database.AuthSecretName) } else if model.LocalDbSecret != nil { diff --git a/pkg/model/db-statefulset_test.go b/pkg/model/db-statefulset_test.go index 699ee377..24ceddac 100644 --- a/pkg/model/db-statefulset_test.go +++ b/pkg/model/db-statefulset_test.go @@ -23,21 +23,21 @@ import ( "k8s.io/utils/ptr" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/stretchr/testify/assert" ) -var dbStatefulSetBackstage = &bsv1alpha1.Backstage{ +var dbStatefulSetBackstage = &bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Database: &bsv1alpha1.Database{}, - Application: &bsv1alpha1.Application{}, + Spec: bsv1.BackstageSpec{ + Database: &bsv1.Database{}, + Application: &bsv1.Application{}, }, } diff --git a/pkg/model/deployment.go b/pkg/model/deployment.go index 39ef9d98..607c425c 100644 --- a/pkg/model/deployment.go +++ b/pkg/model/deployment.go @@ -18,11 +18,16 @@ import ( "fmt" "os" + kyaml "sigs.k8s.io/kustomize/kyaml/yaml" + "sigs.k8s.io/kustomize/kyaml/yaml/merge2" + + "sigs.k8s.io/yaml" + "k8s.io/utils/ptr" corev1 "k8s.io/api/core/v1" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" @@ -70,7 +75,7 @@ func (b *BackstageDeployment) EmptyObject() client.Object { } // implementation of RuntimeObject interface -func (b *BackstageDeployment) addToModel(model *BackstageModel, _ bsv1alpha1.Backstage) (bool, error) { +func (b *BackstageDeployment) addToModel(model *BackstageModel, backstage bsv1.Backstage) (bool, error) { if b.deployment == nil { return false, fmt.Errorf("Backstage Deployment is not initialized, make sure there is deployment.yaml in default or raw configuration") } @@ -80,6 +85,10 @@ func (b *BackstageDeployment) addToModel(model *BackstageModel, _ bsv1alpha1.Bac } b.deployment.Spec.Template.ObjectMeta.Annotations[ExtConfigHashAnnotation] = model.ExternalConfig.GetHash() + if err := b.setDeployment(backstage); err != nil { + return false, err + } + model.backstageDeployment = b model.setRuntimeObject(b) @@ -93,14 +102,7 @@ func (b *BackstageDeployment) addToModel(model *BackstageModel, _ bsv1alpha1.Bac } // implementation of RuntimeObject interface -func (b *BackstageDeployment) validate(model *BackstageModel, backstage bsv1alpha1.Backstage) error { - - if backstage.Spec.Application != nil { - b.setReplicas(backstage.Spec.Application.Replicas) - utils.SetImagePullSecrets(b.podSpec(), backstage.Spec.Application.ImagePullSecrets) - b.setImage(backstage.Spec.Application.Image) - b.addExtraEnvs(backstage.Spec.Application.ExtraEnvs) - } +func (b *BackstageDeployment) validate(model *BackstageModel, backstage bsv1.Backstage) error { for _, bso := range model.RuntimeObjects { if bs, ok := bso.(BackstagePodContributor); ok { @@ -149,6 +151,39 @@ func (b *BackstageDeployment) podSpec() *corev1.PodSpec { return &b.deployment.Spec.Template.Spec } +func (b *BackstageDeployment) setDeployment(backstage bsv1.Backstage) error { + + // set from backstage.Spec.Application + if backstage.Spec.Application != nil { + b.setReplicas(backstage.Spec.Application.Replicas) + utils.SetImagePullSecrets(b.podSpec(), backstage.Spec.Application.ImagePullSecrets) + b.setImage(backstage.Spec.Application.Image) + b.addExtraEnvs(backstage.Spec.Application.ExtraEnvs) + } + + // set from backstage.Spec.Deployment + if backstage.Spec.Deployment != nil { + if conf := backstage.Spec.Deployment.Patch; conf != nil { + + deplStr, err := yaml.Marshal(b.deployment) + if err != nil { + return fmt.Errorf("can not marshal deployment object: %w", err) + } + + merged, err := merge2.MergeStrings(string(conf.Raw), string(deplStr), false, kyaml.MergeOptions{}) + if err != nil { + return fmt.Errorf("can not merge spec.deployment: %w", err) + } + + err = yaml.Unmarshal([]byte(merged), b.deployment) + if err != nil { + return fmt.Errorf("can not unmarshal merged deployment: %w", err) + } + } + } + return nil +} + // sets the amount of replicas (used by CR config) func (b *BackstageDeployment) setReplicas(replicas *int32) { if replicas != nil { @@ -174,7 +209,7 @@ func (b *BackstageDeployment) setImage(image *string) { } // adds environment variables to the Backstage Container -func (b *BackstageDeployment) addContainerEnvVar(env bsv1alpha1.Env) { +func (b *BackstageDeployment) addContainerEnvVar(env bsv1.Env) { b.container().Env = append(b.deployment.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{ Name: env.Name, @@ -183,7 +218,7 @@ func (b *BackstageDeployment) addContainerEnvVar(env bsv1alpha1.Env) { } // adds environment from source to the Backstage Container -func (b *BackstageDeployment) addExtraEnvs(extraEnvs *bsv1alpha1.ExtraEnvs) { +func (b *BackstageDeployment) addExtraEnvs(extraEnvs *bsv1.ExtraEnvs) { if extraEnvs != nil { for _, e := range extraEnvs.Envs { b.addContainerEnvVar(e) diff --git a/pkg/model/deployment_test.go b/pkg/model/deployment_test.go index 261ceb86..f257cbaa 100644 --- a/pkg/model/deployment_test.go +++ b/pkg/model/deployment_test.go @@ -18,25 +18,27 @@ import ( "context" "testing" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/utils/ptr" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/stretchr/testify/assert" ) -var deploymentTestBackstage = bsv1alpha1.Backstage{ +var deploymentTestBackstage = bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Database: &bsv1alpha1.Database{ + Spec: bsv1.BackstageSpec{ + Database: &bsv1.Database{ EnableLocalDb: ptr.To(false), }, - Application: &bsv1alpha1.Application{}, + Application: &bsv1.Application{}, }, } @@ -104,3 +106,94 @@ func TestSpecImagePullSecrets(t *testing.T) { assert.Equal(t, 0, len(model.backstageDeployment.deployment.Spec.Template.Spec.ImagePullSecrets)) } + +func TestMergeFromSpecDeployment(t *testing.T) { + bs := *deploymentTestBackstage.DeepCopy() + bs.Spec.Deployment = &bsv1.BackstageDeployment{} + bs.Spec.Deployment.Patch = &apiextensionsv1.JSON{ + Raw: []byte(` +metadata: + labels: + mylabel: java +spec: + template: + metadata: + labels: + pod: backstage + spec: + containers: + - name: sidecar + image: my-image:1.0.0 + - name: backstage-backend + resources: + requests: + cpu: 251m + memory: 257Mi + volumes: + - ephemeral: + volumeClaimTemplate: + spec: + storageClassName: "special" + name: dynamic-plugins-root + - emptyDir: + name: my-vol +`), + } + + testObj := createBackstageTest(bs).withDefaultConfig(true). + addToDefaultConfig("deployment.yaml", "janus-deployment.yaml") + + model, err := InitObjects(context.TODO(), bs, testObj.externalConfig, true, true, testObj.scheme) + assert.NoError(t, err) + + // label added + assert.Equal(t, "java", model.backstageDeployment.deployment.Labels["mylabel"]) + assert.Equal(t, "backstage", model.backstageDeployment.deployment.Spec.Template.Labels["pod"]) + + // sidecar added + assert.Equal(t, 2, len(model.backstageDeployment.deployment.Spec.Template.Spec.Containers)) + assert.Equal(t, "sidecar", model.backstageDeployment.deployment.Spec.Template.Spec.Containers[1].Name) + assert.Equal(t, "my-image:1.0.0", model.backstageDeployment.deployment.Spec.Template.Spec.Containers[1].Image) + + // backstage container resources updated + assert.Equal(t, "backstage-backend", model.backstageDeployment.container().Name) + assert.Equal(t, "257Mi", model.backstageDeployment.container().Resources.Requests.Memory().String()) + + // volumes + // dynamic-plugins-root, dynamic-plugins-npmrc, my-vol + assert.Equal(t, 3, len(model.backstageDeployment.deployment.Spec.Template.Spec.Volumes)) + assert.Equal(t, "dynamic-plugins-root", model.backstageDeployment.deployment.Spec.Template.Spec.Volumes[0].Name) + // overrides StorageClassName + assert.Equal(t, "special", *model.backstageDeployment.deployment.Spec.Template.Spec.Volumes[0].Ephemeral.VolumeClaimTemplate.Spec.StorageClassName) + // adds new volume + assert.Equal(t, "my-vol", model.backstageDeployment.deployment.Spec.Template.Spec.Volumes[2].Name) +} + +// to remove when stop supporting v1alpha1 +func TestDeploymentFieldPrevailsOnDeprecated(t *testing.T) { + bs := *deploymentTestBackstage.DeepCopy() + bs.Spec.Application.Image = ptr.To("app-image") + bs.Spec.Application.Replicas = ptr.To(int32(2)) + bs.Spec.Deployment = &bsv1.BackstageDeployment{} + bs.Spec.Deployment.Patch = &apiextensionsv1.JSON{ + Raw: []byte(` +spec: + replicas: 3 + template: + spec: + containers: + - name: backstage-backend + image: deployment-image +`), + } + + testObj := createBackstageTest(bs).withDefaultConfig(true). + addToDefaultConfig("deployment.yaml", "janus-deployment.yaml") + + model, err := InitObjects(context.TODO(), bs, testObj.externalConfig, true, true, testObj.scheme) + assert.NoError(t, err) + + assert.Equal(t, "backstage-backend", model.backstageDeployment.container().Name) + assert.Equal(t, "deployment-image", model.backstageDeployment.container().Image) + assert.Equal(t, int32(3), *model.backstageDeployment.deployment.Spec.Replicas) +} diff --git a/pkg/model/dynamic-plugins.go b/pkg/model/dynamic-plugins.go index f55dbd5c..f0235ea0 100644 --- a/pkg/model/dynamic-plugins.go +++ b/pkg/model/dynamic-plugins.go @@ -20,7 +20,7 @@ import ( appsv1 "k8s.io/api/apps/v1" - "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" corev1 "k8s.io/api/core/v1" @@ -48,7 +48,7 @@ func DynamicPluginsDefaultName(backstageName string) string { return utils.GenerateRuntimeObjectName(backstageName, "backstage-dynamic-plugins") } -func addDynamicPlugins(spec v1alpha1.BackstageSpec, deployment *appsv1.Deployment, model *BackstageModel) error { +func addDynamicPlugins(spec v1alpha2.BackstageSpec, deployment *appsv1.Deployment, model *BackstageModel) error { if spec.Application == nil || spec.Application.DynamicPluginsConfigMapName == "" { return nil @@ -88,7 +88,7 @@ func (p *DynamicPlugins) EmptyObject() client.Object { } // implementation of RuntimeObject interface -func (p *DynamicPlugins) addToModel(model *BackstageModel, backstage v1alpha1.Backstage) (bool, error) { +func (p *DynamicPlugins) addToModel(model *BackstageModel, backstage v1alpha2.Backstage) (bool, error) { if p.ConfigMap == nil || (backstage.Spec.Application != nil && backstage.Spec.Application.DynamicPluginsConfigMapName != "") { return false, nil @@ -124,7 +124,7 @@ func (p *DynamicPlugins) updatePod(deployment *appsv1.Deployment) { // implementation of RuntimeObject interface // ConfigMap name must be the same as (deployment.yaml).spec.template.spec.volumes.name.dynamic-plugins-conf.ConfigMap.name -func (p *DynamicPlugins) validate(model *BackstageModel, _ v1alpha1.Backstage) error { +func (p *DynamicPlugins) validate(model *BackstageModel, _ v1alpha2.Backstage) error { _, initContainer := DynamicPluginsInitContainer(model.backstageDeployment.deployment.Spec.Template.Spec.InitContainers) if initContainer == nil { diff --git a/pkg/model/dynamic-plugins_test.go b/pkg/model/dynamic-plugins_test.go index 5bac21c0..7c4f7351 100644 --- a/pkg/model/dynamic-plugins_test.go +++ b/pkg/model/dynamic-plugins_test.go @@ -21,7 +21,7 @@ import ( "k8s.io/utils/ptr" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -29,16 +29,16 @@ import ( "github.com/stretchr/testify/assert" ) -var testDynamicPluginsBackstage = bsv1alpha1.Backstage{ +var testDynamicPluginsBackstage = bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Database: &bsv1alpha1.Database{ + Spec: bsv1.BackstageSpec{ + Database: &bsv1.Database{ EnableLocalDb: ptr.To(false), }, - Application: &bsv1alpha1.Application{}, + Application: &bsv1.Application{}, }, } diff --git a/pkg/model/interfaces.go b/pkg/model/interfaces.go index 859ce115..cc679590 100644 --- a/pkg/model/interfaces.go +++ b/pkg/model/interfaces.go @@ -15,7 +15,7 @@ package model import ( - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" appsv1 "k8s.io/api/apps/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -45,10 +45,10 @@ type RuntimeObject interface { EmptyObject() client.Object // adds runtime object to the model // returns false if the object was not added to the model (not configured) - addToModel(model *BackstageModel, backstage bsv1alpha1.Backstage) (bool, error) + addToModel(model *BackstageModel, backstage bsv1.Backstage) (bool, error) // at this stage all the information is updated // set the final references validates the object at the end of initialization - validate(model *BackstageModel, backstage bsv1alpha1.Backstage) error + validate(model *BackstageModel, backstage bsv1.Backstage) error // sets object name, labels and other necessary meta information setMetaInfo(backstageName string) } diff --git a/pkg/model/model_tests.go b/pkg/model/model_tests.go index 3948d2c8..7dde3751 100644 --- a/pkg/model/model_tests.go +++ b/pkg/model/model_tests.go @@ -27,22 +27,22 @@ import ( "k8s.io/apimachinery/pkg/runtime" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" ) // testBackstageObject it is a helper object to simplify testing model component allowing to customize and isolate testing configuration // usual sequence of creating testBackstageObject contains such a steps: -// createBackstageTest(bsv1alpha1.Backstage). +// createBackstageTest(bsv1.Backstage). // withDefaultConfig(useDef bool) // addToDefaultConfig(key, fileName) type testBackstageObject struct { - backstage bsv1alpha1.Backstage + backstage bsv1.Backstage externalConfig ExternalConfig scheme *runtime.Scheme } // initialises testBackstageObject object -func createBackstageTest(bs bsv1alpha1.Backstage) *testBackstageObject { +func createBackstageTest(bs bsv1.Backstage) *testBackstageObject { ec := ExternalConfig{ RawConfig: map[string]string{}, AppConfigs: map[string]corev1.ConfigMap{}, @@ -50,7 +50,7 @@ func createBackstageTest(bs bsv1alpha1.Backstage) *testBackstageObject { ExtraEnvConfigMaps: map[string]corev1.ConfigMap{}, } b := &testBackstageObject{backstage: bs, externalConfig: ec, scheme: runtime.NewScheme()} - utilruntime.Must(bsv1alpha1.AddToScheme(b.scheme)) + utilruntime.Must(bsv1.AddToScheme(b.scheme)) return b } diff --git a/pkg/model/route.go b/pkg/model/route.go index 56601949..02767af8 100644 --- a/pkg/model/route.go +++ b/pkg/model/route.go @@ -15,7 +15,7 @@ package model import ( - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" openshift "github.com/openshift/api/route/v1" @@ -36,7 +36,7 @@ func RouteName(backstageName string) string { return utils.GenerateRuntimeObjectName(backstageName, "backstage") } -func (b *BackstageRoute) setRoute(specified *bsv1alpha1.Route) { +func (b *BackstageRoute) setRoute(specified *bsv1.Route) { if len(specified.Host) > 0 { b.route.Spec.Host = specified.Host @@ -101,7 +101,7 @@ func (b *BackstageRoute) EmptyObject() client.Object { } // implementation of RuntimeObject interface -func (b *BackstageRoute) addToModel(model *BackstageModel, backstage bsv1alpha1.Backstage) (bool, error) { +func (b *BackstageRoute) addToModel(model *BackstageModel, backstage bsv1.Backstage) (bool, error) { // not Openshift if !model.isOpenshift { @@ -137,7 +137,7 @@ func (b *BackstageRoute) addToModel(model *BackstageModel, backstage bsv1alpha1. } // implementation of RuntimeObject interface -func (b *BackstageRoute) validate(model *BackstageModel, _ bsv1alpha1.Backstage) error { +func (b *BackstageRoute) validate(model *BackstageModel, _ bsv1.Backstage) error { b.route.Spec.To.Name = model.backstageService.service.Name return nil } diff --git a/pkg/model/route_test.go b/pkg/model/route_test.go index c035af39..9189ce14 100644 --- a/pkg/model/route_test.go +++ b/pkg/model/route_test.go @@ -24,20 +24,20 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "github.com/stretchr/testify/assert" ) func TestDefaultRoute(t *testing.T) { - bs := bsv1alpha1.Backstage{ + bs := bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "TestSpecifiedRoute", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Application: &bsv1alpha1.Application{ - Route: &bsv1alpha1.Route{}, + Spec: bsv1.BackstageSpec{ + Application: &bsv1.Application{ + Route: &bsv1.Route{}, }, }, } @@ -63,14 +63,14 @@ func TestDefaultRoute(t *testing.T) { } func TestSpecifiedRoute(t *testing.T) { - bs := bsv1alpha1.Backstage{ + bs := bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "TestSpecifiedRoute", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Application: &bsv1alpha1.Application{ - Route: &bsv1alpha1.Route{ + Spec: bsv1.BackstageSpec{ + Application: &bsv1.Application{ + Route: &bsv1.Route{ Enabled: ptr.To(true), Host: "TestSpecifiedRoute", //TLS: nil, @@ -109,14 +109,14 @@ func TestSpecifiedRoute(t *testing.T) { func TestDisabledRoute(t *testing.T) { // Route.Enabled = false - bs := bsv1alpha1.Backstage{ + bs := bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "TestSpecifiedRoute", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Application: &bsv1alpha1.Application{ - Route: &bsv1alpha1.Route{ + Spec: bsv1.BackstageSpec{ + Application: &bsv1.Application{ + Route: &bsv1.Route{ Enabled: ptr.To(false), Host: "TestSpecifiedRoute", //TLS: nil, @@ -141,12 +141,12 @@ func TestDisabledRoute(t *testing.T) { func TestExcludedRoute(t *testing.T) { // No route configured - bs := bsv1alpha1.Backstage{ + bs := bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "TestSpecifiedRoute", Namespace: "ns123", }, - //Spec: bsv1alpha1.BackstageSpec{ // //Application: &bsv1alpha1.Application{}, + //Spec: bsv1.BackstageSpec{ // //Application: &bsv1.Application{}, //}, } @@ -165,14 +165,14 @@ func TestExcludedRoute(t *testing.T) { func TestEnabledRoute(t *testing.T) { // Route is enabled by default if configured - bs := bsv1alpha1.Backstage{ + bs := bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "TestSpecifiedRoute", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Application: &bsv1alpha1.Application{ - Route: &bsv1alpha1.Route{}, + Spec: bsv1.BackstageSpec{ + Application: &bsv1.Application{ + Route: &bsv1.Route{}, }, }, } diff --git a/pkg/model/runtime.go b/pkg/model/runtime.go index 82f3f3db..cdf26b49 100644 --- a/pkg/model/runtime.go +++ b/pkg/model/runtime.go @@ -29,7 +29,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" ) @@ -105,7 +105,7 @@ func registerConfig(key string, factory ObjectFactory) { } // InitObjects performs a main loop for configuring and making the array of objects to reconcile -func InitObjects(ctx context.Context, backstage bsv1alpha1.Backstage, externalConfig ExternalConfig, ownsRuntime bool, isOpenshift bool, scheme *runtime.Scheme) (*BackstageModel, error) { +func InitObjects(ctx context.Context, backstage bsv1.Backstage, externalConfig ExternalConfig, ownsRuntime bool, isOpenshift bool, scheme *runtime.Scheme) (*BackstageModel, error) { // 3 phases of Backstage configuration: // 1- load from Operator defaults, modify metadata (labels, selectors..) and namespace as needed @@ -146,7 +146,7 @@ func InitObjects(ctx context.Context, backstage bsv1alpha1.Backstage, externalCo // apply spec and add the object to the model and list if added, err := backstageObject.addToModel(model, backstage); err != nil { - return nil, fmt.Errorf("failed to initialize %s reason: %s", backstageObject, err) + return nil, fmt.Errorf("failed to initialize backstage, reason: %s", err) } else if added { setMetaInfo(backstageObject, backstage, ownsRuntime, scheme) } @@ -167,7 +167,7 @@ func InitObjects(ctx context.Context, backstage bsv1alpha1.Backstage, externalCo } // Every RuntimeObject.setMetaInfo should as minimum call this -func setMetaInfo(modelObject RuntimeObject, backstage bsv1alpha1.Backstage, ownsRuntime bool, scheme *runtime.Scheme) { +func setMetaInfo(modelObject RuntimeObject, backstage bsv1.Backstage, ownsRuntime bool, scheme *runtime.Scheme) { modelObject.setMetaInfo(backstage.Name) modelObject.Object().SetNamespace(backstage.Namespace) modelObject.Object().SetLabels(utils.SetKubeLabels(modelObject.Object().GetLabels(), backstage.Name)) diff --git a/pkg/model/runtime_test.go b/pkg/model/runtime_test.go index 3f5354cb..f69ac680 100644 --- a/pkg/model/runtime_test.go +++ b/pkg/model/runtime_test.go @@ -22,8 +22,8 @@ import ( "k8s.io/utils/ptr" - "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -42,13 +42,13 @@ func TestIfEmptyObjectsContainTypeinfo(t *testing.T) { // NOTE: to make it work locally env var LOCALBIN should point to the directory where default-config folder located func TestInitDefaultDeploy(t *testing.T) { - bs := v1alpha1.Backstage{ + bs := v1alpha2.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs", Namespace: "ns123", }, - Spec: v1alpha1.BackstageSpec{ - Database: &v1alpha1.Database{ + Spec: v1alpha2.BackstageSpec{ + Database: &v1alpha2.Database{ EnableLocalDb: ptr.To(false), }, }, @@ -78,13 +78,13 @@ func TestInitDefaultDeploy(t *testing.T) { func TestIfEmptyObjectIsValid(t *testing.T) { - bs := bsv1alpha1.Backstage{ + bs := bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Database: &bsv1alpha1.Database{ + Spec: bsv1.BackstageSpec{ + Database: &bsv1.Database{ EnableLocalDb: ptr.To(false), }, }, @@ -103,13 +103,13 @@ func TestIfEmptyObjectIsValid(t *testing.T) { func TestAddToModel(t *testing.T) { - bs := v1alpha1.Backstage{ + bs := v1alpha2.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs", Namespace: "ns123", }, - Spec: v1alpha1.BackstageSpec{ - Database: &v1alpha1.Database{ + Spec: v1alpha2.BackstageSpec{ + Database: &v1alpha2.Database{ EnableLocalDb: ptr.To(false), }, }, diff --git a/pkg/model/secretenvs.go b/pkg/model/secretenvs.go index a6277351..86ed9660 100644 --- a/pkg/model/secretenvs.go +++ b/pkg/model/secretenvs.go @@ -15,7 +15,7 @@ package model import ( - "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" appsv1 "k8s.io/api/apps/v1" @@ -44,7 +44,7 @@ func (p *SecretEnvs) Object() client.Object { return p.Secret } -func addSecretEnvs(spec v1alpha1.BackstageSpec, deployment *appsv1.Deployment) error { +func addSecretEnvs(spec v1alpha2.BackstageSpec, deployment *appsv1.Deployment) error { if spec.Application == nil || spec.Application.ExtraEnvs == nil || spec.Application.ExtraEnvs.Secrets == nil { return nil @@ -73,7 +73,7 @@ func (p *SecretEnvs) EmptyObject() client.Object { } // implementation of RuntimeObject interface -func (p *SecretEnvs) addToModel(model *BackstageModel, _ v1alpha1.Backstage) (bool, error) { +func (p *SecretEnvs) addToModel(model *BackstageModel, _ v1alpha2.Backstage) (bool, error) { if p.Secret != nil { model.setRuntimeObject(p) return true, nil @@ -82,7 +82,7 @@ func (p *SecretEnvs) addToModel(model *BackstageModel, _ v1alpha1.Backstage) (bo } // implementation of RuntimeObject interface -func (p *SecretEnvs) validate(_ *BackstageModel, _ v1alpha1.Backstage) error { +func (p *SecretEnvs) validate(_ *BackstageModel, _ v1alpha2.Backstage) error { return nil } diff --git a/pkg/model/secretfiles.go b/pkg/model/secretfiles.go index 17430ab3..93dec9e1 100644 --- a/pkg/model/secretfiles.go +++ b/pkg/model/secretfiles.go @@ -20,7 +20,7 @@ import ( appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" corev1 "k8s.io/api/core/v1" @@ -43,7 +43,7 @@ func init() { registerConfig("secret-files.yaml", SecretFilesFactory{}) } -func addSecretFiles(spec v1alpha1.BackstageSpec, deployment *appsv1.Deployment) error { +func addSecretFiles(spec v1alpha2.BackstageSpec, deployment *appsv1.Deployment) error { if spec.Application == nil || spec.Application.ExtraFiles == nil || spec.Application.ExtraFiles.Secrets == nil { return nil @@ -90,7 +90,7 @@ func (p *SecretFiles) EmptyObject() client.Object { } // implementation of RuntimeObject interface -func (p *SecretFiles) addToModel(model *BackstageModel, _ v1alpha1.Backstage) (bool, error) { +func (p *SecretFiles) addToModel(model *BackstageModel, _ v1alpha2.Backstage) (bool, error) { if p.Secret != nil { model.setRuntimeObject(p) return true, nil @@ -99,7 +99,7 @@ func (p *SecretFiles) addToModel(model *BackstageModel, _ v1alpha1.Backstage) (b } // implementation of RuntimeObject interface -func (p *SecretFiles) validate(_ *BackstageModel, _ v1alpha1.Backstage) error { +func (p *SecretFiles) validate(_ *BackstageModel, _ v1alpha2.Backstage) error { return nil } diff --git a/pkg/model/secretfiles_test.go b/pkg/model/secretfiles_test.go index 4a95110f..98718707 100644 --- a/pkg/model/secretfiles_test.go +++ b/pkg/model/secretfiles_test.go @@ -20,7 +20,7 @@ import ( "redhat-developer/red-hat-developer-hub-operator/pkg/utils" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -44,16 +44,16 @@ var ( // StringData: map[string]string{"conf2.yaml": ""}, //} - secretFilesTestBackstage = bsv1alpha1.Backstage{ + secretFilesTestBackstage = bsv1.Backstage{ ObjectMeta: metav1.ObjectMeta{ Name: "bs", Namespace: "ns123", }, - Spec: bsv1alpha1.BackstageSpec{ - Application: &bsv1alpha1.Application{ - ExtraFiles: &bsv1alpha1.ExtraFiles{ + Spec: bsv1.BackstageSpec{ + Application: &bsv1.Application{ + ExtraFiles: &bsv1.ExtraFiles{ MountPath: "/my/path", - Secrets: []bsv1alpha1.ObjectKeyRef{}, + Secrets: []bsv1.ObjectKeyRef{}, }, }, }, @@ -82,10 +82,10 @@ func TestSpecifiedSecretFiles(t *testing.T) { bs := *secretFilesTestBackstage.DeepCopy() sf := &bs.Spec.Application.ExtraFiles.Secrets - *sf = append(*sf, bsv1alpha1.ObjectKeyRef{Name: "secret1", Key: "conf.yaml"}) - *sf = append(*sf, bsv1alpha1.ObjectKeyRef{Name: "secret2", Key: "conf.yaml"}) + *sf = append(*sf, bsv1.ObjectKeyRef{Name: "secret1", Key: "conf.yaml"}) + *sf = append(*sf, bsv1.ObjectKeyRef{Name: "secret2", Key: "conf.yaml"}) // https://issues.redhat.com/browse/RHIDP-2246 - mounting secret/CM with dot in the name - *sf = append(*sf, bsv1alpha1.ObjectKeyRef{Name: "secret.dot", Key: "conf3.yaml"}) + *sf = append(*sf, bsv1.ObjectKeyRef{Name: "secret.dot", Key: "conf3.yaml"}) testObj := createBackstageTest(bs).withDefaultConfig(true) @@ -111,7 +111,7 @@ func TestDefaultAndSpecifiedSecretFiles(t *testing.T) { bs := *secretFilesTestBackstage.DeepCopy() sf := &bs.Spec.Application.ExtraFiles.Secrets - *sf = append(*sf, bsv1alpha1.ObjectKeyRef{Name: "secret1", Key: "conf.yaml"}) + *sf = append(*sf, bsv1.ObjectKeyRef{Name: "secret1", Key: "conf.yaml"}) testObj := createBackstageTest(bs).withDefaultConfig(true).addToDefaultConfig("secret-files.yaml", "raw-secret-files.yaml") model, err := InitObjects(context.TODO(), bs, testObj.externalConfig, true, false, testObj.scheme) diff --git a/pkg/model/service.go b/pkg/model/service.go index 519a77d6..5f03e7f0 100644 --- a/pkg/model/service.go +++ b/pkg/model/service.go @@ -17,7 +17,7 @@ package model import ( "fmt" - bsv1alpha1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha1" + bsv1 "redhat-developer/red-hat-developer-hub-operator/api/v1alpha2" "redhat-developer/red-hat-developer-hub-operator/pkg/utils" corev1 "k8s.io/api/core/v1" @@ -55,7 +55,7 @@ func (b *BackstageService) setObject(obj client.Object) { } // implementation of RuntimeObject interface -func (b *BackstageService) addToModel(model *BackstageModel, _ bsv1alpha1.Backstage) (bool, error) { +func (b *BackstageService) addToModel(model *BackstageModel, _ bsv1.Backstage) (bool, error) { if b.service == nil { return false, fmt.Errorf("Backstage Service is not initialized, make sure there is service.yaml in default or raw configuration") } @@ -72,7 +72,7 @@ func (b *BackstageService) EmptyObject() client.Object { } // implementation of RuntimeObject interface -func (b *BackstageService) validate(_ *BackstageModel, _ bsv1alpha1.Backstage) error { +func (b *BackstageService) validate(_ *BackstageModel, _ bsv1.Backstage) error { return nil }