From 7ac6a025286da8e7f9f5b174a371896ee39d5033 Mon Sep 17 00:00:00 2001 From: Lukas Piwowarski Date: Wed, 5 Nov 2025 10:34:51 -0500 Subject: [PATCH 01/10] Add OLS operator installation Implement automatic installation, version checking ,and lifecycle management of the OpenShift Lightspeed operator. Add support for both user-installed and instance-owned installation modes with proper ownership tracking. If the OLS operator has already been installed then the OpenStack Lightspeed operator checks it version. If the version is valied OpenStack Lightspeed utilizes the preinstalled OLS operator. If the OLS operator has not been already installed then the operator installs it. In this mode when the OpenStackLightspeed instance is created the OLS operator is automatically uninstalled as well. Whereas in the preinstalled OLS operator mode the OLS oeprator stays even after the removal of the OpenStackLightspeed instance. --- api/v1beta1/conditions.go | 10 + api/v1beta1/openstacklightspeed_types.go | 10 + cmd/main.go | 4 + ...ed.openstack.org_openstacklightspeeds.yaml | 11 +- config/manager/manager.yaml | 3 + config/rbac/role.yaml | 17 + internal/controller/funcs.go | 85 ++-- internal/controller/ols_install.go | 372 ++++++++++++++++++ .../openstacklightspeed_controller.go | 112 ++++-- 9 files changed, 558 insertions(+), 66 deletions(-) create mode 100644 internal/controller/ols_install.go diff --git a/api/v1beta1/conditions.go b/api/v1beta1/conditions.go index 52dcd1e0..ccdcb978 100644 --- a/api/v1beta1/conditions.go +++ b/api/v1beta1/conditions.go @@ -22,6 +22,10 @@ const ( // OpenStackLightspeedReadyCondition Status=True condition which indicates if OpenStackLightspeedReadyCondition // is configured and operational OpenStackLightspeedReadyCondition condition.Type = "OpenStackLightspeedReady" + + // OpenShift Lightspeed Operator Status=True condition which indicates if OpenShift Lightspeed is installed and + // operational and it can be used by OpenStack Lihgtspeed operator. + OpenShiftLightspeedOperatorReadyCondition condition.Type = "OpenShiftLightspeedOperatorReady" ) // Common Messages used by API objects. @@ -34,4 +38,10 @@ const ( // OpenStackLightspeedWaitingVectorDBMessage OpenStackLightspeedWaitingVectorDBMessage = "Waiting for OpenStackLightspeed vector DB pod to become ready" + + // OpenShiftLightspeedOperatorWaiting + OpenShiftLightspeedOperatorWaiting = "Waiting for the OpenShift Lightspeed operator to deploy." + + // OpenShiftLigthspeedOperatorReady + OpenShiftLightspeedOperatorReady = "OpenShift Lightspeed operator is ready." ) diff --git a/api/v1beta1/openstacklightspeed_types.go b/api/v1beta1/openstacklightspeed_types.go index 870d5895..15e826aa 100644 --- a/api/v1beta1/openstacklightspeed_types.go +++ b/api/v1beta1/openstacklightspeed_types.go @@ -67,6 +67,16 @@ type OpenStackLightspeedCore struct { // +kubebuilder:validation:Optional // MaxTokensForResponse defines the maximum number of tokens to be used for the response generation MaxTokensForResponse int `json:"maxTokensForResponse,omitempty"` + + // +kubebuilder:validation:Optional + // +kubebuilder:default="openshift-marketplace" + // Namespace where the CatalogSource containing the OLS operator is located + CatalogSourceNamespace string `json:"catalogSourceNamespace"` + + // +kubebuilder:validation:Optional + // +kubebuilder:default="redhat-operators" + // Name of the CatalogSource that contains the OLS Operator + CatalogSourceName string `json:"catalogSourceName"` } // OpenStackLightspeedStatus defines the observed state of OpenStackLightspeed diff --git a/cmd/main.go b/cmd/main.go index a4ac3b67..bca9e76c 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -35,6 +35,8 @@ import ( metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" + operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" + apiv1beta1 "github.com/openstack-lightspeed/operator/api/v1beta1" "github.com/openstack-lightspeed/operator/internal/controller" // +kubebuilder:scaffold:imports @@ -48,6 +50,8 @@ var ( func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + utilruntime.Must(operatorsv1alpha1.AddToScheme(scheme)) + utilruntime.Must(apiv1beta1.AddToScheme(scheme)) // +kubebuilder:scaffold:scheme } diff --git a/config/crd/bases/lightspeed.openstack.org_openstacklightspeeds.yaml b/config/crd/bases/lightspeed.openstack.org_openstacklightspeeds.yaml index 92457f46..391650a7 100644 --- a/config/crd/bases/lightspeed.openstack.org_openstacklightspeeds.yaml +++ b/config/crd/bases/lightspeed.openstack.org_openstacklightspeeds.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.16.5 name: openstacklightspeeds.lightspeed.openstack.org spec: group: lightspeed.openstack.org @@ -40,6 +40,15 @@ spec: spec: description: OpenStackLightspeedSpec defines the desired state of OpenStackLightspeed properties: + catalogSourceName: + default: redhat-operators + description: Name of the CatalogSource that contains the OLS Operator + type: string + catalogSourceNamespace: + default: openshift-marketplace + description: Namespace where the CatalogSource containing the OLS + operator is located + type: string llmCredentials: description: |- Secret name containing API token for the LLMEndpoint. The key for the field diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index bb70ff8f..d3fccc46 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -65,6 +65,9 @@ spec: - --health-probe-bind-address=:8081 image: controller:latest name: manager + env: + - name: "OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION" + value: "1.0.7" securityContext: allowPrivilegeEscalation: false capabilities: diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index a92552af..ffbf01f7 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -91,5 +91,22 @@ rules: resources: - clusterserviceversions verbs: + - delete - get - list + - patch + - update + - watch +- apiGroups: + - operators.coreos.com + resources: + - installplans + - subscriptions + verbs: + - create + - delete + - get + - list + - patch + - update + - watch diff --git a/internal/controller/funcs.go b/internal/controller/funcs.go index a1d29cbb..aa9cf733 100644 --- a/internal/controller/funcs.go +++ b/internal/controller/funcs.go @@ -63,6 +63,51 @@ const ( OLSConfigName = "cluster" ) +// RemoveOLSConfig attempts to remove the OLSConfig custom resource if it exists +// and is managed by the given OpenStackLightspeed instance. It first fetches the OLSConfig, +// checks whether the current OpenStackLightspeed instance is the owner (via label check), +// and if so, removes the finalizer and deletes the OLSConfig resource. +// Returns (true, nil) if the OLSConfig is not found (indicating it has already been deleted). +// Returns (true, nil) if the resource was deleted successfully, or (false, error) if any error occurs. +func RemoveOLSConfig( + ctx context.Context, + helper *common_helper.Helper, + instance *apiv1beta1.OpenStackLightspeed, +) (bool, error) { + olsConfig, err := GetOLSConfig(ctx, helper) + if err != nil && !k8s_errors.IsNotFound(err) { + return false, err + } else if err != nil && k8s_errors.IsNotFound(err) { + return true, nil + } + + _, err = controllerutil.CreateOrPatch(ctx, helper.GetClient(), &olsConfig, func() error { + ownerLabel := olsConfig.GetLabels()[OpenStackLightspeedOwnerIDLabel] + isInstanceOwnedOLSConfig := ownerLabel == string(instance.GetObjectMeta().GetUID()) + + if ownerLabel == "" || !isInstanceOwnedOLSConfig { + helper.GetLogger().Info("Skipping OLSConfig deletion as it is not managed by the OpenStackLightspeed instance") + return nil + } + + if ok := controllerutil.RemoveFinalizer(&olsConfig, helper.GetFinalizer()); !ok { + return fmt.Errorf("remove finalizer failed") + } + + return nil + }) + if err != nil { + return false, err + } + + err = helper.GetClient().Delete(ctx, &olsConfig) + if err != nil { + return false, err + } + + return true, nil +} + // GetOLSConfig returns OLSConfig if there is one present in the cluster. func GetOLSConfig(ctx context.Context, helper *common_helper.Helper) (uns.Unstructured, error) { OLSConfigGVR := schema.GroupVersionResource{ @@ -87,35 +132,6 @@ func GetOLSConfig(ctx context.Context, helper *common_helper.Helper) (uns.Unstru "OLSConfig") } -// IsOLSOperatorInstalled checks whether OLS Operator is already running in the cluster. -func IsOLSOperatorInstalled(ctx context.Context, helper *common_helper.Helper) (bool, error) { - csvGVR := schema.GroupVersionResource{ - Group: "operators.coreos.com", - Version: "v1alpha1", - Resource: "clusterserviceversions", - } - - csvList := &uns.UnstructuredList{} - csvList.SetGroupVersionKind(csvGVR.GroupVersion().WithKind("clusterserviceversion")) - - listOpts := []client.ListOption{ - client.InNamespace(""), // Retrieve from all namespaces - } - - err := helper.GetClient().List(ctx, csvList, listOpts...) - if err != nil { - return false, err - } - - for _, csv := range csvList.Items { - if strings.HasPrefix(csv.GetName(), "lightspeed-operator") { - return true, nil - } - } - - return false, nil -} - // PatchOLSConfig patches OLSConfig with information from OpenStackLightspeed instance. func PatchOLSConfig( helper *common_helper.Helper, @@ -397,3 +413,14 @@ func requeueWaitingPod(helper *common_helper.Helper, instance *apiv1beta1.OpenSt helper.GetLogger().Info(apiv1beta1.OpenStackLightspeedReadyMessage) return "", ctrl.Result{RequeueAfter: 5 * time.Second}, nil } + +// IsOwnedBy returns true if 'object' is owned by 'owner' based on OwnerReference UID. +func IsOwnedBy(object metav1.Object, owner metav1.Object) bool { + for _, ref := range object.GetOwnerReferences() { + if ref.UID == owner.GetUID() { + return true + } + } + return false +} + diff --git a/internal/controller/ols_install.go b/internal/controller/ols_install.go new file mode 100644 index 00000000..4263f957 --- /dev/null +++ b/internal/controller/ols_install.go @@ -0,0 +1,372 @@ +/* +Copyright 2025. + +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. +*/ + +// This file contains the logic for managing and ensuring the installation of +// the OpenShift Lightspeed (OLS) Operator in a cluster. +package controller + +import ( + "context" + "fmt" + "os" + "strings" + + apiv1beta1 "github.com/openstack-lightspeed/operator/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/client" + + common_helper "github.com/openstack-k8s-operators/lib-common/modules/common/helper" + operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" + k8s_errors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +const ( + // OLSOperatorName - Name of the OpenShift Lightspeed operator. + OLSOperatorName = "lightspeed-operator" +) + +// EnsureOLSOperatorInstalled ensures that a compatible OLS Operator is present in the cluster. +// If the operator already exists, this checks that it matches the required version (otherwise it fails). +// If it is missing, this attempts to install the correct version. +func EnsureOLSOperatorInstalled( + ctx context.Context, + helper *common_helper.Helper, + instance *apiv1beta1.OpenStackLightspeed, +) (bool, error) { + isUserInstalledOLSOperator, err := IsUserInstalledOLSOperatorMode(ctx, helper, instance) + if err != nil { + return false, err + } + + if isUserInstalledOLSOperator { + return CheckOLSOperatorVersion(ctx, helper, instance) + } + + OLSOperatorInstalled, err := InstallInstanceOwnedOLSOperator(ctx, helper, instance) + if err != nil { + return false, err + } + + return OLSOperatorInstalled, nil +} + +// InstallInstanceOwnedOLSOperator - ensures that the OpenShift Lightspeed Operator (OLS Operator) +// is installed and owned by the specified OpenStackLightspeed instance. This function: +// 1. Determines the recommended OLS Operator version. +// 2. Creates or updates a Subscription, setting the instance as its owner. +// 3. Approves the related InstallPlan manually. +// 4. Sets ownership of the generated ClusterServiceVersion (CSV) to the instance. +// 5. Returns true if the OLS Operator is installed and owned by the instance, or an error otherwise. +func InstallInstanceOwnedOLSOperator( + ctx context.Context, + helper *common_helper.Helper, + instance *apiv1beta1.OpenStackLightspeed, +) (bool, error) { + olsVersion, err := GetRecommendedOLSVersion() + if err != nil { + return false, err + } + + subscription := &operatorsv1alpha1.Subscription{ + ObjectMeta: metav1.ObjectMeta{ + Name: GetOLSSubscriptionName(instance), + Namespace: instance.Namespace, + }, + } + + instanceOwnerReference := []metav1.OwnerReference{ + { + APIVersion: instance.APIVersion, + Kind: instance.Kind, + Name: instance.GetName(), + UID: instance.GetUID(), + Controller: ptr.To(true), + BlockOwnerDeletion: ptr.To(true), + }, + } + opResult, err := controllerutil.CreateOrUpdate(ctx, helper.GetClient(), subscription, func() error { + subscription.Spec = &operatorsv1alpha1.SubscriptionSpec{ + Channel: "stable", + InstallPlanApproval: operatorsv1alpha1.ApprovalManual, + CatalogSource: instance.Spec.CatalogSourceName, + CatalogSourceNamespace: instance.Spec.CatalogSourceNamespace, + Package: OLSOperatorName, + StartingCSV: fmt.Sprintf("%s.v%s", OLSOperatorName, olsVersion), + } + + subscription.SetOwnerReferences(instanceOwnerReference) + + return nil + }) + if err != nil { + return false, err + } + + // If the Subscription was just created, or if it doesn't yet contain an InstallPlanRef, + // return (false, nil) -> wait. Attempting to approve the InstallPlan before it is properly + // linked can cause OLM to create unnecessary additional InstallPlans. + if opResult != controllerutil.OperationResultNone || subscription.Status.InstallPlanRef == nil { + return false, nil + } + + // Because we've set the subscription to require manual approval, we need to explicitly + // approve the InstallPlan at this point. Manual approval is used to prevent OLM from + // automatically upgrading the operator to a newer version than we've tested. This way, + // we ensure that only the specific OLS Operator version we've tested is installed. + installPlanApproved, err := ApproveOLSOperatorInstallPlan(ctx, helper, instance) + if err != nil { + return false, err + } else if !installPlanApproved { + return false, nil + } + + // Ensure the CSV is owned by this instance. This helps determine during + // deletion if the OLS Operator was installed by us or pre-existed before + // the instance. + OLSOperatorCSV, err := GetOLSOperatorCSV(ctx, helper) + if err != nil { + return false, err + } else if OLSOperatorCSV == nil { + return false, nil + } + + OLSOperatorCSV.SetOwnerReferences(instanceOwnerReference) + err = helper.GetClient().Update(ctx, OLSOperatorCSV) + if err != nil && k8s_errors.IsConflict(err) { + return false, nil + } else if err != nil { + return false, err + } + + return InstanceOwnedOLSOperatorComplete(ctx, helper, instance) +} + +// InstanceOwnedOLSOperatorComplete checks if the OLS Operator's CSV is owned +// by the given OpenStackLightspeed instance and is in the Succeeded phase. +func InstanceOwnedOLSOperatorComplete( + ctx context.Context, + helper *common_helper.Helper, + instance *apiv1beta1.OpenStackLightspeed, +) (bool, error) { + OLSOperatorCSV, err := GetOLSOperatorCSV(ctx, helper) + if err != nil { + return false, err + } else if OLSOperatorCSV == nil { + return false, nil + } + + // When the OLS Operator CSV is owned by us and it is in the Succeeded phase + // we can be certain that the deployment of OLS Operator is over. + return IsOwnedBy(OLSOperatorCSV, instance) && OLSOperatorCSV.Status.Phase == operatorsv1alpha1.CSVPhaseSucceeded, nil +} + +// GetRecommendedOLSVersion returns the recommended version of the OpenShift +// Lightspeed (OLS) operator to deploy. This version is obtained from the environment +// variable "OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION". If the variable +// is unset or empty, the function returns an error. +func GetRecommendedOLSVersion() (string, error) { + version := os.Getenv("OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION") + if version != "" { + return version, nil + } + + return "", fmt.Errorf("environment variable OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION is not set") +} + +// GetOLSOperatorCSV - retrieves the ClusterServiceVersion (CSV) for the OpenShift Lightspeed operator +// from all namespaces in the OpenShift cluster. It returns the first CSV it finds whose name begins +// with the OLSOperatorName. If no such CSV is found, it returns (nil, nil). If there is an error +// while listing the CSV resources, that error is returned. +func GetOLSOperatorCSV( + ctx context.Context, + helper *common_helper.Helper, +) (*operatorsv1alpha1.ClusterServiceVersion, error) { + var CSVs operatorsv1alpha1.ClusterServiceVersionList + err := helper.GetClient().List(ctx, &CSVs, client.InNamespace("")) + if err != nil && k8s_errors.IsNotFound(err) { + return nil, nil + } else if err != nil { + return nil, err + } + + for _, CSV := range CSVs.Items { + if strings.HasPrefix(CSV.GetName(), OLSOperatorName) { + return &CSV, nil + } + } + + return nil, nil +} + +// IsUserInstalledOLSOperatorMode checks if an OpenShift Lightspeed Operator +// (OLS Operator) is installed in the cluster (by the user), but was NOT installed/owned by +// this specific OpenStackLightspeed instance. Returns true only if there is an OLS OperatorIsOwnedBy +// ClusterServiceVersion (CSV) found, and that CSV is NOT owned by the given instance. +func IsUserInstalledOLSOperatorMode( + ctx context.Context, + helper *common_helper.Helper, + instance *apiv1beta1.OpenStackLightspeed, +) (bool, error) { + OLSOperatorCSV, err := GetOLSOperatorCSV(ctx, helper) + if err != nil { + return false, err + } else if OLSOperatorCSV == nil { + // Note: If no CSV is found we can be 100 % certain we are in the InstanceOwned + // installation mode. + return false, nil + } + + subscription := &operatorsv1alpha1.Subscription{} + err = helper.GetClient().Get(ctx, client.ObjectKey{ + Name: GetOLSSubscriptionName(instance), + Namespace: instance.Namespace, + }, subscription) + if err != nil && !k8s_errors.IsNotFound(err) { + return false, err + } + + userInstalledMode := !IsOwnedBy(OLSOperatorCSV, instance) && !IsOwnedBy(subscription, instance) + return userInstalledMode, nil +} + +// UninstallInstanceOwnedOLSOperator ensures that the OLS Operator installed by +// a specific OpenStackLightspeed instance is uninstalled from the cluster. The function +// checks if the ClusterServiceVersion (CSV) for the OLS Operator exists and whether it +// is owned by the given OpenStackLightspeed instance. If so, it deletes the CSV. +// The function then checks whether the CSV has been successfully removed. It returns +// true if the operator CSV is no longer found (i.e., uninstalled), or an error if an +// unexpected problem occurs. +func UninstallInstanceOwnedOLSOperator( + ctx context.Context, + helper *common_helper.Helper, + instance *apiv1beta1.OpenStackLightspeed, +) (bool, error) { + OLSOperatorCSV, err := GetOLSOperatorCSV(ctx, helper) + if err != nil { + return false, err + } else if OLSOperatorCSV == nil { + return true, nil + } + + if !IsOwnedBy(OLSOperatorCSV, instance) { + return true, nil + } + + if err := helper.GetClient().Delete(ctx, OLSOperatorCSV); err != nil { + return false, err + } + + OLSOperatorCSV, err = GetOLSOperatorCSV(ctx, helper) + if err != nil { + return false, err + } else if OLSOperatorCSV == nil { + return true, nil + } + + return false, nil +} + +// ApproveOLSOperatorInstallPlan - checks for any pending, unapproved InstallPlans associated with the +// OpenShift Lightspeed Operator (OLS operator) within the namespace of the provided OpenStackLightspeed instance, +// and approves them. The function lists all InstallPlans in the instance's namespace, identifies those linked to +// the OLS operator and not yet approved, and updates their status to approved. Returns true if a pending +// InstallPlan is successfully approved. Returns false if there are no InstallPlans to be approved, +// and returns false with an error if any occurs during the listing or approval process. +func ApproveOLSOperatorInstallPlan( + ctx context.Context, + helper *common_helper.Helper, + instance *apiv1beta1.OpenStackLightspeed, +) (bool, error) { + var installPlans operatorsv1alpha1.InstallPlanList + err := helper.GetClient().List(ctx, &installPlans, client.InNamespace(instance.Namespace)) + if err != nil { + return false, err + } + + recommendedOLSVersion, err := GetRecommendedOLSVersion() + if err != nil { + return false, err + } + + for _, installPlan := range installPlans.Items { + // Continue if the InstallPlan does not have any CSVs associated with it. + if len(installPlan.Spec.ClusterServiceVersionNames) == 0 { + continue + } + + isOLSOperatorCSV := strings.HasPrefix(installPlan.Spec.ClusterServiceVersionNames[0], OLSOperatorName) + if !isOLSOperatorCSV { + continue + } + + isCorrectVersion := strings.HasSuffix(installPlan.Spec.ClusterServiceVersionNames[0], recommendedOLSVersion) + if !isCorrectVersion { + continue + } + + installPlan.Spec.Approved = true + err = helper.GetClient().Update(ctx, &installPlan) + if err != nil && k8s_errors.IsConflict(err) { + return false, nil + } else if err != nil { + return false, err + } + + return true, nil + } + + return false, nil +} + +// CheckOLSOperatorVersion returns true if the installed OLS Operator's version matches +// the recommended version for the currently installed OpenStack Lightspeed operator. +func CheckOLSOperatorVersion( + ctx context.Context, + helper *common_helper.Helper, + instance *apiv1beta1.OpenStackLightspeed, +) (bool, error) { + OLSOperatorCSV, err := GetOLSOperatorCSV(ctx, helper) + if err != nil { + return false, err + } else if OLSOperatorCSV == nil { + return false, nil + } + + recommendedVersion, err := GetRecommendedOLSVersion() + if err != nil { + return false, err + } + + installedVersion := OLSOperatorCSV.Spec.Version.String() + if installedVersion != recommendedVersion { + errMsg := ("detected an unsupported version of OpenShift Lightspeed in the cluster." + + "The recommended version is: %s. Please ensure that the installed version " + + "matches the recommended version or uninstall it (OpenStack Lightspeed " + + "will install the OpenShift Lightspeed operator automatically)") + return false, fmt.Errorf(errMsg, recommendedVersion) + } + + return true, nil +} + +// GetOLSSubscriptionName generates a unique subscription name for the OpenStack Lightspeed Operator +// by appending the first 5 characters of the instance's UID. This reduces the likelihood of +// naming collisions with existing subscriptions that may have been created manually by the user. +func GetOLSSubscriptionName(instance *apiv1beta1.OpenStackLightspeed) string { + return fmt.Sprintf("%s-%s", OLSOperatorName, string(instance.GetUID())[:5]) +} diff --git a/internal/controller/openstacklightspeed_controller.go b/internal/controller/openstacklightspeed_controller.go index fee2a4c6..c64973c7 100644 --- a/internal/controller/openstacklightspeed_controller.go +++ b/internal/controller/openstacklightspeed_controller.go @@ -24,15 +24,19 @@ import ( "github.com/go-logr/logr" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" common_helper "github.com/openstack-k8s-operators/lib-common/modules/common/helper" + operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" k8s_errors "k8s.io/apimachinery/pkg/api/errors" uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" apiv1beta1 "github.com/openstack-lightspeed/operator/api/v1beta1" ) @@ -55,8 +59,10 @@ func (r *OpenStackLightspeedReconciler) GetLogger(ctx context.Context) logr.Logg // +kubebuilder:rbac:groups=ols.openshift.io,resources=olsconfigs,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=ols.openshift.io,resources=olsconfigs/status,verbs=get;update;patch // +kubebuilder:rbac:groups=ols.openshift.io,resources=olsconfigs/finalizers,verbs=update -// +kubebuilder:rbac:groups=operators.coreos.com,resources=clusterserviceversions,verbs=get;list; -// +kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;update;patch;delete; +// +kubebuilder:rbac:groups=operators.coreos.com,resources=clusterserviceversions,verbs=get;list;watch;update;patch;delete +// +kubebuilder:rbac:groups=operators.coreos.com,resources=subscriptions,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=operators.coreos.com,resources=installplans,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups="",resources=pods,verbs=create;delete;get;list;patch;update;watch // +kubebuilder:rbac:groups="",resources=pods/log,verbs=get @@ -136,7 +142,7 @@ func (r *OpenStackLightspeedReconciler) Reconcile(ctx context.Context, req ctrl. instance.Status.ObservedGeneration = instance.Generation if !instance.DeletionTimestamp.IsZero() { - return ctrl.Result{}, r.reconcileDelete(ctx, helper, instance) + return r.reconcileDelete(ctx, helper, instance) } if instance.DeletionTimestamp.IsZero() && controllerutil.AddFinalizer(instance, helper.GetFinalizer()) { @@ -151,18 +157,37 @@ func (r *OpenStackLightspeedReconciler) Reconcile(ctx context.Context, req ctrl. instance.Spec.MaxTokensForResponse = apiv1beta1.OpenStackLightspeedDefaultValues.MaxTokensForResponse } - OLSOperatorInstalled, err := IsOLSOperatorInstalled(ctx, helper) - if !OLSOperatorInstalled || err != nil { - errMsg := fmt.Errorf("installation of OpenShift LightSpeed not detected") + // Ensure a compatible version of the OpenShift Lightspeed Operator is running in the cluster. + // This checks if the correct OLS Operator version is present and installs it if necessary. + isOLSOperatorInstalled, err := EnsureOLSOperatorInstalled(ctx, helper, instance) + if err != nil { instance.Status.Conditions.Set(condition.FalseCondition( - apiv1beta1.OpenStackLightspeedReadyCondition, + apiv1beta1.OpenShiftLightspeedOperatorReadyCondition, condition.ErrorReason, condition.SeverityWarning, condition.DeploymentReadyErrorMessage, - errMsg)) - return ctrl.Result{}, errMsg + err.Error(), + )) + + return ctrl.Result{}, nil + } else if !isOLSOperatorInstalled { + instance.Status.Conditions.Set(condition.FalseCondition( + apiv1beta1.OpenShiftLightspeedOperatorReadyCondition, + condition.RequestedReason, + condition.SeverityInfo, + apiv1beta1.OpenShiftLightspeedOperatorWaiting, + )) + + // In this branch we know that the + return ctrl.Result{Requeue: true, RequeueAfter: 10 * time.Second}, nil } + // Mark the OpenShift Lightspeed Operator as ready in the status conditions. + instance.Status.Conditions.MarkTrue( + apiv1beta1.OpenShiftLightspeedOperatorReadyCondition, + apiv1beta1.OpenShiftLightspeedOperatorReady, + ) + // TODO(lpiwowar): Remove ResolveIndexID once OpenShift Lightspeed supports auto discovery of the indexID directly // from the vector db image. indexID, result, err := ResolveIndexID(ctx, helper, instance) @@ -248,50 +273,65 @@ func (r *OpenStackLightspeedReconciler) reconcileDelete( ctx context.Context, helper *common_helper.Helper, instance *apiv1beta1.OpenStackLightspeed, -) error { +) (ctrl.Result, error) { Log := r.GetLogger(ctx) Log.Info("OpenStackLightspeed Reconciling Delete") - olsConfig, err := GetOLSConfig(ctx, helper) - if err != nil && k8s_errors.IsNotFound(err) { - controllerutil.RemoveFinalizer(instance, helper.GetFinalizer()) - return nil - } else if err != nil { - return err - } - - ownerLabel := olsConfig.GetLabels()[OpenStackLightspeedOwnerIDLabel] - if ownerLabel == "" || ownerLabel != string(instance.GetObjectMeta().GetUID()) { - Log.Info("Skipping OLSConfig deletion as it is not managed by the OpenStackLightspeed instance") - controllerutil.RemoveFinalizer(instance, helper.GetFinalizer()) - return nil - } - - _, err = controllerutil.CreateOrPatch(ctx, r.Client, &olsConfig, func() error { - if ok := controllerutil.RemoveFinalizer(&olsConfig, helper.GetFinalizer()); !ok { - return fmt.Errorf("remove finalizer failed") - } - - return nil - }) + isRemoved, err := RemoveOLSConfig(ctx, helper, instance) if err != nil { - return err + return ctrl.Result{}, err + } else if !isRemoved { + Log.Info("OLSConfig removal in progress ...") + return ctrl.Result{RequeueAfter: time.Second * 10}, nil } - err = r.Delete(ctx, &olsConfig) + isUninstalled, err := UninstallInstanceOwnedOLSOperator(ctx, helper, instance) if err != nil { - return err + return ctrl.Result{}, err + } else if !isUninstalled { + Log.Info("OLS Operator uninstallation in progress ...") + return ctrl.Result{RequeueAfter: time.Second * 10}, nil } controllerutil.RemoveFinalizer(instance, helper.GetFinalizer()) Log.Info("OpenStackLightspeed Reconciling Delete completed") - return nil + return ctrl.Result{}, nil } // SetupWithManager sets up the controller with the Manager. func (r *OpenStackLightspeedReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&apiv1beta1.OpenStackLightspeed{}). + Owns(&operatorsv1alpha1.ClusterServiceVersion{}). + Owns(&operatorsv1alpha1.Subscription{}). + Watches( + &operatorsv1alpha1.InstallPlan{}, + handler.EnqueueRequestsFromMapFunc(r.NotifyAllOpenStackLightspeeds), + builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), + ). Complete(r) } + +// NotifyAllOpenStackLightspeeds returns a list of reconcile requests for all OpenStackLightspeed objects +// in the same namespace as the given InstallPlan. This is used to trigger reconciliation on all +// OpenStackLightspeed resources when an InstallPlan in their namespace changes. +func (r *OpenStackLightspeedReconciler) NotifyAllOpenStackLightspeeds(ctx context.Context, obj client.Object) []ctrl.Request { + // Pre-allocate requests slice with the capacity equal to the number of OpenStackLightspeed objects + var lightspeedList apiv1beta1.OpenStackLightspeedList + if err := r.List(ctx, &lightspeedList, client.InNamespace("")); err != nil { + return nil + } + requests := make([]ctrl.Request, 0, len(lightspeedList.Items)) + + for _, item := range lightspeedList.Items { + requests = append(requests, ctrl.Request{ + NamespacedName: client.ObjectKey{ + Namespace: item.GetNamespace(), + Name: item.GetName(), + }, + }) + } + + return requests +} From 41fcf0e101b2661d791dacf3c8e18c5ab7a11f24 Mon Sep 17 00:00:00 2001 From: Lukas Piwowarski Date: Fri, 14 Nov 2025 10:57:59 -0500 Subject: [PATCH 02/10] Add OLSConfig ping mechanism Introduce a ping function that adds a random label to OLSConfig resources to trigger reconciliation by the OpenShift Lightspeed operator. This ensures the operator updates the Status field when the OLSConfig is not ready. This addresses a current limitation where the OLS operator does not automatically update the OLSConfig status when installed in the openstack-lightspeed namespace. --- internal/controller/funcs.go | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/internal/controller/funcs.go b/internal/controller/funcs.go index aa9cf733..f7decf2b 100644 --- a/internal/controller/funcs.go +++ b/internal/controller/funcs.go @@ -22,6 +22,8 @@ import ( "encoding/json" "fmt" "io" + "math/rand" + "strconv" "strings" "time" @@ -251,7 +253,7 @@ func IsOLSConfigReady(ctx context.Context, helper *common_helper.Helper) (bool, for _, OLSConfigCondition := range OLSConfigConditions { for _, requiredConditionType := range requiredConditionTypes { if OLSConfigCondition.Type == requiredConditionType && OLSConfigCondition.Status != metav1.ConditionTrue { - return false, nil + return false, OLSConfigPing(ctx, helper) } } } @@ -424,3 +426,30 @@ func IsOwnedBy(object metav1.Object, owner metav1.Object) bool { return false } + +// OLSConfigPing adds a random label to the OLSConfig to trigger a reconciliation +// by the OpenShift Lightspeed operator. This causes the operator to update the Status field. +// Note: This is a workaround for a current limitation—when the OLS operator is installed +// in the openstack-lightspeed namespace, it does not automatically update the OLSConfig +// status as expected. +func OLSConfigPing(ctx context.Context, helper *common_helper.Helper) error { + const randomLabelKey = "openstack-lightspeed/ping" + + olsConfig, err := GetOLSConfig(ctx, helper) + if err != nil { + return err + } + + labels := olsConfig.GetLabels() + if labels == nil { + labels = make(map[string]string) + } + + labels[randomLabelKey] = strconv.Itoa(rand.Int()) + olsConfig.SetLabels(labels) + + if err := helper.GetClient().Update(ctx, &olsConfig); err != nil { + return err + } + return nil +} From 1ec797b2fa52183edba6158cfd71732b8dcaa427 Mon Sep 17 00:00:00 2001 From: Lukas Piwowarski Date: Wed, 12 Nov 2025 12:25:13 -0500 Subject: [PATCH 03/10] Make OLS installation works with make run Because the OpenStack Lightspeed operator now depends on the OPENSHIFT_LIGTSPEED_OPERATOR_VERSION variable we have to ensure that it is set when we run the operator during development with make run. --- Makefile | 2 +- scripts/env.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 scripts/env.sh diff --git a/Makefile b/Makefile index 57c7d38b..be065ec9 100644 --- a/Makefile +++ b/Makefile @@ -146,7 +146,7 @@ build: manifests generate fmt vet ## Build manager binary. .PHONY: run run: manifests generate fmt vet ## Run a controller from your host. - go run ./cmd/main.go + source ./scripts/env.sh && go run ./cmd/main.go # If you wish to build the manager image targeting other platforms you can use the --platform flag. # (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it. diff --git a/scripts/env.sh b/scripts/env.sh new file mode 100644 index 00000000..44223588 --- /dev/null +++ b/scripts/env.sh @@ -0,0 +1,2 @@ +#!/bin/bash +export OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION=1.0.7 From 6504f67b8be645f933bb4279e0fb859390f99fcf Mon Sep 17 00:00:00 2001 From: Lukas Piwowarski Date: Wed, 12 Nov 2025 12:24:47 -0500 Subject: [PATCH 04/10] Update installation steps Update README to remove manual OLS operator deployment step since the operator now handles this automatically. This commit also renames the catalog-deploy to openstack-lightspeed-deploy to better reflect its behavior. --- Makefile | 12 ++++++------ README.md | 13 ++++--------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index be065ec9..767d1970 100644 --- a/Makefile +++ b/Makefile @@ -217,18 +217,18 @@ undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/. $(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f - # Deploy using the catalog image. -.PHONY: catalog-deploy -catalog-deploy: export OUTPUT_DIR = out -catalog-deploy: ## Deploy using a catalog image. +.PHONY: openstack-lightspeed-deploy +openstack-lightspeed-deploy: export OUTPUT_DIR = out +openstack-lightspeed-deploy: ## Deploy using a catalog image. bash scripts/gen-catalog.sh $(CATALOG_IMG) $(CATALOG_NAME) oc apply -f $(OUTPUT_DIR)/catalog bash scripts/gen-rhosls.sh $(CATALOG_NAME) $(CATALOG_CHANNEL) oc apply -f $(OUTPUT_DIR)/rhosls # Deploy using the catalog image. -.PHONY: catalog-undeploy -catalog-undeploy: export OUTPUT_DIR = out -catalog-undeploy: ## Undeploy using a catalog image. +.PHONY: openstack-lightspeed-undeploy +openstack-lightspeed-undeploy: export OUTPUT_DIR = out +openstack-lightspeed-undeploy: ## Undeploy using a catalog image. find out/{catalog,rhosls} -name "*.yaml" -printf " -f %p" | xargs oc delete --ignore-not-found=true CATALOG_NAME ?= openstack-lightspeed-catalog diff --git a/README.md b/README.md index 84dd1742..42011b5c 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ eval $(crc oc-env) cd ../.. ``` -### Deploy OpenShift and OpenStack Lightspeed Operators +### Deploy OpenStack Lightspeed Operator Get the operator repository: @@ -46,20 +46,15 @@ git clone https://github.com/openstack-lightspeed/operator.git cd operator ``` -First, deploy OpenShift Lightspeed, then proceed to deploy OpenStack Lightspeed: +First, deploy OpenStack Lightspeed Operator: ```bash -make ols-deploy -make catalog-deploy +make openstack-lightspeed-deploy ``` -Now verify that they are up and running: +Next, verify that the OpenStack Lightspeed Operator pod is running: ```bash -$ oc get -n openshift-lightspeed pods -NAME READY STATUS RESTARTS AGE -lightspeed-operator-controller-manager-7f4698b55c-8w8vn 1/1 Running 0 81s - $ oc get -n openstack-lightspeed pods NAME READY STATUS RESTARTS AGE openstack-lightspeed-operator-controller-manager-76df7fbfb5wggr 1/1 Running 0 72s From d580af1b4a6b93b309f6220b27c7566462088c14 Mon Sep 17 00:00:00 2001 From: Lukas Piwowarski Date: Wed, 12 Nov 2025 12:24:34 -0500 Subject: [PATCH 05/10] Update Go module dependencies Update go.mod and go.sum with latest dependency versions. --- go.mod | 76 ++++++++++++----------- go.sum | 193 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 137 insertions(+), 132 deletions(-) diff --git a/go.mod b/go.mod index 64b4e4ab..82c98524 100644 --- a/go.mod +++ b/go.mod @@ -7,23 +7,27 @@ require ( github.com/onsi/ginkgo/v2 v2.20.1 github.com/onsi/gomega v1.34.1 github.com/openstack-k8s-operators/lib-common/modules/common v0.5.0 - k8s.io/api v0.30.1 - k8s.io/apimachinery v0.30.1 - k8s.io/client-go v0.30.1 - sigs.k8s.io/controller-runtime v0.18.4 + github.com/operator-framework/api v0.27.0 + k8s.io/api v0.31.0 + k8s.io/apimachinery v0.31.0 + k8s.io/client-go v0.31.0 + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 + sigs.k8s.io/controller-runtime v0.19.0 ) require ( - github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect + github.com/antlr4-go/antlr/v4 v4.13.0 // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.0 // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect @@ -33,14 +37,15 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/google/cel-go v0.17.8 // indirect + github.com/google/cel-go v0.20.1 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/imdario/mergo v0.3.16 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -48,25 +53,28 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.19.0 // indirect - github.com/prometheus/client_model v0.6.0 // indirect - github.com/prometheus/common v0.51.1 // indirect - github.com/prometheus/procfs v0.13.0 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stoewer/go-strcase v1.2.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 // indirect - go.opentelemetry.io/otel v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect - go.opentelemetry.io/otel/metric v1.19.0 // indirect - go.opentelemetry.io/otel/sdk v1.19.0 // indirect - go.opentelemetry.io/otel/trace v1.19.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect + github.com/stoewer/go-strcase v1.3.0 // indirect + github.com/x448/float16 v0.8.4 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect golang.org/x/net v0.28.0 // indirect - golang.org/x/oauth2 v0.18.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.23.0 // indirect golang.org/x/term v0.23.0 // indirect @@ -74,21 +82,19 @@ require ( golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.24.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/grpc v1.58.3 // indirect - google.golang.org/protobuf v1.34.1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect 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.30.1 // indirect - k8s.io/apiserver v0.30.1 // indirect - k8s.io/component-base v0.30.1 // indirect - k8s.io/klog/v2 v2.120.1 // indirect + k8s.io/apiextensions-apiserver v0.31.0 // indirect + k8s.io/apiserver v0.31.0 // indirect + k8s.io/component-base v0.31.0 // indirect + k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 // indirect - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // 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 c076d967..beb5be8f 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,16 @@ -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= @@ -18,10 +21,12 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 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/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -39,19 +44,14 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/cel-go v0.17.8 h1:j9m730pMZt1Fc4oKhCLUHfjj6527LuhYcYw0Rl8gqto= -github.com/google/cel-go v0.17.8/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= +github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= +github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -62,10 +62,12 @@ github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQu github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -91,48 +93,62 @@ github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/openstack-k8s-operators/lib-common/modules/common v0.5.0 h1:wto7Vprhr84z2LJzjbbw589MGkfjKtpHnhIhzgOa+BI= github.com/openstack-k8s-operators/lib-common/modules/common v0.5.0/go.mod h1:tNeup9Xl7j2eaeMslJ/rt59NNEAw7ATf6RuebS/YkSk= +github.com/operator-framework/api v0.27.0 h1:OrVaGKZJvbZo58HTv2guz7aURkhVKYhFqZ/6VpifiXI= +github.com/operator-framework/api v0.27.0/go.mod h1:lg2Xx+S8NQWGYlEOvFwQvH46E5EK5IrAIL7HWfAhciM= 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/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= -github.com/prometheus/common v0.51.1 h1:eIjN50Bwglz6a/c3hAgSMcofL3nD+nFQkV6Dd4DsQCw= -github.com/prometheus/common v0.51.1/go.mod h1:lrWtQx+iDfn2mbH5GUzlH9TSHyfZpHkSiG1W7y3sF2Q= -github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o= -github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g= -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/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.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 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/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= +github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +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/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= -go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= -go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= -go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= -go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= -go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= -go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -142,45 +158,33 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -189,7 +193,6 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -198,53 +201,49 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= -google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e h1:z3vDksarJxsAKM5dmEGv0GHwE2hKJ096wZra71Vs4sw= -google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= +google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.30.1 h1:kCm/6mADMdbAxmIh0LBjS54nQBE+U4KmbCfIkF5CpJY= -k8s.io/api v0.30.1/go.mod h1:ddbN2C0+0DIiPntan/bye3SW3PdwLa11/0yqwvuRrJM= -k8s.io/apiextensions-apiserver v0.30.1 h1:4fAJZ9985BmpJG6PkoxVRpXv9vmPUOVzl614xarePws= -k8s.io/apiextensions-apiserver v0.30.1/go.mod h1:R4GuSrlhgq43oRY9sF2IToFh7PVlF1JjfWdoG3pixk4= -k8s.io/apimachinery v0.30.1 h1:ZQStsEfo4n65yAdlGTfP/uSHMQSoYzU/oeEbkmF7P2U= -k8s.io/apimachinery v0.30.1/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= -k8s.io/apiserver v0.30.1 h1:BEWEe8bzS12nMtDKXzCF5Q5ovp6LjjYkSp8qOPk8LZ8= -k8s.io/apiserver v0.30.1/go.mod h1:i87ZnQ+/PGAmSbD/iEKM68bm1D5reX8fO4Ito4B01mo= -k8s.io/client-go v0.30.1 h1:uC/Ir6A3R46wdkgCV3vbLyNOYyCJ8oZnjtJGKfytl/Q= -k8s.io/client-go v0.30.1/go.mod h1:wrAqLNs2trwiCH/wxxmT/x3hKVH9PuV0GGW0oDoHVqc= -k8s.io/component-base v0.30.1 h1:bvAtlPh1UrdaZL20D9+sWxsJljMi0QZ3Lmw+kmZAaxQ= -k8s.io/component-base v0.30.1/go.mod h1:e/X9kDiOebwlI41AvBHuWdqFriSRrX50CdwA9TFaHLI= -k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= -k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo= +k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE= +k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= +k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= +k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= +k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/apiserver v0.31.0 h1:p+2dgJjy+bk+B1Csz+mc2wl5gHwvNkC9QJV+w55LVrY= +k8s.io/apiserver v0.31.0/go.mod h1:KI9ox5Yu902iBnnyMmy7ajonhKnkeZYJhTZ/YI+WEMk= +k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8= +k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU= +k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs= +k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 h1:qVoMaQV5t62UUvHe16Q3eb2c5HPzLHYzsi0Tu/xLndo= k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 h1:/U5vjBbQn3RChhv7P11uhYvCSm5G2GaIi5AIGBS6r4c= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0/go.mod h1:z7+wmGM2dfIiLRfrC6jb5kV2Mq/sK1ZP303cxzkV5Y4= -sigs.k8s.io/controller-runtime v0.18.4 h1:87+guW1zhvuPLh1PHybKdYFLU0YJp4FhJRmiHvm5BZw= -sigs.k8s.io/controller-runtime v0.18.4/go.mod h1:TVoGrfdpbA9VRFaRnKgk9P5/atA0pMwq+f+msb9M8Sg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= +sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= 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/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= From 84fa63c8f9484fccb93cab76386611f74aef3241 Mon Sep 17 00:00:00 2001 From: Lukas Piwowarski Date: Wed, 12 Nov 2025 12:23:23 -0500 Subject: [PATCH 06/10] Add namespace scoped RBAC for OLS operator management Split RBAC permissions into cluster-scoped (read-only CSV list/watch) and namespace-scoped (CSV/subscription/installplan management) roles to support namespace-scoped operator deployment. Note that this commit adjusts the permissions that are related to the recent changes (OLS operator installation). In the follow up changes we have to modify the permissions for other resources as well. --- config/rbac/kustomization.yaml | 1 + config/rbac/namespace_role_binding.yaml | 17 +++++++++++++++++ config/rbac/role.yaml | 17 +++++++++++++++-- .../openstacklightspeed_controller.go | 9 +++++---- 4 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 config/rbac/namespace_role_binding.yaml diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index 07d14f17..4c75b00d 100644 --- a/config/rbac/kustomization.yaml +++ b/config/rbac/kustomization.yaml @@ -7,6 +7,7 @@ resources: - service_account.yaml - role.yaml - role_binding.yaml +- namespace_role_binding.yaml - leader_election_role.yaml - leader_election_role_binding.yaml # The following RBAC configurations are used to protect diff --git a/config/rbac/namespace_role_binding.yaml b/config/rbac/namespace_role_binding.yaml new file mode 100644 index 00000000..01bcdddc --- /dev/null +++ b/config/rbac/namespace_role_binding.yaml @@ -0,0 +1,17 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/name: openstack-lightspeed-operator + app.kubernetes.io/managed-by: kustomize + name: manager-rolebinding + namespace: openstack-lightspeed +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: manager-role +subjects: +- kind: ServiceAccount + name: controller-manager + namespace: system + diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index ffbf01f7..8078552c 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -91,12 +91,25 @@ rules: resources: - clusterserviceversions verbs: - - delete - get - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: manager-role + namespace: openstack-lightspeed +rules: +- apiGroups: + - operators.coreos.com + resources: + - clusterserviceversions + verbs: + - create + - delete - patch - update - - watch - apiGroups: - operators.coreos.com resources: diff --git a/internal/controller/openstacklightspeed_controller.go b/internal/controller/openstacklightspeed_controller.go index c64973c7..15427a93 100644 --- a/internal/controller/openstacklightspeed_controller.go +++ b/internal/controller/openstacklightspeed_controller.go @@ -59,9 +59,10 @@ func (r *OpenStackLightspeedReconciler) GetLogger(ctx context.Context) logr.Logg // +kubebuilder:rbac:groups=ols.openshift.io,resources=olsconfigs,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=ols.openshift.io,resources=olsconfigs/status,verbs=get;update;patch // +kubebuilder:rbac:groups=ols.openshift.io,resources=olsconfigs/finalizers,verbs=update -// +kubebuilder:rbac:groups=operators.coreos.com,resources=clusterserviceversions,verbs=get;list;watch;update;patch;delete -// +kubebuilder:rbac:groups=operators.coreos.com,resources=subscriptions,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=operators.coreos.com,resources=installplans,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=operators.coreos.com,resources=clusterserviceversions,verbs=get;list;watch +// +kubebuilder:rbac:groups=operators.coreos.com,resources=clusterserviceversions,namespace=openstack-lightspeed,verbs=create;update;patch;delete +// +kubebuilder:rbac:groups=operators.coreos.com,resources=subscriptions,namespace=openstack-lightspeed,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=operators.coreos.com,resources=installplans,namespace=openstack-lightspeed,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups="",resources=pods,verbs=create;delete;get;list;patch;update;watch // +kubebuilder:rbac:groups="",resources=pods/log,verbs=get @@ -319,7 +320,7 @@ func (r *OpenStackLightspeedReconciler) SetupWithManager(mgr ctrl.Manager) error func (r *OpenStackLightspeedReconciler) NotifyAllOpenStackLightspeeds(ctx context.Context, obj client.Object) []ctrl.Request { // Pre-allocate requests slice with the capacity equal to the number of OpenStackLightspeed objects var lightspeedList apiv1beta1.OpenStackLightspeedList - if err := r.List(ctx, &lightspeedList, client.InNamespace("")); err != nil { + if err := r.List(ctx, &lightspeedList, client.InNamespace(obj.GetNamespace())); err != nil { return nil } requests := make([]ctrl.Request, 0, len(lightspeedList.Items)) From 060c45a827cb26cbe904216e9cf1b02da1065181 Mon Sep 17 00:00:00 2001 From: Lukas Piwowarski Date: Wed, 12 Nov 2025 12:22:51 -0500 Subject: [PATCH 07/10] Add WATCH_NAMESPACE support Configure the operator to watch only the namespace specified in the WATCH_NAMESPACE environment variable instead of watching all namespaces cluster-wide. This enables namespace-scoped RBAC permissions for the operator. GetOLSOperatorCSV now uses a raw client to query CSVs cluster-wide, since the default controller client is scoped to WATCH_NAMESPACE. --- cmd/main.go | 26 ++++++++++++++++++++++++++ config/manager/manager.yaml | 4 ++++ internal/controller/funcs.go | 16 ++++++++++++++++ internal/controller/ols_install.go | 9 ++++++++- scripts/env.sh | 1 + 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/cmd/main.go b/cmd/main.go index bca9e76c..20e2c2a1 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -19,6 +19,7 @@ package main import ( "crypto/tls" "flag" + "fmt" "os" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) @@ -29,6 +30,7 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/metrics/filters" @@ -124,6 +126,13 @@ func main() { metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization } + watchNamespace, err := getWatchNamespace() + if err != nil { + setupLog.Error(err, "unable to get WatchNamespace, "+ + "the manager will watch and manage resources in all namespaces") + os.Exit(1) + } + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: scheme, Metrics: metricsServerOptions, @@ -131,6 +140,9 @@ func main() { HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "c83b0a4f.lightspeed.openstack.org", + Cache: cache.Options{ + DefaultNamespaces: map[string]cache.Config{watchNamespace: {}}, + }, // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily // when the Manager ends. This requires the binary to immediately end when the // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly @@ -175,3 +187,17 @@ func main() { os.Exit(1) } } + +// getWatchNamespace returns the Namespace the operator should be watching for changes +func getWatchNamespace() (string, error) { + // WatchNamespaceEnvVar is the constant for env variable WATCH_NAMESPACE + // which specifies the Namespace to watch. + // An empty value means the operator is running with cluster scope. + var watchNamespaceEnvVar = "WATCH_NAMESPACE" + + ns, found := os.LookupEnv(watchNamespaceEnvVar) + if !found { + return "", fmt.Errorf("%s must be set", watchNamespaceEnvVar) + } + return ns, nil +} diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index d3fccc46..eb6a3130 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -68,6 +68,10 @@ spec: env: - name: "OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION" value: "1.0.7" + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace securityContext: allowPrivilegeEscalation: false capabilities: diff --git a/internal/controller/funcs.go b/internal/controller/funcs.go index f7decf2b..cea3eeea 100644 --- a/internal/controller/funcs.go +++ b/internal/controller/funcs.go @@ -426,6 +426,22 @@ func IsOwnedBy(object metav1.Object, owner metav1.Object) bool { return false } +// GetRawClient returns a raw client that is not restricted to WATCH_NAMESPACE. +// This is useful for operations that need to query resources across all namespaces +// cluster wide. +func GetRawClient(helper *common_helper.Helper) (client.Client, error) { + cfg, err := config.GetConfig() + if err != nil { + return nil, err + } + + rawClient, err := client.New(cfg, client.Options{Scheme: helper.GetScheme()}) + if err != nil { + return nil, err + } + + return rawClient, nil +} // OLSConfigPing adds a random label to the OLSConfig to trigger a reconciliation // by the OpenShift Lightspeed operator. This causes the operator to update the Status field. diff --git a/internal/controller/ols_install.go b/internal/controller/ols_install.go index 4263f957..cfc4c9b9 100644 --- a/internal/controller/ols_install.go +++ b/internal/controller/ols_install.go @@ -196,8 +196,15 @@ func GetOLSOperatorCSV( ctx context.Context, helper *common_helper.Helper, ) (*operatorsv1alpha1.ClusterServiceVersion, error) { + // Use a dedicated client here because the default controller-runtime client may be restricted + // to WATCH_NAMESPACE. This ensures we can retrieve CSVs from all namespaces cluster-wide. + rawClient, err := GetRawClient(helper) + if err != nil { + return nil, err + } + var CSVs operatorsv1alpha1.ClusterServiceVersionList - err := helper.GetClient().List(ctx, &CSVs, client.InNamespace("")) + err = rawClient.List(ctx, &CSVs, client.InNamespace("")) if err != nil && k8s_errors.IsNotFound(err) { return nil, nil } else if err != nil { diff --git a/scripts/env.sh b/scripts/env.sh index 44223588..fcde45a6 100644 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -1,2 +1,3 @@ #!/bin/bash export OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION=1.0.7 +export WATCH_NAMESPACE="openstack-lightspeed" From adba0a0c3e510c295d3badfe5d45e145438b925f Mon Sep 17 00:00:00 2001 From: Lukas Piwowarski Date: Wed, 12 Nov 2025 18:51:58 +0100 Subject: [PATCH 08/10] Update CONTROLLER_TOOLS_VERSION to v0.16.5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 767d1970..489b1b95 100644 --- a/Makefile +++ b/Makefile @@ -250,7 +250,7 @@ GOLANGCI_LINT = $(LOCALBIN)/golangci-lint ## Tool Versions KUSTOMIZE_VERSION ?= v5.4.2 -CONTROLLER_TOOLS_VERSION ?= v0.15.0 +CONTROLLER_TOOLS_VERSION ?= v0.16.5 ENVTEST_VERSION ?= release-0.18 GOLANGCI_LINT_VERSION ?= v2.6.0 From 934f51b8d3486f36d7de07b2bab4335a0d7deece Mon Sep 17 00:00:00 2001 From: Lukas Piwowarski Date: Tue, 18 Nov 2025 06:04:26 -0500 Subject: [PATCH 09/10] Support latest OLS operator version Default OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION to "latest" to ensure compatibility with Operator Hub, which does not retain older versions indefinitely. Changes: - Set default version to "latest" in manager.yaml - Update GetRecommendedOLSVersion to handle "latest" value - Add SetStartingCSV helper to set version conditionally in Subscriptions - Return error when user-installed OLS operator is detected instead of attempting version compatibility check Future work should consider pinning to specific versions for production stability. --- config/manager/manager.yaml | 2 +- internal/controller/ols_install.go | 75 ++++++++++++++---------------- 2 files changed, 35 insertions(+), 42 deletions(-) diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index eb6a3130..780fd01c 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -67,7 +67,7 @@ spec: name: manager env: - name: "OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION" - value: "1.0.7" + value: "latest" - name: WATCH_NAMESPACE valueFrom: fieldRef: diff --git a/internal/controller/ols_install.go b/internal/controller/ols_install.go index cfc4c9b9..1afb5bf2 100644 --- a/internal/controller/ols_install.go +++ b/internal/controller/ols_install.go @@ -20,6 +20,7 @@ package controller import ( "context" + "errors" "fmt" "os" "strings" @@ -54,7 +55,10 @@ func EnsureOLSOperatorInstalled( } if isUserInstalledOLSOperator { - return CheckOLSOperatorVersion(ctx, helper, instance) + return false, errors.New( + "detected an existing OpenShift Lightspeed operator installation. " + + "Please uninstall OpenShift Lightspeed operator and allow the " + + "OpenStack Lightspeed operator to manage its installation automatically") } OLSOperatorInstalled, err := InstallInstanceOwnedOLSOperator(ctx, helper, instance) @@ -77,11 +81,6 @@ func InstallInstanceOwnedOLSOperator( helper *common_helper.Helper, instance *apiv1beta1.OpenStackLightspeed, ) (bool, error) { - olsVersion, err := GetRecommendedOLSVersion() - if err != nil { - return false, err - } - subscription := &operatorsv1alpha1.Subscription{ ObjectMeta: metav1.ObjectMeta{ Name: GetOLSSubscriptionName(instance), @@ -106,7 +105,11 @@ func InstallInstanceOwnedOLSOperator( CatalogSource: instance.Spec.CatalogSourceName, CatalogSourceNamespace: instance.Spec.CatalogSourceNamespace, Package: OLSOperatorName, - StartingCSV: fmt.Sprintf("%s.v%s", OLSOperatorName, olsVersion), + } + + err := SetStartingCSV(subscription) + if err != nil { + return err } subscription.SetOwnerReferences(instanceOwnerReference) @@ -177,15 +180,20 @@ func InstanceOwnedOLSOperatorComplete( // GetRecommendedOLSVersion returns the recommended version of the OpenShift // Lightspeed (OLS) operator to deploy. This version is obtained from the environment -// variable "OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION". If the variable -// is unset or empty, the function returns an error. +// variable "OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION". If the variable is unset or empty, +// an error is returned. If the value is "latest", an empty string and no error are returned. +// This indicates the rest of the OLS installation code can install the latest version +// of OLS operator since no specific version is set. func GetRecommendedOLSVersion() (string, error) { version := os.Getenv("OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION") - if version != "" { + switch version { + case "": + return "", errors.New("environment variable OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION is not set") + case "latest": + return "", nil + default: return version, nil } - - return "", fmt.Errorf("environment variable OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION is not set") } // GetOLSOperatorCSV - retrieves the ClusterServiceVersion (CSV) for the OpenShift Lightspeed operator @@ -340,40 +348,25 @@ func ApproveOLSOperatorInstallPlan( return false, nil } -// CheckOLSOperatorVersion returns true if the installed OLS Operator's version matches -// the recommended version for the currently installed OpenStack Lightspeed operator. -func CheckOLSOperatorVersion( - ctx context.Context, - helper *common_helper.Helper, - instance *apiv1beta1.OpenStackLightspeed, -) (bool, error) { - OLSOperatorCSV, err := GetOLSOperatorCSV(ctx, helper) - if err != nil { - return false, err - } else if OLSOperatorCSV == nil { - return false, nil - } +// GetOLSSubscriptionName generates a unique subscription name for the OpenStack Lightspeed Operator +// by appending the first 5 characters of the instance's UID. This reduces the likelihood of +// naming collisions with existing subscriptions that may have been created manually by the user. +func GetOLSSubscriptionName(instance *apiv1beta1.OpenStackLightspeed) string { + return fmt.Sprintf("%s-%s", OLSOperatorName, string(instance.GetUID())[:5]) +} +// SetStartingCSV sets the StartingCSV field of the given Subscription based on +// the recommended OLS operator version. If the recommended version is "", +// StartingCSV is not set to allow OLM to select the latest compatible version. +func SetStartingCSV(subscription *operatorsv1alpha1.Subscription) error { recommendedVersion, err := GetRecommendedOLSVersion() if err != nil { - return false, err + return err } - installedVersion := OLSOperatorCSV.Spec.Version.String() - if installedVersion != recommendedVersion { - errMsg := ("detected an unsupported version of OpenShift Lightspeed in the cluster." + - "The recommended version is: %s. Please ensure that the installed version " + - "matches the recommended version or uninstall it (OpenStack Lightspeed " + - "will install the OpenShift Lightspeed operator automatically)") - return false, fmt.Errorf(errMsg, recommendedVersion) + if recommendedVersion != "" { + subscription.Spec.StartingCSV = fmt.Sprintf("%s.v%s", OLSOperatorName, recommendedVersion) } - return true, nil -} - -// GetOLSSubscriptionName generates a unique subscription name for the OpenStack Lightspeed Operator -// by appending the first 5 characters of the instance's UID. This reduces the likelihood of -// naming collisions with existing subscriptions that may have been created manually by the user. -func GetOLSSubscriptionName(instance *apiv1beta1.OpenStackLightspeed) string { - return fmt.Sprintf("%s-%s", OLSOperatorName, string(instance.GetUID())[:5]) + return nil } From 1c631819c5fcf193046160a4eebc58d7497ecef7 Mon Sep 17 00:00:00 2001 From: Lukas Piwowarski Date: Tue, 18 Nov 2025 09:52:14 -0500 Subject: [PATCH 10/10] Use openshift-lightspeed namespace Install the OpenStack Lightspeed operator into the openshift-lightspeed namespace by default to align with ownership responsibilities and ensure compatibility, as the OLS operator is not guaranteed to function correctly in other namespaces. --- ...enstack-lightspeed-operator.clusterserviceversion.yaml | 4 ++-- scripts/env.sh | 2 +- scripts/gen-rhosls.sh | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/config/manifests/bases/openstack-lightspeed-operator.clusterserviceversion.yaml b/config/manifests/bases/openstack-lightspeed-operator.clusterserviceversion.yaml index 31510365..731765bb 100644 --- a/config/manifests/bases/openstack-lightspeed-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/openstack-lightspeed-operator.clusterserviceversion.yaml @@ -4,10 +4,10 @@ metadata: annotations: alm-examples: '[]' capabilities: Basic Install - operatorframework.io/suggested-namespace: openstack-lightspeed + operatorframework.io/suggested-namespace: openshift-lightspeed repository: https://github.com/openstack-lightspeed/operator name: openstack-lightspeed-operator.v0.0.0 - namespace: openstack-lightspeed + namespace: openshift-lightspeed spec: apiservicedefinitions: {} customresourcedefinitions: {} diff --git a/scripts/env.sh b/scripts/env.sh index fcde45a6..004a6c37 100644 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -1,3 +1,3 @@ #!/bin/bash export OPENSHIFT_LIGHTSPEED_OPERATOR_VERSION=1.0.7 -export WATCH_NAMESPACE="openstack-lightspeed" +export WATCH_NAMESPACE="openshift-lightspeed" diff --git a/scripts/gen-rhosls.sh b/scripts/gen-rhosls.sh index b47513d2..fd86d1b9 100644 --- a/scripts/gen-rhosls.sh +++ b/scripts/gen-rhosls.sh @@ -18,7 +18,7 @@ cat > "${DEST_DIR}/namespace.yaml" < "${DEST_DIR}/operator_group.yaml" <