diff --git a/apis/bases/core.openstack.org_openstackcontrolplanes.yaml b/apis/bases/core.openstack.org_openstackcontrolplanes.yaml index 66d2a43a0..fa4df5d20 100644 --- a/apis/bases/core.openstack.org_openstackcontrolplanes.yaml +++ b/apis/bases/core.openstack.org_openstackcontrolplanes.yaml @@ -40,6 +40,49 @@ spec: type: object spec: properties: + applicationCredential: + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + default: 365 + minimum: 2 + type: integer + gracePeriodDays: + default: 182 + minimum: 1 + type: integer + roles: + default: + - service + items: + type: string + minItems: 1 + type: array + unrestricted: + default: false + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: self.gracePeriodDays < self.expirationDays barbican: properties: apiOverride: @@ -166,6 +209,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -674,6 +758,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -1703,6 +1828,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean @@ -3581,6 +3747,47 @@ spec: type: object type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -4509,6 +4716,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' cnfAPIOverride: properties: route: @@ -6444,6 +6692,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean @@ -8096,6 +8385,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean @@ -9163,6 +9493,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -9993,6 +10364,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' cellOverride: additionalProperties: properties: @@ -11061,6 +11473,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean @@ -12537,6 +12990,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -13566,6 +14060,47 @@ spec: type: string swift: properties: + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -14213,6 +14748,88 @@ spec: type: string type: object type: object + aodhApplicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -15647,6 +16264,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean diff --git a/apis/core/v1beta1/openstackcontrolplane_types.go b/apis/core/v1beta1/openstackcontrolplane_types.go index 0016d78a4..9f0b28194 100644 --- a/apis/core/v1beta1/openstackcontrolplane_types.go +++ b/apis/core/v1beta1/openstackcontrolplane_types.go @@ -225,6 +225,14 @@ type OpenStackControlPlaneSpec struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // Watcher - Parameters related to the Watcher service Watcher WatcherSection `json:"watcher,omitempty"` + + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // ApplicationCredential - Global configuration for ApplicationCredentials. + // Both this global section AND the per-service applicationCredential section + // must be enabled for a service to use ApplicationCredentials. + // If omitted, defaults to enabled=false with standard expiration/grace periods. + ApplicationCredential ApplicationCredentialSection `json:"applicationCredential,omitempty"` } // TLSSection defines the desired state of TLS configuration @@ -419,6 +427,13 @@ type PlacementSection struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // APIOverride, provides the ability to override the generated manifest of several child resources. APIOverride Override `json:"apiOverride,omitempty"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` } // GlanceSection defines the desired state of Glance service @@ -445,6 +460,13 @@ type GlanceSection struct { // Convenient to avoid podname (and thus hostname) collision between different deployments. // Useful for CI jobs as well as preproduction and production environments that use the same storage backend, etc. UniquePodNames bool `json:"uniquePodNames"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` } // CinderSection defines the desired state of Cinder service @@ -471,6 +493,13 @@ type CinderSection struct { // Convenient to avoid podname (and thus hostname) collision between different deployments. // Useful for CI jobs as well as preproduction and production environments that use the same storage backend, etc. UniquePodNames bool `json:"uniquePodNames"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` } // GaleraSection defines the desired state of Galera services @@ -564,6 +593,13 @@ type NeutronSection struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // APIOverride, provides the ability to override the generated manifest of several child resources. APIOverride Override `json:"apiOverride,omitempty"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` } // NovaSection defines the desired state of Nova services @@ -590,6 +626,13 @@ type NovaSection struct { // for a nova cell. cell0 never have compute nodes and therefore it won't have a noVNCProxy deployed. // Providing an override for cell0 noVNCProxy does not have an effect. CellOverride map[string]NovaCellOverrideSpec `json:"cellOverride,omitempty"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` } // NovaCellOverrideSpec to override the generated manifest of several child resources. @@ -620,6 +663,13 @@ type HeatSection struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // CnfAPIOverride, provides the ability to override the generated manifest of several child resources. CnfAPIOverride Override `json:"cnfAPIOverride,omitempty"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` } // IronicSection defines the desired state of Ironic services @@ -644,6 +694,13 @@ type IronicSection struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // InspectorOverride, provides the ability to override the generated manifest of several child resources. InspectorOverride Override `json:"inspectorOverride,omitempty"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` } // ManilaSection defines the desired state of Manila service @@ -663,6 +720,13 @@ type ManilaSection struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // APIOverride, provides the ability to override the generated manifest of several child resources. APIOverride Override `json:"apiOverride,omitempty"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` } // HorizonSection defines the desired state of Horizon services @@ -711,6 +775,20 @@ type TelemetrySection struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // AlertmanagerOverride, provides the ability to override the generated manifest of several child resources. AlertmanagerOverride Override `json:"alertmanagerOverride,omitempty"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` + + // AodhApplicationCredential allows service-specific overrides of the global AC configuration for Aodh. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + AodhApplicationCredential *ServiceAppCredSection `json:"aodhApplicationCredential"` } // SwiftSection defines the desired state of Swift service @@ -730,6 +808,13 @@ type SwiftSection struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // ProxyOverride, provides the ability to override the generated manifest of several child resources. ProxyOverride Override `json:"proxyOverride,omitempty"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` } // OctaviaSection defines the desired state of the Octavia service @@ -749,6 +834,13 @@ type OctaviaSection struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // APIOverride, provides the ability to override the generated manifest of several child resources. APIOverride Override `json:"apiOverride,omitempty"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` } // DesignateSection defines the desired state of the Designate service @@ -768,6 +860,13 @@ type DesignateSection struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // APIOverride, provides the ability to override the generated manifest of several child resources. APIOverride Override `json:"apiOverride,omitempty"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` } // BarbicanSection defines the desired state of Barbican service @@ -787,6 +886,13 @@ type BarbicanSection struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // APIOverride, provides the ability to override the generated manifest of several child resources. APIOverride Override `json:"apiOverride,omitempty"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` } // RedisSection defines the desired state of the Redis service @@ -828,6 +934,94 @@ type WatcherSection struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // APIOverride, provides the ability to override the generated manifest of several child resources. APIOverride Override `json:"apiOverride,omitempty"` + + // ApplicationCredential allows service-specific overrides of the global AC configuration. + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:validation:Optional + // +nullable + // +kubebuilder:default={enabled:false} + ApplicationCredential *ServiceAppCredSection `json:"applicationCredential"` +} + +// +kubebuilder:validation:XValidation:rule="self.gracePeriodDays < self.expirationDays",message="gracePeriodDays must be smaller than expirationDays" +// ApplicationCredentialSection defines the desired configuration for ApplicationCredentials +type ApplicationCredentialSection struct { + // Enabled indicates whether an ApplicationCredential should be created + // +kubebuilder:validation:Optional + // +kubebuilder:default=false + Enabled bool `json:"enabled"` + + // ExpirationDays sets the lifetime in days for the AC + // +kubebuilder:validation:Optional + // +kubebuilder:default=365 + // +kubebuilder:validation:Minimum=2 + ExpirationDays *int `json:"expirationDays"` + + // GracePeriodDays sets how many days before expiration the AC should be rotated + // +kubebuilder:validation:Optional + // +kubebuilder:default=182 + // +kubebuilder:validation:Minimum=1 + GracePeriodDays *int `json:"gracePeriodDays"` + + // +kubebuilder:validation:Optional + // +kubebuilder:default={"service"} + // +kubebuilder:validation:MinItems=1 + // Roles to assign to the ApplicationCredential + Roles []string `json:"roles"` + + // +kubebuilder:validation:Optional + // +kubebuilder:default=false + // Whether the AC should be unrestricted + Unrestricted *bool `json:"unrestricted"` + + // AccessRules lets supply a custom list of rules + // If unset, no accessRules field is emitted + // +kubebuilder:validation:Optional + // +listType=atomic + AccessRules []ACRule `json:"accessRules,omitempty"` +} + +// +kubebuilder:validation:XValidation:rule="!(has(self.expirationDays) && has(self.gracePeriodDays)) || self.gracePeriodDays < self.expirationDays",message="gracePeriodDays must be smaller than expirationDays" +// ServiceAppCredSection allows service-specific overrides of the global AC configuration +type ServiceAppCredSection struct { + // +kubebuilder:validation:Optional + // +kubebuilder:default=false + Enabled bool `json:"enabled"` + + // +kubebuilder:validation:Optional + // +kubebuilder:validation:Minimum=2 + ExpirationDays *int `json:"expirationDays,omitempty"` + + // +kubebuilder:validation:Optional + // +kubebuilder:validation:Minimum=1 + GracePeriodDays *int `json:"gracePeriodDays,omitempty"` + + // +kubebuilder:validation:Optional + // Roles to assign to the ApplicationCredential + Roles []string `json:"roles,omitempty"` + + // +kubebuilder:validation:Optional + // Whether the AC should be unrestricted + Unrestricted *bool `json:"unrestricted,omitempty"` + + // AccessRules lets the service override either the global rules + // +kubebuilder:validation:Optional + // +listType=atomic + AccessRules []ACRule `json:"accessRules,omitempty"` +} + +// ACRule describes a single access rule for an ApplicationCredential +// +k8s:openapi-gen=true +type ACRule struct { + // Service is the name of the service to target (e.g. "identity"). + // +kubebuilder:validation:Required + Service string `json:"service"` + // Path is the HTTP path (e.g. "/v3/auth/tokens"). + // +kubebuilder:validation:Required + Path string `json:"path"` + // Method is the HTTP method to allow (e.g. "POST"). + // +kubebuilder:validation:Required + Method string `json:"method"` } // OpenStackControlPlaneStatus defines the observed state of OpenStackControlPlane diff --git a/apis/core/v1beta1/zz_generated.deepcopy.go b/apis/core/v1beta1/zz_generated.deepcopy.go index 7d3f8f17c..4b7dd1a39 100644 --- a/apis/core/v1beta1/zz_generated.deepcopy.go +++ b/apis/core/v1beta1/zz_generated.deepcopy.go @@ -51,6 +51,61 @@ import ( "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ACRule) DeepCopyInto(out *ACRule) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ACRule. +func (in *ACRule) DeepCopy() *ACRule { + if in == nil { + return nil + } + out := new(ACRule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationCredentialSection) DeepCopyInto(out *ApplicationCredentialSection) { + *out = *in + if in.ExpirationDays != nil { + in, out := &in.ExpirationDays, &out.ExpirationDays + *out = new(int) + **out = **in + } + if in.GracePeriodDays != nil { + in, out := &in.GracePeriodDays, &out.GracePeriodDays + *out = new(int) + **out = **in + } + if in.Roles != nil { + in, out := &in.Roles, &out.Roles + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Unrestricted != nil { + in, out := &in.Unrestricted, &out.Unrestricted + *out = new(bool) + **out = **in + } + if in.AccessRules != nil { + in, out := &in.AccessRules, &out.AccessRules + *out = make([]ACRule, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationCredentialSection. +func (in *ApplicationCredentialSection) DeepCopy() *ApplicationCredentialSection { + if in == nil { + return nil + } + out := new(ApplicationCredentialSection) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BarbicanSection) DeepCopyInto(out *BarbicanSection) { *out = *in @@ -60,6 +115,11 @@ func (in *BarbicanSection) DeepCopyInto(out *BarbicanSection) { (*in).DeepCopyInto(*out) } in.APIOverride.DeepCopyInto(&out.APIOverride) + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BarbicanSection. @@ -153,6 +213,11 @@ func (in *CinderSection) DeepCopyInto(out *CinderSection) { (*in).DeepCopyInto(*out) } in.APIOverride.DeepCopyInto(&out.APIOverride) + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CinderSection. @@ -801,6 +866,11 @@ func (in *DesignateSection) DeepCopyInto(out *DesignateSection) { (*in).DeepCopyInto(*out) } in.APIOverride.DeepCopyInto(&out.APIOverride) + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DesignateSection. @@ -854,6 +924,11 @@ func (in *GlanceSection) DeepCopyInto(out *GlanceSection) { (*out)[key] = *val.DeepCopy() } } + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlanceSection. @@ -876,6 +951,11 @@ func (in *HeatSection) DeepCopyInto(out *HeatSection) { } in.APIOverride.DeepCopyInto(&out.APIOverride) in.CnfAPIOverride.DeepCopyInto(&out.CnfAPIOverride) + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeatSection. @@ -919,6 +999,11 @@ func (in *IronicSection) DeepCopyInto(out *IronicSection) { } in.APIOverride.DeepCopyInto(&out.APIOverride) in.InspectorOverride.DeepCopyInto(&out.InspectorOverride) + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IronicSection. @@ -961,6 +1046,11 @@ func (in *ManilaSection) DeepCopyInto(out *ManilaSection) { (*in).DeepCopyInto(*out) } in.APIOverride.DeepCopyInto(&out.APIOverride) + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManilaSection. @@ -1008,6 +1098,11 @@ func (in *NeutronSection) DeepCopyInto(out *NeutronSection) { (*in).DeepCopyInto(*out) } in.APIOverride.DeepCopyInto(&out.APIOverride) + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NeutronSection. @@ -1052,6 +1147,11 @@ func (in *NovaSection) DeepCopyInto(out *NovaSection) { (*out)[key] = *val.DeepCopy() } } + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NovaSection. @@ -1073,6 +1173,11 @@ func (in *OctaviaSection) DeepCopyInto(out *OctaviaSection) { (*in).DeepCopyInto(*out) } in.APIOverride.DeepCopyInto(&out.APIOverride) + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OctaviaSection. @@ -1211,6 +1316,7 @@ func (in *OpenStackControlPlaneSpec) DeepCopyInto(out *OpenStackControlPlaneSpec **out = **in } in.Watcher.DeepCopyInto(&out.Watcher) + in.ApplicationCredential.DeepCopyInto(&out.ApplicationCredential) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackControlPlaneSpec. @@ -1520,6 +1626,11 @@ func (in *PlacementSection) DeepCopyInto(out *PlacementSection) { (*in).DeepCopyInto(*out) } in.APIOverride.DeepCopyInto(&out.APIOverride) + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlacementSection. @@ -1584,6 +1695,46 @@ func (in *RedisSection) DeepCopy() *RedisSection { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceAppCredSection) DeepCopyInto(out *ServiceAppCredSection) { + *out = *in + if in.ExpirationDays != nil { + in, out := &in.ExpirationDays, &out.ExpirationDays + *out = new(int) + **out = **in + } + if in.GracePeriodDays != nil { + in, out := &in.GracePeriodDays, &out.GracePeriodDays + *out = new(int) + **out = **in + } + if in.Roles != nil { + in, out := &in.Roles, &out.Roles + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Unrestricted != nil { + in, out := &in.Unrestricted, &out.Unrestricted + *out = new(bool) + **out = **in + } + if in.AccessRules != nil { + in, out := &in.AccessRules, &out.AccessRules + *out = make([]ACRule, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAppCredSection. +func (in *ServiceAppCredSection) DeepCopy() *ServiceAppCredSection { + if in == nil { + return nil + } + out := new(ServiceAppCredSection) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceDefaults) DeepCopyInto(out *ServiceDefaults) { *out = *in @@ -1613,6 +1764,11 @@ func (in *SwiftSection) DeepCopyInto(out *SwiftSection) { (*in).DeepCopyInto(*out) } in.ProxyOverride.DeepCopyInto(&out.ProxyOverride) + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SwiftSection. @@ -1739,6 +1895,16 @@ func (in *TelemetrySection) DeepCopyInto(out *TelemetrySection) { in.AodhAPIOverride.DeepCopyInto(&out.AodhAPIOverride) in.PrometheusOverride.DeepCopyInto(&out.PrometheusOverride) in.AlertmanagerOverride.DeepCopyInto(&out.AlertmanagerOverride) + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } + if in.AodhApplicationCredential != nil { + in, out := &in.AodhApplicationCredential, &out.AodhApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TelemetrySection. @@ -1760,6 +1926,11 @@ func (in *WatcherSection) DeepCopyInto(out *WatcherSection) { (*in).DeepCopyInto(*out) } in.APIOverride.DeepCopyInto(&out.APIOverride) + if in.ApplicationCredential != nil { + in, out := &in.ApplicationCredential, &out.ApplicationCredential + *out = new(ServiceAppCredSection) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatcherSection. diff --git a/apis/go.mod b/apis/go.mod index a23379f4c..70589b415 100644 --- a/apis/go.mod +++ b/apis/go.mod @@ -5,7 +5,7 @@ go 1.24.4 require ( github.com/cert-manager/cert-manager v1.16.5 github.com/go-playground/validator/v10 v10.28.0 - github.com/onsi/ginkgo/v2 v2.27.1 + github.com/onsi/ginkgo/v2 v2.27.2 github.com/onsi/gomega v1.38.2 github.com/openstack-k8s-operators/barbican-operator/api v0.6.1-0.20251014175433-c4ab8419a351 github.com/openstack-k8s-operators/cinder-operator/api v0.6.1-0.20251014173752-ea967e56a392 @@ -13,11 +13,11 @@ require ( github.com/openstack-k8s-operators/glance-operator/api v0.6.1-0.20251022111742-64b4039d28a7 github.com/openstack-k8s-operators/heat-operator/api v0.6.1-0.20251025092254-de6e9a251638 github.com/openstack-k8s-operators/horizon-operator/api v0.6.1-0.20251025090908-00fab1da8f24 - github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251025092254-9bbe85d92ae4 + github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251030184102-82d2cbaafd35 github.com/openstack-k8s-operators/ironic-operator/api v0.6.1-0.20251023190508-87e9d60da59a github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20251021163720-bb51cea0d967 - github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251021145236-2b84ec9fd9bb - github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20251021145236-2b84ec9fd9bb + github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251027074416-ab5c045dbe00 + github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20251027074416-ab5c045dbe00 github.com/openstack-k8s-operators/manila-operator/api v0.6.1-0.20251025092538-cee75eec6178 github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20251015110425-ad0381ce8cd4 github.com/openstack-k8s-operators/neutron-operator/api v0.6.1-0.20251016170447-17d48235c379 @@ -90,7 +90,6 @@ require ( github.com/robfig/cron/v3 v3.0.1 // indirect github.com/spf13/pflag v1.0.7 // indirect github.com/x448/float16 v0.8.4 // indirect - go.uber.org/automaxprocs v1.6.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/crypto v0.42.0 // indirect @@ -144,3 +143,20 @@ replace k8s.io/code-generator => k8s.io/code-generator v0.31.13 //allow-merging replace k8s.io/component-base => k8s.io/component-base v0.31.13 //allow-merging replace github.com/cert-manager/cmctl/v2 => github.com/cert-manager/cmctl/v2 v2.1.2-0.20241127223932-88edb96860cf //allow-merging + +// appcred related changes +replace github.com/openstack-k8s-operators/keystone-operator/api => github.com/Deydra71/keystone-operator/api v0.0.0-20251111075800-83054d6ff4b8 + +replace github.com/openstack-k8s-operators/barbican-operator/api => github.com/Deydra71/barbican-operator/api v0.0.0-20251103101323-46355b1793bf + +replace github.com/openstack-k8s-operators/cinder-operator/api => github.com/Deydra71/cinder-operator/api v0.0.0-20251103142104-0e9fbab80ef4 + +replace github.com/openstack-k8s-operators/glance-operator/api => github.com/Deydra71/glance-operator/api v0.0.0-20251103102702-77f7cfe01e3c + +replace github.com/openstack-k8s-operators/swift-operator/api => github.com/Deydra71/swift-operator/api v0.0.0-20251103103412-f201b1caed51 + +replace github.com/openstack-k8s-operators/manila-operator/api => github.com/Deydra71/manila-operator/api v0.0.0-20251103105945-a1a7e6a68acb + +replace github.com/openstack-k8s-operators/neutron-operator/api => github.com/Deydra71/neutron-operator/api v0.0.0-20251110111522-92da1dc44ef2 + +replace github.com/openstack-k8s-operators/placement-operator/api => github.com/Deydra71/placement-operator/api v0.0.0-20251110112720-6c8e2ac62669 \ No newline at end of file diff --git a/apis/go.sum b/apis/go.sum index 0bf8b0532..134316b61 100644 --- a/apis/go.sum +++ b/apis/go.sum @@ -1,3 +1,17 @@ +github.com/Deydra71/barbican-operator/api v0.0.0-20251103101323-46355b1793bf h1:buyWKcSAgJZCjRg5hx7ebQITFmUV4ed7aE7nMdhE/qs= +github.com/Deydra71/barbican-operator/api v0.0.0-20251103101323-46355b1793bf/go.mod h1:A0S5Z0+duN9bKqW2eLpwtP+JjJMbAde1MkjKP0q5eDQ= +github.com/Deydra71/cinder-operator/api v0.0.0-20251103142104-0e9fbab80ef4 h1:vOnKHiDM3zgIEo1F1vr3G/S0UWHH+A8Py5TjbbLwRh4= +github.com/Deydra71/cinder-operator/api v0.0.0-20251103142104-0e9fbab80ef4/go.mod h1:dMvuD60r9mpwwBd+4yK3W0jR9S2jdYs6rQ84i1XUvKE= +github.com/Deydra71/glance-operator/api v0.0.0-20251103102702-77f7cfe01e3c h1:1d9Z08PXUK1hmozlp0Xi1JUSvh7LCiu1uP8+YjLTRiE= +github.com/Deydra71/glance-operator/api v0.0.0-20251103102702-77f7cfe01e3c/go.mod h1:Ij/yka+SFp7krWedAgcpkymj0e0PiLWJPB0CNYMOe08= +github.com/Deydra71/keystone-operator/api v0.0.0-20251111075800-83054d6ff4b8 h1:ph9qoP7sPAZqydaWMWC1WXhuXk0ENY55toyq+sjUCa8= +github.com/Deydra71/keystone-operator/api v0.0.0-20251111075800-83054d6ff4b8/go.mod h1:FMFoO4MjEQ85JpdLtDHxYSZxvJ9KzHua+HdKhpl0KRI= +github.com/Deydra71/manila-operator/api v0.0.0-20251103105945-a1a7e6a68acb h1:LvL4JwnIKe3ooBvXQszQyigBr21wnvGhecbx4g0zetE= +github.com/Deydra71/manila-operator/api v0.0.0-20251103105945-a1a7e6a68acb/go.mod h1:T3l1aWpo01IZX3JrgmDPr9vzrXMMBPgloJJbHt5m+4M= +github.com/Deydra71/neutron-operator/api v0.0.0-20251110111522-92da1dc44ef2 h1:oPO/Q+Q21e7ypELSYXD3OsIK4Izlv7nD+5vXwqErAv0= +github.com/Deydra71/placement-operator/api v0.0.0-20251110112720-6c8e2ac62669 h1:Rv9LXqsjinxI8+X9H6gu2BpMtqLfyZnrGkkNa1PbsGI= +github.com/Deydra71/swift-operator/api v0.0.0-20251103103412-f201b1caed51 h1:qfyxJiDSzIwrR5qL6eNGglkxF/UkmhqLCmCDjtPWuRw= +github.com/Deydra71/swift-operator/api v0.0.0-20251103103412-f201b1caed51/go.mod h1:4eX/dWpBMzIxSjoShJJeRLa988yKfPulIj4Dqxmo2yI= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -108,42 +122,30 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.27.1 h1:0LJC8MpUSQnfnp4n/3W3GdlmJP3ENGF0ZPzjQGLPP7s= -github.com/onsi/ginkgo/v2 v2.27.1/go.mod h1:wmy3vCqiBjirARfVhAqFpYt8uvX0yaFe+GudAqqcCqA= +github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/openshift/api v0.0.0-20250711200046-c86d80652a9e h1:E1OdwSpqWuDPCedyUt0GEdoAE+r5TXy7YS21yNEo+2U= github.com/openshift/api v0.0.0-20250711200046-c86d80652a9e/go.mod h1:Shkl4HanLwDiiBzakv+con/aMGnVE2MAGvoKp5oyYUo= -github.com/openstack-k8s-operators/barbican-operator/api v0.6.1-0.20251014175433-c4ab8419a351 h1:z+3DmAT3CkEFpI82sjMCTgfLR/Gr+Z7+jfzgZmUHVa8= -github.com/openstack-k8s-operators/barbican-operator/api v0.6.1-0.20251014175433-c4ab8419a351/go.mod h1:DtYNaat+pImzGhh+RgfLeSmUEqw6J/TqytTYbvxVg7E= -github.com/openstack-k8s-operators/cinder-operator/api v0.6.1-0.20251014173752-ea967e56a392 h1:lhMAeJgrD7fBL26pyzp/SVDiVZ7wr3P+ys+h6dsFM1Q= -github.com/openstack-k8s-operators/cinder-operator/api v0.6.1-0.20251014173752-ea967e56a392/go.mod h1:HIDWCoybpcyE2/wacsucEm+1dfo5d+Wr6TAQ3+vOaQc= github.com/openstack-k8s-operators/designate-operator/api v0.6.1-0.20251022085840-31cb063eeb8a h1:To9zRB8ilQEwkKZ8MXLe5+zaVXail+bjknMVLo3F09Y= github.com/openstack-k8s-operators/designate-operator/api v0.6.1-0.20251022085840-31cb063eeb8a/go.mod h1:8R9RYAjEwq+WrgKS558pvMa1Zt5WkAOQEJChloFOKzY= -github.com/openstack-k8s-operators/glance-operator/api v0.6.1-0.20251022111742-64b4039d28a7 h1:rnR6Qq+R6V/7ZF+50fsSYcSD8SMRgQdiqdT+w2mfThM= -github.com/openstack-k8s-operators/glance-operator/api v0.6.1-0.20251022111742-64b4039d28a7/go.mod h1:fK1M/vQi/TxrZmQvRxgIj998sPHo/v0zC0YUgJ25fU0= github.com/openstack-k8s-operators/heat-operator/api v0.6.1-0.20251025092254-de6e9a251638 h1:5Cj3+iee4jhV/WvrPysevisQlTIgmOdREn1mt7JHrw4= github.com/openstack-k8s-operators/heat-operator/api v0.6.1-0.20251025092254-de6e9a251638/go.mod h1:/o8HTAMKnnrETQvJCBXP90yb7kkm0tdfYqp6HUI8Ji0= github.com/openstack-k8s-operators/horizon-operator/api v0.6.1-0.20251025090908-00fab1da8f24 h1:jexX3KB+ZiO8h2oF3zzTWA3epgRI6HWoizRA0G/V10g= github.com/openstack-k8s-operators/horizon-operator/api v0.6.1-0.20251025090908-00fab1da8f24/go.mod h1:QSWFlRcNJF9dbQOSREC4XceAveBvKM/hwrPXLtHJheM= -github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251025092254-9bbe85d92ae4 h1:jIjn2kuj7P2NX/Qr1JzJ6qGqzeEUIPZcKg/AJTt8wUg= -github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251025092254-9bbe85d92ae4/go.mod h1:anuOdjhIQFtRmAiWeBVxwfOBbEAMmZPYuM9GamFq8AQ= +github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251030184102-82d2cbaafd35 h1:QFFGu93A+XCvDUxZIgfBE4gB5hEdVQAIw+E8dF1kP/E= +github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251030184102-82d2cbaafd35/go.mod h1:qq8BCRxTEmLRriUsQ4HeDUzqltWg32MQPDTMhgbBGK4= github.com/openstack-k8s-operators/ironic-operator/api v0.6.1-0.20251023190508-87e9d60da59a h1:ROX3Vxh019mrBfKYAyVK2VcM8CZ0fpXT3pXNvhc0iUs= github.com/openstack-k8s-operators/ironic-operator/api v0.6.1-0.20251023190508-87e9d60da59a/go.mod h1:EqncaSISzZANZh/oXfwpwtlAgWZh5lmPnNVRfBusfxo= -github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20251021163720-bb51cea0d967 h1:3M5wpX25sGAxdj3zkN0Cr9+PL7b8+QaCb0ivbGseCI0= -github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20251021163720-bb51cea0d967/go.mod h1:0aizgUSdLK6TgZ1ATE6s/Cca/V+CLyMS2Mznyoq1Gjo= -github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251021145236-2b84ec9fd9bb h1:s4qKlH16Ofqd9ptA0quFsCjyk8V44FyutB9sJ18yD6A= -github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251021145236-2b84ec9fd9bb/go.mod h1:GRTwOi5ZI6aJrTune36iWP5zNNjVLZNsV9Kb7IK3UJ0= +github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251027074416-ab5c045dbe00 h1:Xih6tYYqiDVllo4fDGHqTPL+M2biO5YLOUmbiTqrW/I= +github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251027074416-ab5c045dbe00/go.mod h1:PMoNILOdQ1Ij7DyrKgljN6RAiq8pFM2AGsUb6mcxe98= github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20251021145236-2b84ec9fd9bb h1:wToXqX7AS1JV3Kna7RcJfkRart8rSGun2biKNfyY6Zg= github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20251021145236-2b84ec9fd9bb/go.mod h1:yf13jWb60XV26eA7A8o86ZCXNWBLNK9dPkTSWFaTPCw= -github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20251021145236-2b84ec9fd9bb h1:/EVeLrhVcnb/x86fZCyEAc2uVhLI8AcWikWT/sCA5b0= -github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20251021145236-2b84ec9fd9bb/go.mod h1:uiWDgmoC+p6mn+ZaFvkgRPQlb8ZHz5ZdXT+Zv4j/Wac= -github.com/openstack-k8s-operators/manila-operator/api v0.6.1-0.20251025092538-cee75eec6178 h1:j4tSNL0dieDOceWBL/0epgfbL7VsWAZg70PUBEsxPdI= -github.com/openstack-k8s-operators/manila-operator/api v0.6.1-0.20251025092538-cee75eec6178/go.mod h1:BGE8wpbMHx6v4Ngt/OfZaQm+sy0f8y6SJ0apZhKCjAg= +github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20251027074416-ab5c045dbe00 h1:XQ4Zl7P+3Yfe0YotB+U9xaipq42U1FByRmrEWvChldg= +github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20251027074416-ab5c045dbe00/go.mod h1:OX2kn3of+eopoVjApgydosWJNKTROjtx/GBZUfaT4mY= github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20251015110425-ad0381ce8cd4 h1:4qDSDLX7HpCIdnlUExyPc3DkyCq+73PLPb99FVj1CZk= github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20251015110425-ad0381ce8cd4/go.mod h1:lOZNSKG7MMkhMjL7OQXKscy+dH2mxs3HPD+oj4wVytA= -github.com/openstack-k8s-operators/neutron-operator/api v0.6.1-0.20251016170447-17d48235c379 h1:jkiJRBsklxDAUxjAlRXJASd1GOek4c8w/Ka2GYifcJk= -github.com/openstack-k8s-operators/neutron-operator/api v0.6.1-0.20251016170447-17d48235c379/go.mod h1:MYz2CgQILsE/tGjGMIPfkGpKkHOqIeCY57rhwmfxHzU= github.com/openstack-k8s-operators/nova-operator/api v0.6.1-0.20251022144230-a61d2a7dde8c h1:vPFQuE7vJaSwW+7HjzeiF9quSuS+ODJwXqemb7GH+o4= github.com/openstack-k8s-operators/nova-operator/api v0.6.1-0.20251022144230-a61d2a7dde8c/go.mod h1:X2+h5BeIC6YPOOlIXzWlIllyUACChuU6rLL01R3CVuc= github.com/openstack-k8s-operators/octavia-operator/api v0.6.1-0.20251022084705-f7d8ed01fa05 h1:iJS6ISpiOCQZ9tmdqjhQlawVNAguPMVGBOHb7H3bAQE= @@ -152,12 +154,8 @@ github.com/openstack-k8s-operators/openstack-baremetal-operator/api v0.6.1-0.202 github.com/openstack-k8s-operators/openstack-baremetal-operator/api v0.6.1-0.20251016050458-7c5c8fc69a7a/go.mod h1:He7rGGmvfl1lzn+OJ0jV1tU6b8+otlCCrRx0T3WxlAQ= github.com/openstack-k8s-operators/ovn-operator/api v0.6.1-0.20251020102141-f19d0ee25e0f h1:4RH4gFZKRRTjJCLmEbUrQLRWC+wfThHoRapS/nPBbl4= github.com/openstack-k8s-operators/ovn-operator/api v0.6.1-0.20251020102141-f19d0ee25e0f/go.mod h1:RTW7SRp+Fn8JmIjdOgLl3GB3tTAhnI0q2XgauR1eEUM= -github.com/openstack-k8s-operators/placement-operator/api v0.6.1-0.20251016091846-46ae39c6d532 h1:Kz2YSBptRCoHu5ie44IJ4rhJ/Unm9Yxdj6wIuv+lc8o= -github.com/openstack-k8s-operators/placement-operator/api v0.6.1-0.20251016091846-46ae39c6d532/go.mod h1:tT7pLlledNe6qxzJPmgG4Vt3y8C8hjlUli0rPBeAiz0= github.com/openstack-k8s-operators/rabbitmq-cluster-operator/v2 v2.6.1-0.20250929174222-a0d328fa4dec h1:saovr368HPAKHN0aRPh8h8n9s9dn3d8Frmfua0UYRlc= github.com/openstack-k8s-operators/rabbitmq-cluster-operator/v2 v2.6.1-0.20250929174222-a0d328fa4dec/go.mod h1:Nh2NEePLjovUQof2krTAg4JaAoLacqtPTZQXK6izNfg= -github.com/openstack-k8s-operators/swift-operator/api v0.6.1-0.20251022081645-83643617513b h1:Xj0Tb70tvsIMdBb0ap/3edx3zY5zyrLlDxac/Uwd4jU= -github.com/openstack-k8s-operators/swift-operator/api v0.6.1-0.20251022081645-83643617513b/go.mod h1:Wxqy0y7uw0zBZ+bvU+aVUUedPnI+RnUm6ci1hVdad4w= github.com/openstack-k8s-operators/telemetry-operator/api v0.6.1-0.20251023173049-bffdcca1b8c9 h1:dOP0npvCEEDoID7m3xhBeSTH+FmwBqyPzEVCsbOOv64= github.com/openstack-k8s-operators/telemetry-operator/api v0.6.1-0.20251023173049-bffdcca1b8c9/go.mod h1:zyFQU87rwagrykCBLM4KdmGAYOFxzKcOOfWDoohxrD0= github.com/openstack-k8s-operators/watcher-operator/api v0.6.1-0.20251024094646-553201ce9553 h1:2YIYwj1BNt8OggMICOj1PTopFBhh/PfwS+3G8gMEJRg= @@ -167,8 +165,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= @@ -203,8 +199,6 @@ 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= -go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= -go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= 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= diff --git a/bindata/crds/crds.yaml b/bindata/crds/crds.yaml index 47fd5661c..f6424d16f 100644 --- a/bindata/crds/crds.yaml +++ b/bindata/crds/crds.yaml @@ -206,6 +206,49 @@ spec: type: object spec: properties: + applicationCredential: + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + default: 365 + minimum: 2 + type: integer + gracePeriodDays: + default: 182 + minimum: 1 + type: integer + roles: + default: + - service + items: + type: string + minItems: 1 + type: array + unrestricted: + default: false + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: self.gracePeriodDays < self.expirationDays barbican: properties: apiOverride: @@ -332,6 +375,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -840,6 +924,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -1869,6 +1994,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean @@ -3747,6 +3913,47 @@ spec: type: object type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -4675,6 +4882,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' cnfAPIOverride: properties: route: @@ -6610,6 +6858,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean @@ -8262,6 +8551,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean @@ -9329,6 +9659,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -10159,6 +10530,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' cellOverride: additionalProperties: properties: @@ -11227,6 +11639,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean @@ -12703,6 +13156,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -13732,6 +14226,47 @@ spec: type: string swift: properties: + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -14379,6 +14914,88 @@ spec: type: string type: object type: object + aodhApplicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -15813,6 +16430,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean diff --git a/bindata/crds/keystone.openstack.org_keystoneapplicationcredentials.yaml b/bindata/crds/keystone.openstack.org_keystoneapplicationcredentials.yaml new file mode 100644 index 000000000..8e3ff25d4 --- /dev/null +++ b/bindata/crds/keystone.openstack.org_keystoneapplicationcredentials.yaml @@ -0,0 +1,212 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + creationTimestamp: null + name: keystoneapplicationcredentials.keystone.openstack.org +spec: + group: keystone.openstack.org + names: + kind: KeystoneApplicationCredential + listKind: KeystoneApplicationCredentialList + plural: keystoneapplicationcredentials + shortNames: + - appcred + singular: keystoneapplicationcredential + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Keystone ApplicationCredential ID + jsonPath: .status.acID + name: ACID + type: string + - description: Secret holding ApplicationCredential secret + jsonPath: .status.secretName + name: SecretName + type: string + - description: Last rotation time + jsonPath: .status.lastRotated + name: LastRotated + type: date + - description: When rotation becomes eligible + jsonPath: .status.rotationEligibleAt + name: RotationEligible + type: date + - description: Status + jsonPath: .status.conditions[0].status + name: Status + type: string + - description: Message + jsonPath: .status.conditions[0].message + name: Message + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: KeystoneApplicationCredential is the Schema for the applicationcredentials + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: KeystoneApplicationCredentialSpec defines what the user can + set + properties: + accessRules: + description: AccessRules defines which services the ApplicationCredential + is permitted to access + items: + description: ACRule defines a additional access rule for an ApplicationCredential + properties: + method: + description: Method is the HTTP verb to allow (defaults to all + if empty) + type: string + path: + description: Path is the API path to allow + type: string + service: + description: Service is the OpenStack service type + type: string + type: object + type: array + expirationDays: + default: 365 + description: ExpirationDays sets the lifetime in days for the ApplicationCredential + minimum: 2 + type: integer + gracePeriodDays: + default: 182 + description: GracePeriodDays sets how many days before expiration + the ApplicationCredential should be rotated + minimum: 1 + type: integer + passwordSelector: + description: PasswordSelector for extracting the service password + type: string + roles: + description: Roles to assign to the ApplicationCredential + items: + type: string + minItems: 1 + type: array + secret: + description: Secret containing service user password + type: string + unrestricted: + default: false + description: Unrestricted indicates whether the ApplicationCredential + may be used to create or destroy other credentials or trusts + type: boolean + userName: + description: UserName - the Keystone user under which this ApplicationCredential + is created + type: string + required: + - passwordSelector + - roles + - secret + - userName + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: self.gracePeriodDays < self.expirationDays + status: + description: KeystoneApplicationCredentialStatus defines the observed + state + properties: + acID: + description: ACID - the ID in Keystone for this ApplicationCredential + type: string + conditions: + description: Conditions + items: + description: Condition defines an observation of a API resource + operational state. + properties: + lastTransitionTime: + description: |- + Last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when + the API field changed is acceptable. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. + type: string + severity: + description: |- + Severity provides a classification of Reason code, so the current situation is immediately + understandable and could act accordingly. + It is meant for situations where Status=False and it should be indicated if it is just + informational, warning (next reconciliation might fix it) or an error (e.g. DB create issue + and no actions to automatically resolve the issue can/should be done). + For conditions where Status=Unknown or Status=True the Severity should be SeverityNone. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition in CamelCase. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + createdAt: + description: CreatedAt - timestap of creation + format: date-time + type: string + expiresAt: + description: ExpiresAt - time of validity expiration + format: date-time + type: string + lastRotated: + description: LastRotated - timestamp when credentials were last rotated + format: date-time + type: string + rotationEligibleAt: + description: |- + RotationEligibleAt indicates when rotation becomes eligible (start of grace period window). + Computed as ExpiresAt - GracePeriodDays. The AC can be rotated after this timestamp. + format: date-time + type: string + secretName: + description: SecretName - name of the k8s Secret storing the ApplicationCredential + secret + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/bindata/rbac/keystone-operator-rbac.yaml b/bindata/rbac/keystone-operator-rbac.yaml index d86c4d32e..1f03dea89 100644 --- a/bindata/rbac/keystone-operator-rbac.yaml +++ b/bindata/rbac/keystone-operator-rbac.yaml @@ -65,6 +65,24 @@ rules: - patch - update - watch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - "" + resources: + - secrets/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update - apiGroups: - "" resources: @@ -113,6 +131,7 @@ rules: - keystone.openstack.org resources: - keystoneapis + - keystoneapplicationcredentials - keystoneendpoints - keystoneservices verbs: @@ -127,6 +146,7 @@ rules: - keystone.openstack.org resources: - keystoneapis/finalizers + - keystoneapplicationcredentials/finalizers - keystoneendpoints/finalizers - keystoneservices/finalizers verbs: @@ -136,6 +156,7 @@ rules: - keystone.openstack.org resources: - keystoneapis/status + - keystoneapplicationcredentials/status - keystoneendpoints/status - keystoneservices/status verbs: diff --git a/bindata/rbac/rbac.yaml b/bindata/rbac/rbac.yaml index 09a3fd41b..760471a43 100644 --- a/bindata/rbac/rbac.yaml +++ b/bindata/rbac/rbac.yaml @@ -385,6 +385,7 @@ rules: - keystone.openstack.org resources: - keystoneapis + - keystoneapplicationcredentials verbs: - create - delete @@ -393,6 +394,14 @@ rules: - patch - update - watch +- apiGroups: + - keystone.openstack.org + resources: + - keystoneapplicationcredentials/status + verbs: + - get + - patch + - update - apiGroups: - machineconfiguration.openshift.io resources: diff --git a/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml b/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml index 66d2a43a0..fa4df5d20 100644 --- a/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml +++ b/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml @@ -40,6 +40,49 @@ spec: type: object spec: properties: + applicationCredential: + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + default: 365 + minimum: 2 + type: integer + gracePeriodDays: + default: 182 + minimum: 1 + type: integer + roles: + default: + - service + items: + type: string + minItems: 1 + type: array + unrestricted: + default: false + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: self.gracePeriodDays < self.expirationDays barbican: properties: apiOverride: @@ -166,6 +209,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -674,6 +758,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -1703,6 +1828,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean @@ -3581,6 +3747,47 @@ spec: type: object type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -4509,6 +4716,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' cnfAPIOverride: properties: route: @@ -6444,6 +6692,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean @@ -8096,6 +8385,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean @@ -9163,6 +9493,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -9993,6 +10364,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' cellOverride: additionalProperties: properties: @@ -11061,6 +11473,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean @@ -12537,6 +12990,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -13566,6 +14060,47 @@ spec: type: string swift: properties: + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -14213,6 +14748,88 @@ spec: type: string type: object type: object + aodhApplicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: true type: boolean @@ -15647,6 +16264,47 @@ spec: type: string type: object type: object + applicationCredential: + default: + enabled: false + nullable: true + properties: + accessRules: + items: + properties: + method: + type: string + path: + type: string + service: + type: string + required: + - method + - path + - service + type: object + type: array + x-kubernetes-list-type: atomic + enabled: + default: false + type: boolean + expirationDays: + minimum: 2 + type: integer + gracePeriodDays: + minimum: 1 + type: integer + roles: + items: + type: string + type: array + unrestricted: + type: boolean + type: object + x-kubernetes-validations: + - message: gracePeriodDays must be smaller than expirationDays + rule: '!(has(self.expirationDays) && has(self.gracePeriodDays)) + || self.gracePeriodDays < self.expirationDays' enabled: default: false type: boolean diff --git a/config/manifests/bases/openstack-operator.clusterserviceversion.yaml b/config/manifests/bases/openstack-operator.clusterserviceversion.yaml index a78a4a5da..690bba46c 100644 --- a/config/manifests/bases/openstack-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/openstack-operator.clusterserviceversion.yaml @@ -38,6 +38,9 @@ spec: kind: OpenStackControlPlane name: openstackcontrolplanes.core.openstack.org specDescriptors: + - description: ApplicationCredential - Parameters related to the ApplicationCredential + displayName: Application Credential + path: applicationCredential - description: Barbican - Parameters related to the Barbican service displayName: Barbican path: barbican @@ -48,6 +51,10 @@ spec: - description: TLS - overrides tls parameters for public endpoint displayName: TLS path: barbican.apiOverride.tls + - description: ApplicationCredential allows service-specific overrides of the + global AC configuration. + displayName: Application Credential + path: barbican.applicationCredential - description: Enabled - Whether Barbican service should be deployed and managed displayName: Enabled path: barbican.enabled @@ -66,6 +73,10 @@ spec: - description: TLS - overrides tls parameters for public endpoint displayName: TLS path: cinder.apiOverride.tls + - description: ApplicationCredential allows service-specific overrides of the + global AC configuration. + displayName: Application Credential + path: cinder.applicationCredential - description: Enabled - Whether Cinder service should be deployed and managed displayName: Enabled path: cinder.enabled @@ -131,6 +142,10 @@ spec: - description: TLS - overrides tls parameters for public endpoint displayName: TLS path: glance.apiOverrides.tls + - description: ApplicationCredential allows service-specific overrides of the + global AC configuration. + displayName: Application Credential + path: glance.applicationCredential - description: Enabled - Whether Glance service should be deployed and managed displayName: Enabled path: glance.enabled @@ -264,6 +279,10 @@ spec: - description: TLS - overrides tls parameters for public endpoint displayName: TLS path: neutron.apiOverride.tls + - description: ApplicationCredential allows service-specific overrides of the + global AC configuration. + displayName: Application Credential + path: neutron.applicationCredential - description: Enabled - Whether Neutron service should be deployed and managed displayName: Enabled path: neutron.enabled @@ -286,6 +305,10 @@ spec: - description: TLS - overrides tls parameters for public endpoint displayName: TLS path: nova.apiOverride.tls + - description: ApplicationCredential allows service-specific overrides of the + global AC configuration. + displayName: Application Credential + path: nova.applicationCredential - description: CellOverride, provides the ability to override the generated manifest of several child resources for a nova cell. cell0 never have compute nodes and therefore it won't have a noVNCProxy deployed. Providing an override @@ -364,6 +387,10 @@ spec: - description: TLS - overrides tls parameters for public endpoint displayName: TLS path: placement.apiOverride.tls + - description: ApplicationCredential allows service-specific overrides of the + global AC configuration. + displayName: Application Credential + path: placement.applicationCredential - description: Enabled - Whether Placement service should be deployed and managed displayName: Enabled path: placement.enabled @@ -404,6 +431,10 @@ spec: - description: Swift - Parameters related to the Swift service displayName: Swift path: swift + - description: ApplicationCredential allows service-specific overrides of the + global AC configuration. + displayName: Application Credential + path: swift.applicationCredential - description: Enabled - Whether Swift service should be deployed and managed displayName: Enabled path: swift.enabled @@ -436,6 +467,10 @@ spec: - description: TLS - overrides tls parameters for public endpoint displayName: TLS path: telemetry.aodhApiOverride.tls + - description: ApplicationCredential allows service-specific overrides of the + global AC configuration. + displayName: Application Credential + path: telemetry.applicationCredential - description: Enabled - Whether OpenStack Telemetry services should be deployed and managed displayName: Enabled diff --git a/config/operator/deployment/kustomization.yaml b/config/operator/deployment/kustomization.yaml index 6ca4c7dc7..7970d7813 100644 --- a/config/operator/deployment/kustomization.yaml +++ b/config/operator/deployment/kustomization.yaml @@ -12,5 +12,48 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization images: - name: controller - newName: quay.io/openstack-k8s-operators/openstack-operator - newTag: latest + newName: quay.io/rh-ee-vfisarov/openstack-operator + newTag: v0.0.1 +patches: +- patch: '[{"op": "replace", "path": "/spec/template/spec/containers/1/env/0", "value": + {"name": "OPENSTACK_RELEASE_VERSION", "value": "0.3.0-1744882474"}}]' + target: + kind: Deployment + name: openstack-operator-controller-operator + namespace: system +- patch: '[{"op": "replace", "path": "/spec/template/spec/containers/1/env/1", "value": + {"name": "OPERATOR_IMAGE_URL", "value": "quay.io/openstack-k8s-operators/openstack-operator:latest"}}]' + target: + kind: Deployment + name: openstack-operator-controller-operator + namespace: system +- patch: '[{"op": "replace", "path": "/spec/template/spec/containers/1/env/0", "value": + {"name": "OPENSTACK_RELEASE_VERSION", "value": "0.3.0-1744883041"}}]' + target: + kind: Deployment + name: openstack-operator-controller-operator + namespace: system +- patch: '[{"op": "replace", "path": "/spec/template/spec/containers/1/env/0", "value": + {"name": "OPENSTACK_RELEASE_VERSION", "value": "0.3.0-1744883133"}}]' + target: + kind: Deployment + name: openstack-operator-controller-operator + namespace: system +- patch: '[{"op": "replace", "path": "/spec/template/spec/containers/1/env/0", "value": + {"name": "OPENSTACK_RELEASE_VERSION", "value": "0.3.0-1745922411"}}]' + target: + kind: Deployment + name: openstack-operator-controller-operator + namespace: system +- patch: '[{"op": "replace", "path": "/spec/template/spec/containers/1/env/0", "value": + {"name": "OPENSTACK_RELEASE_VERSION", "value": "0.0.1-1748436359"}}]' + target: + kind: Deployment + name: openstack-operator-controller-operator + namespace: system +- patch: '[{"op": "replace", "path": "/spec/template/spec/containers/1/env/1", "value": + {"name": "OPERATOR_IMAGE_URL", "value": "quay.io/rh-ee-vfisarov/openstack-operator:v0.0.1"}}]' + target: + kind: Deployment + name: openstack-operator-controller-operator + namespace: system diff --git a/config/operator/manager_operator_images.yaml b/config/operator/manager_operator_images.yaml index 3e5ac55f6..d7991f5ef 100644 --- a/config/operator/manager_operator_images.yaml +++ b/config/operator/manager_operator_images.yaml @@ -14,29 +14,29 @@ spec: - name: operator env: - name: RELATED_IMAGE_BARBICAN_OPERATOR_MANAGER_IMAGE_URL - value: quay.io/openstack-k8s-operators/barbican-operator@sha256:2b673886e5632955ed22e40622f3a1d6be00e7ebe7535f3a0ed25cb67ee1a9d1 + value: quay.io/rh-ee-vfisarov/barbican-operator@sha256:bc8de744f58f16642c0394353bd6619fae98e07c6b28932b0d1660c6e468bec4 - name: RELATED_IMAGE_CINDER_OPERATOR_MANAGER_IMAGE_URL - value: quay.io/openstack-k8s-operators/cinder-operator@sha256:c5f2ac270a982a599e665960ae2622703421f3b5bd2952dc0a82735c474eb9a8 + value: quay.io/rh-ee-vfisarov/cinder-operator@sha256:7ece03d39b09ebc3ad904fce2e43730768023ba4e1eb08a2075c326e5cb1b705 - name: RELATED_IMAGE_DESIGNATE_OPERATOR_MANAGER_IMAGE_URL value: quay.io/openstack-k8s-operators/designate-operator@sha256:c20f1cf4f8a94c1658a253b546c96d4052cbee9cce3a3c1c884904ef1a1c4a25 - name: RELATED_IMAGE_GLANCE_OPERATOR_MANAGER_IMAGE_URL - value: quay.io/openstack-k8s-operators/glance-operator@sha256:46875c236a83d6e07d3f817857e1ce4d21508ddaf326a2e320e2ee56d15b8123 + value: quay.io/rh-ee-vfisarov/glance-operator@sha256:ce414f728de2a3c807306647b8133f838439578888a0cbc4632f99f084df398c - name: RELATED_IMAGE_HEAT_OPERATOR_MANAGER_IMAGE_URL value: quay.io/openstack-k8s-operators/heat-operator@sha256:25a0194f58a30b212ee9f4a8fb949cc834a9212374920d1bb6adedc14c72abf6 - name: RELATED_IMAGE_HORIZON_OPERATOR_MANAGER_IMAGE_URL value: quay.io/openstack-k8s-operators/horizon-operator@sha256:f023985eb4e1830638f341ff409e4370d016b3b7508ff30e61744a8cfa67a155 - name: RELATED_IMAGE_INFRA_OPERATOR_MANAGER_IMAGE_URL - value: quay.io/openstack-k8s-operators/infra-operator@sha256:810bea5c7caaace8aa8388545d110e7c6e412c6f7ba0e74d027970ec394690d0 + value: quay.io/openstack-k8s-operators/infra-operator@sha256:81ad8f03c545397f27e1d100014ce452593d9010302e525772ceb40d3d2e82dc - name: RELATED_IMAGE_IRONIC_OPERATOR_MANAGER_IMAGE_URL value: quay.io/openstack-k8s-operators/ironic-operator@sha256:fc00fca9f5462acded19bf9a866d7a879b2cc5eb126a4eb20dde9d43cc2f6392 - name: RELATED_IMAGE_KEYSTONE_OPERATOR_MANAGER_IMAGE_URL - value: quay.io/openstack-k8s-operators/keystone-operator@sha256:cce57d1528476d1b22ee5d7cac3b178762f4e087b80feda35fbbcdd74ee2e378 + value: quay.io/rh-ee-vfisarov/keystone-operator@sha256:a1056dcb69538dd2a508c665848ac0b7f909293856929c01cfea379e3cd405b7 - name: RELATED_IMAGE_MANILA_OPERATOR_MANAGER_IMAGE_URL - value: quay.io/openstack-k8s-operators/manila-operator@sha256:c8a28d99a2de585df772e1d495c8dbc7e9b25a71f18c677b3f15aea6b275ca92 + value: quay.io/rh-ee-vfisarov/manila-operator@sha256:531052a1b971c25a6d4478884cff46200a3800ed96ca2c63a305ddbccd825e4a - name: RELATED_IMAGE_MARIADB_OPERATOR_MANAGER_IMAGE_URL value: quay.io/openstack-k8s-operators/mariadb-operator@sha256:3451ff344ece308690d7ee33e376cef52e177e61f7795819d222d086cccbe951 - name: RELATED_IMAGE_NEUTRON_OPERATOR_MANAGER_IMAGE_URL - value: quay.io/openstack-k8s-operators/neutron-operator@sha256:9b541a92154ae0d5e98e8c0ca0b31556daeffb603ca08ca5fc81d825adce1f16 + value: quay.io/rh-ee-vfisarov/neutron-operator@sha256:cefeb1d97b8f3b38c4314d259d02d5a937b9112e5842d9764bebbd1a750b2f27 - name: RELATED_IMAGE_NOVA_OPERATOR_MANAGER_IMAGE_URL value: quay.io/openstack-k8s-operators/nova-operator@sha256:d1b9745674b362cb2aad70c18db4da4ac01a0a1eafdeba6f5c902596e632c131 - name: RELATED_IMAGE_OCTAVIA_OPERATOR_MANAGER_IMAGE_URL @@ -46,11 +46,11 @@ spec: - name: RELATED_IMAGE_OVN_OPERATOR_MANAGER_IMAGE_URL value: quay.io/openstack-k8s-operators/ovn-operator@sha256:9ed3e90ad9a4613c6c9c924487006183539b153fc00136ed37b3732f9f6ca2f2 - name: RELATED_IMAGE_PLACEMENT_OPERATOR_MANAGER_IMAGE_URL - value: quay.io/openstack-k8s-operators/placement-operator@sha256:f4ff739c066e6ba873376bd1cdb533b68b8ffa38f0e399b0d315476c05c6b322 + value: quay.io/rh-ee-vfisarov/placement-operator@sha256:712883ea4c3913b28a585ca030aa6fa4be0ba5fc544e5253bf1f6d4cf24e3f79 - name: RELATED_IMAGE_RABBITMQ_CLUSTER_OPERATOR_MANAGER_IMAGE_URL value: quay.io/openstack-k8s-operators/rabbitmq-cluster-operator@sha256:893e66303c1b0bc1d00a299a3f0380bad55c8dc813c8a1c6a4aab379f5aa12a2 - name: RELATED_IMAGE_SWIFT_OPERATOR_MANAGER_IMAGE_URL - value: quay.io/openstack-k8s-operators/swift-operator@sha256:8ed782cb1a952aa31950a9153a51c25fc30b130a928b58e0870e1071d5e5efbe + value: quay.io/rh-ee-vfisarov/swift-operator@sha256:aaf1a55bca9ec0a09a1fd519a982dd33bbf6fc9cc45b3641849d7d058f9d98ba - name: RELATED_IMAGE_TELEMETRY_OPERATOR_MANAGER_IMAGE_URL value: quay.io/openstack-k8s-operators/telemetry-operator@sha256:7c7268354f4ce92a0112580323172c603f39eb8339098f40cda9a8e58b4a98e4 - name: RELATED_IMAGE_TEST_OPERATOR_MANAGER_IMAGE_URL diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 7decfd254..9f56f9f81 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -342,6 +342,7 @@ rules: - keystone.openstack.org resources: - keystoneapis + - keystoneapplicationcredentials verbs: - create - delete @@ -350,6 +351,14 @@ rules: - patch - update - watch +- apiGroups: + - keystone.openstack.org + resources: + - keystoneapplicationcredentials/status + verbs: + - get + - patch + - update - apiGroups: - machineconfiguration.openshift.io resources: diff --git a/config/samples/applicationcredentials/kustomization.yaml b/config/samples/applicationcredentials/kustomization.yaml new file mode 100644 index 000000000..c7cbe3ecf --- /dev/null +++ b/config/samples/applicationcredentials/kustomization.yaml @@ -0,0 +1,14 @@ +resources: +- ../base/openstackcontrolplane + +patches: +- target: + kind: OpenStackControlPlane + name: .* + patch: |- + - op: replace + path: /metadata/name + value: openstack +- target: + kind: OpenStackControlPlane + path: patch.yaml diff --git a/config/samples/applicationcredentials/patch.yaml b/config/samples/applicationcredentials/patch.yaml new file mode 100644 index 000000000..566cac6f4 --- /dev/null +++ b/config/samples/applicationcredentials/patch.yaml @@ -0,0 +1,33 @@ +apiVersion: core.openstack.org/v1beta1 +kind: OpenStackControlPlane +metadata: + name: openstack +spec: + applicationCredential: + enabled: true + expirationDays: 200 + gracePeriodDays: 90 + roles: + - service + unrestricted: false + barbican: + applicationCredential: + enabled: true + glance: + applicationCredential: + enabled: true + swift: + applicationCredential: + enabled: true + cinder: + applicationCredential: + enabled: true + expirationDays: 10 + gracePeriodDays: 5 + roles: + - admin + - service + unrestricted: true + manila: + applicationCredential: + enabled: true diff --git a/controllers/core/openstackcontrolplane_controller.go b/controllers/core/openstackcontrolplane_controller.go index 1f2a31e93..f130e6143 100644 --- a/controllers/core/openstackcontrolplane_controller.go +++ b/controllers/core/openstackcontrolplane_controller.go @@ -92,6 +92,8 @@ func (r *OpenStackControlPlaneReconciler) GetLogger(ctx context.Context) logr.Lo // +kubebuilder:rbac:groups=client.openstack.org,resources=openstackclients,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=horizon.openstack.org,resources=horizons,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=keystone.openstack.org,resources=keystoneapis,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=keystone.openstack.org,resources=keystoneapplicationcredentials,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=keystone.openstack.org,resources=keystoneapplicationcredentials/status,verbs=get;patch;update // +kubebuilder:rbac:groups=placement.openstack.org,resources=placementapis,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=glance.openstack.org,resources=glances,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=heat.openstack.org,resources=heats,verbs=get;list;watch;create;update;patch;delete @@ -600,6 +602,13 @@ func (r *OpenStackControlPlaneReconciler) reconcileNormal(ctx context.Context, i instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneCertCleanupReadyCondition) + ctrlResult, err = openstack.ReconcileApplicationCredentials(ctx, instance, version, helper) + if err != nil { + return ctrl.Result{}, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + return ctrl.Result{}, nil } @@ -708,6 +717,7 @@ func (r *OpenStackControlPlaneReconciler) SetupWithManager( Owns(&mariadbv1.Galera{}). Owns(&memcachedv1.Memcached{}). Owns(&keystonev1.KeystoneAPI{}). + Owns(&keystonev1.KeystoneApplicationCredential{}). Owns(&placementv1.PlacementAPI{}). Owns(&glancev1.Glance{}). Owns(&cinderv1.Cinder{}). diff --git a/go.mod b/go.mod index 521b44a62..6b56a7d52 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/uuid v1.6.0 github.com/iancoleman/strcase v0.3.0 github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.7 - github.com/onsi/ginkgo/v2 v2.27.1 + github.com/onsi/ginkgo/v2 v2.27.2 github.com/onsi/gomega v1.38.2 github.com/openshift/api v3.9.0+incompatible github.com/openstack-k8s-operators/barbican-operator/api v0.6.1-0.20251014175433-c4ab8419a351 @@ -18,13 +18,13 @@ require ( github.com/openstack-k8s-operators/glance-operator/api v0.6.1-0.20251022111742-64b4039d28a7 github.com/openstack-k8s-operators/heat-operator/api v0.6.1-0.20251025092254-de6e9a251638 github.com/openstack-k8s-operators/horizon-operator/api v0.6.1-0.20251025090908-00fab1da8f24 - github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251025092254-9bbe85d92ae4 + github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251030184102-82d2cbaafd35 github.com/openstack-k8s-operators/ironic-operator/api v0.6.1-0.20251023190508-87e9d60da59a github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20251021163720-bb51cea0d967 github.com/openstack-k8s-operators/lib-common/modules/ansible v0.6.1-0.20251021145236-2b84ec9fd9bb github.com/openstack-k8s-operators/lib-common/modules/certmanager v0.6.1-0.20251021145236-2b84ec9fd9bb - github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251021145236-2b84ec9fd9bb - github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20251021145236-2b84ec9fd9bb + github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251027074416-ab5c045dbe00 + github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20251027074416-ab5c045dbe00 github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20251021145236-2b84ec9fd9bb github.com/openstack-k8s-operators/manila-operator/api v0.6.1-0.20251025092538-cee75eec6178 github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20251015110425-ad0381ce8cd4 @@ -97,7 +97,6 @@ require ( github.com/robfig/cron/v3 v3.0.1 // indirect github.com/spf13/pflag v1.0.7 // indirect github.com/x448/float16 v0.8.4 // indirect - go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect @@ -155,3 +154,20 @@ replace k8s.io/code-generator => k8s.io/code-generator v0.31.13 //allow-merging replace k8s.io/component-base => k8s.io/component-base v0.31.13 //allow-merging replace github.com/cert-manager/cmctl/v2 => github.com/cert-manager/cmctl/v2 v2.1.2-0.20241127223932-88edb96860cf //allow-merging + +// appcred related changes +replace github.com/openstack-k8s-operators/keystone-operator/api => github.com/Deydra71/keystone-operator/api v0.0.0-20251111075800-83054d6ff4b8 + +replace github.com/openstack-k8s-operators/barbican-operator/api => github.com/Deydra71/barbican-operator/api v0.0.0-20251103101323-46355b1793bf + +replace github.com/openstack-k8s-operators/cinder-operator/api => github.com/Deydra71/cinder-operator/api v0.0.0-20251103142104-0e9fbab80ef4 + +replace github.com/openstack-k8s-operators/glance-operator/api => github.com/Deydra71/glance-operator/api v0.0.0-20251103102702-77f7cfe01e3c + +replace github.com/openstack-k8s-operators/swift-operator/api => github.com/Deydra71/swift-operator/api v0.0.0-20251103103412-f201b1caed51 + +replace github.com/openstack-k8s-operators/manila-operator/api => github.com/Deydra71/manila-operator/api v0.0.0-20251103105945-a1a7e6a68acb + +replace github.com/openstack-k8s-operators/neutron-operator/api => github.com/Deydra71/neutron-operator/api v0.0.0-20251110111522-92da1dc44ef2 + +replace github.com/openstack-k8s-operators/placement-operator/api => github.com/Deydra71/placement-operator/api v0.0.0-20251110112720-6c8e2ac62669 \ No newline at end of file diff --git a/go.sum b/go.sum index 824c10153..1347c0397 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,17 @@ +github.com/Deydra71/barbican-operator/api v0.0.0-20251103101323-46355b1793bf h1:buyWKcSAgJZCjRg5hx7ebQITFmUV4ed7aE7nMdhE/qs= +github.com/Deydra71/barbican-operator/api v0.0.0-20251103101323-46355b1793bf/go.mod h1:A0S5Z0+duN9bKqW2eLpwtP+JjJMbAde1MkjKP0q5eDQ= +github.com/Deydra71/cinder-operator/api v0.0.0-20251103142104-0e9fbab80ef4 h1:vOnKHiDM3zgIEo1F1vr3G/S0UWHH+A8Py5TjbbLwRh4= +github.com/Deydra71/cinder-operator/api v0.0.0-20251103142104-0e9fbab80ef4/go.mod h1:dMvuD60r9mpwwBd+4yK3W0jR9S2jdYs6rQ84i1XUvKE= +github.com/Deydra71/glance-operator/api v0.0.0-20251103102702-77f7cfe01e3c h1:1d9Z08PXUK1hmozlp0Xi1JUSvh7LCiu1uP8+YjLTRiE= +github.com/Deydra71/glance-operator/api v0.0.0-20251103102702-77f7cfe01e3c/go.mod h1:Ij/yka+SFp7krWedAgcpkymj0e0PiLWJPB0CNYMOe08= +github.com/Deydra71/keystone-operator/api v0.0.0-20251111075800-83054d6ff4b8 h1:ph9qoP7sPAZqydaWMWC1WXhuXk0ENY55toyq+sjUCa8= +github.com/Deydra71/keystone-operator/api v0.0.0-20251111075800-83054d6ff4b8/go.mod h1:FMFoO4MjEQ85JpdLtDHxYSZxvJ9KzHua+HdKhpl0KRI= +github.com/Deydra71/manila-operator/api v0.0.0-20251103105945-a1a7e6a68acb h1:LvL4JwnIKe3ooBvXQszQyigBr21wnvGhecbx4g0zetE= +github.com/Deydra71/manila-operator/api v0.0.0-20251103105945-a1a7e6a68acb/go.mod h1:T3l1aWpo01IZX3JrgmDPr9vzrXMMBPgloJJbHt5m+4M= +github.com/Deydra71/neutron-operator/api v0.0.0-20251110111522-92da1dc44ef2 h1:oPO/Q+Q21e7ypELSYXD3OsIK4Izlv7nD+5vXwqErAv0= +github.com/Deydra71/placement-operator/api v0.0.0-20251110112720-6c8e2ac62669 h1:Rv9LXqsjinxI8+X9H6gu2BpMtqLfyZnrGkkNa1PbsGI= +github.com/Deydra71/swift-operator/api v0.0.0-20251103103412-f201b1caed51 h1:qfyxJiDSzIwrR5qL6eNGglkxF/UkmhqLCmCDjtPWuRw= +github.com/Deydra71/swift-operator/api v0.0.0-20251103103412-f201b1caed51/go.mod h1:4eX/dWpBMzIxSjoShJJeRLa988yKfPulIj4Dqxmo2yI= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -112,48 +126,36 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.27.1 h1:0LJC8MpUSQnfnp4n/3W3GdlmJP3ENGF0ZPzjQGLPP7s= -github.com/onsi/ginkgo/v2 v2.27.1/go.mod h1:wmy3vCqiBjirARfVhAqFpYt8uvX0yaFe+GudAqqcCqA= +github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= +github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/openshift/api v0.0.0-20250711200046-c86d80652a9e h1:E1OdwSpqWuDPCedyUt0GEdoAE+r5TXy7YS21yNEo+2U= github.com/openshift/api v0.0.0-20250711200046-c86d80652a9e/go.mod h1:Shkl4HanLwDiiBzakv+con/aMGnVE2MAGvoKp5oyYUo= -github.com/openstack-k8s-operators/barbican-operator/api v0.6.1-0.20251014175433-c4ab8419a351 h1:z+3DmAT3CkEFpI82sjMCTgfLR/Gr+Z7+jfzgZmUHVa8= -github.com/openstack-k8s-operators/barbican-operator/api v0.6.1-0.20251014175433-c4ab8419a351/go.mod h1:DtYNaat+pImzGhh+RgfLeSmUEqw6J/TqytTYbvxVg7E= -github.com/openstack-k8s-operators/cinder-operator/api v0.6.1-0.20251014173752-ea967e56a392 h1:lhMAeJgrD7fBL26pyzp/SVDiVZ7wr3P+ys+h6dsFM1Q= -github.com/openstack-k8s-operators/cinder-operator/api v0.6.1-0.20251014173752-ea967e56a392/go.mod h1:HIDWCoybpcyE2/wacsucEm+1dfo5d+Wr6TAQ3+vOaQc= github.com/openstack-k8s-operators/designate-operator/api v0.6.1-0.20251022085840-31cb063eeb8a h1:To9zRB8ilQEwkKZ8MXLe5+zaVXail+bjknMVLo3F09Y= github.com/openstack-k8s-operators/designate-operator/api v0.6.1-0.20251022085840-31cb063eeb8a/go.mod h1:8R9RYAjEwq+WrgKS558pvMa1Zt5WkAOQEJChloFOKzY= -github.com/openstack-k8s-operators/glance-operator/api v0.6.1-0.20251022111742-64b4039d28a7 h1:rnR6Qq+R6V/7ZF+50fsSYcSD8SMRgQdiqdT+w2mfThM= -github.com/openstack-k8s-operators/glance-operator/api v0.6.1-0.20251022111742-64b4039d28a7/go.mod h1:fK1M/vQi/TxrZmQvRxgIj998sPHo/v0zC0YUgJ25fU0= github.com/openstack-k8s-operators/heat-operator/api v0.6.1-0.20251025092254-de6e9a251638 h1:5Cj3+iee4jhV/WvrPysevisQlTIgmOdREn1mt7JHrw4= github.com/openstack-k8s-operators/heat-operator/api v0.6.1-0.20251025092254-de6e9a251638/go.mod h1:/o8HTAMKnnrETQvJCBXP90yb7kkm0tdfYqp6HUI8Ji0= github.com/openstack-k8s-operators/horizon-operator/api v0.6.1-0.20251025090908-00fab1da8f24 h1:jexX3KB+ZiO8h2oF3zzTWA3epgRI6HWoizRA0G/V10g= github.com/openstack-k8s-operators/horizon-operator/api v0.6.1-0.20251025090908-00fab1da8f24/go.mod h1:QSWFlRcNJF9dbQOSREC4XceAveBvKM/hwrPXLtHJheM= -github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251025092254-9bbe85d92ae4 h1:jIjn2kuj7P2NX/Qr1JzJ6qGqzeEUIPZcKg/AJTt8wUg= -github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251025092254-9bbe85d92ae4/go.mod h1:anuOdjhIQFtRmAiWeBVxwfOBbEAMmZPYuM9GamFq8AQ= +github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251030184102-82d2cbaafd35 h1:QFFGu93A+XCvDUxZIgfBE4gB5hEdVQAIw+E8dF1kP/E= +github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20251030184102-82d2cbaafd35/go.mod h1:qq8BCRxTEmLRriUsQ4HeDUzqltWg32MQPDTMhgbBGK4= github.com/openstack-k8s-operators/ironic-operator/api v0.6.1-0.20251023190508-87e9d60da59a h1:ROX3Vxh019mrBfKYAyVK2VcM8CZ0fpXT3pXNvhc0iUs= github.com/openstack-k8s-operators/ironic-operator/api v0.6.1-0.20251023190508-87e9d60da59a/go.mod h1:EqncaSISzZANZh/oXfwpwtlAgWZh5lmPnNVRfBusfxo= -github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20251021163720-bb51cea0d967 h1:3M5wpX25sGAxdj3zkN0Cr9+PL7b8+QaCb0ivbGseCI0= -github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20251021163720-bb51cea0d967/go.mod h1:0aizgUSdLK6TgZ1ATE6s/Cca/V+CLyMS2Mznyoq1Gjo= github.com/openstack-k8s-operators/lib-common/modules/ansible v0.6.1-0.20251021145236-2b84ec9fd9bb h1:pFa+ZX8xI1AMxjx7VWvNF96qqzbPL0eNg9wjKLldgV4= github.com/openstack-k8s-operators/lib-common/modules/ansible v0.6.1-0.20251021145236-2b84ec9fd9bb/go.mod h1:tXxVkkk8HlATwTmDA5RTP3b+c8apfuMM15mZ2wW5iNs= github.com/openstack-k8s-operators/lib-common/modules/certmanager v0.6.1-0.20251021145236-2b84ec9fd9bb h1:GIpUwDNfOLX8VJNB/aSiXp7rvYlxJazfLRnqvUcNem8= github.com/openstack-k8s-operators/lib-common/modules/certmanager v0.6.1-0.20251021145236-2b84ec9fd9bb/go.mod h1:9u3/TiMn/d8+ZWvRXZKP/vdvZer4Fk655n1PQZjZ904= -github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251021145236-2b84ec9fd9bb h1:s4qKlH16Ofqd9ptA0quFsCjyk8V44FyutB9sJ18yD6A= -github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251021145236-2b84ec9fd9bb/go.mod h1:GRTwOi5ZI6aJrTune36iWP5zNNjVLZNsV9Kb7IK3UJ0= +github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251027074416-ab5c045dbe00 h1:Xih6tYYqiDVllo4fDGHqTPL+M2biO5YLOUmbiTqrW/I= +github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20251027074416-ab5c045dbe00/go.mod h1:PMoNILOdQ1Ij7DyrKgljN6RAiq8pFM2AGsUb6mcxe98= github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20251021145236-2b84ec9fd9bb h1:wToXqX7AS1JV3Kna7RcJfkRart8rSGun2biKNfyY6Zg= github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20251021145236-2b84ec9fd9bb/go.mod h1:yf13jWb60XV26eA7A8o86ZCXNWBLNK9dPkTSWFaTPCw= -github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20251021145236-2b84ec9fd9bb h1:/EVeLrhVcnb/x86fZCyEAc2uVhLI8AcWikWT/sCA5b0= -github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20251021145236-2b84ec9fd9bb/go.mod h1:uiWDgmoC+p6mn+ZaFvkgRPQlb8ZHz5ZdXT+Zv4j/Wac= +github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20251027074416-ab5c045dbe00 h1:XQ4Zl7P+3Yfe0YotB+U9xaipq42U1FByRmrEWvChldg= +github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20251027074416-ab5c045dbe00/go.mod h1:OX2kn3of+eopoVjApgydosWJNKTROjtx/GBZUfaT4mY= github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20251021145236-2b84ec9fd9bb h1:Kc1zH+91k3wSZ8h1s/dGOxrA2KnThnEKGif/BfSQcjk= github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20251021145236-2b84ec9fd9bb/go.mod h1:9xfytPqO2LihbG/DP9FTZMNExNgzeZGdr8i4SM+aMdg= -github.com/openstack-k8s-operators/manila-operator/api v0.6.1-0.20251025092538-cee75eec6178 h1:j4tSNL0dieDOceWBL/0epgfbL7VsWAZg70PUBEsxPdI= -github.com/openstack-k8s-operators/manila-operator/api v0.6.1-0.20251025092538-cee75eec6178/go.mod h1:BGE8wpbMHx6v4Ngt/OfZaQm+sy0f8y6SJ0apZhKCjAg= github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20251015110425-ad0381ce8cd4 h1:4qDSDLX7HpCIdnlUExyPc3DkyCq+73PLPb99FVj1CZk= github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20251015110425-ad0381ce8cd4/go.mod h1:lOZNSKG7MMkhMjL7OQXKscy+dH2mxs3HPD+oj4wVytA= -github.com/openstack-k8s-operators/neutron-operator/api v0.6.1-0.20251016170447-17d48235c379 h1:jkiJRBsklxDAUxjAlRXJASd1GOek4c8w/Ka2GYifcJk= -github.com/openstack-k8s-operators/neutron-operator/api v0.6.1-0.20251016170447-17d48235c379/go.mod h1:MYz2CgQILsE/tGjGMIPfkGpKkHOqIeCY57rhwmfxHzU= github.com/openstack-k8s-operators/nova-operator/api v0.6.1-0.20251022144230-a61d2a7dde8c h1:vPFQuE7vJaSwW+7HjzeiF9quSuS+ODJwXqemb7GH+o4= github.com/openstack-k8s-operators/nova-operator/api v0.6.1-0.20251022144230-a61d2a7dde8c/go.mod h1:X2+h5BeIC6YPOOlIXzWlIllyUACChuU6rLL01R3CVuc= github.com/openstack-k8s-operators/octavia-operator/api v0.6.1-0.20251022084705-f7d8ed01fa05 h1:iJS6ISpiOCQZ9tmdqjhQlawVNAguPMVGBOHb7H3bAQE= @@ -162,12 +164,8 @@ github.com/openstack-k8s-operators/openstack-baremetal-operator/api v0.6.1-0.202 github.com/openstack-k8s-operators/openstack-baremetal-operator/api v0.6.1-0.20251016050458-7c5c8fc69a7a/go.mod h1:He7rGGmvfl1lzn+OJ0jV1tU6b8+otlCCrRx0T3WxlAQ= github.com/openstack-k8s-operators/ovn-operator/api v0.6.1-0.20251020102141-f19d0ee25e0f h1:4RH4gFZKRRTjJCLmEbUrQLRWC+wfThHoRapS/nPBbl4= github.com/openstack-k8s-operators/ovn-operator/api v0.6.1-0.20251020102141-f19d0ee25e0f/go.mod h1:RTW7SRp+Fn8JmIjdOgLl3GB3tTAhnI0q2XgauR1eEUM= -github.com/openstack-k8s-operators/placement-operator/api v0.6.1-0.20251016091846-46ae39c6d532 h1:Kz2YSBptRCoHu5ie44IJ4rhJ/Unm9Yxdj6wIuv+lc8o= -github.com/openstack-k8s-operators/placement-operator/api v0.6.1-0.20251016091846-46ae39c6d532/go.mod h1:tT7pLlledNe6qxzJPmgG4Vt3y8C8hjlUli0rPBeAiz0= github.com/openstack-k8s-operators/rabbitmq-cluster-operator/v2 v2.6.1-0.20250929174222-a0d328fa4dec h1:saovr368HPAKHN0aRPh8h8n9s9dn3d8Frmfua0UYRlc= github.com/openstack-k8s-operators/rabbitmq-cluster-operator/v2 v2.6.1-0.20250929174222-a0d328fa4dec/go.mod h1:Nh2NEePLjovUQof2krTAg4JaAoLacqtPTZQXK6izNfg= -github.com/openstack-k8s-operators/swift-operator/api v0.6.1-0.20251022081645-83643617513b h1:Xj0Tb70tvsIMdBb0ap/3edx3zY5zyrLlDxac/Uwd4jU= -github.com/openstack-k8s-operators/swift-operator/api v0.6.1-0.20251022081645-83643617513b/go.mod h1:Wxqy0y7uw0zBZ+bvU+aVUUedPnI+RnUm6ci1hVdad4w= github.com/openstack-k8s-operators/telemetry-operator/api v0.6.1-0.20251023173049-bffdcca1b8c9 h1:dOP0npvCEEDoID7m3xhBeSTH+FmwBqyPzEVCsbOOv64= github.com/openstack-k8s-operators/telemetry-operator/api v0.6.1-0.20251023173049-bffdcca1b8c9/go.mod h1:zyFQU87rwagrykCBLM4KdmGAYOFxzKcOOfWDoohxrD0= github.com/openstack-k8s-operators/test-operator/api v0.6.1-0.20251015105850-737534bb4fcf h1:+6NbDmvZkgQOO/0ZvSMo8EaOqFJPyfkz3uyU7imoj+k= @@ -179,8 +177,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= @@ -215,8 +211,6 @@ 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= -go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= -go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= 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= diff --git a/hack/export_operator_related_images.sh b/hack/export_operator_related_images.sh index 53982e00d..4eab07685 100644 --- a/hack/export_operator_related_images.sh +++ b/hack/export_operator_related_images.sh @@ -1,24 +1,24 @@ # NOTE: this file is automatically generated by hack/sync-bindata.sh! -export RELATED_IMAGE_BARBICAN_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/barbican-operator@sha256:2b673886e5632955ed22e40622f3a1d6be00e7ebe7535f3a0ed25cb67ee1a9d1 -export RELATED_IMAGE_CINDER_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/cinder-operator@sha256:c5f2ac270a982a599e665960ae2622703421f3b5bd2952dc0a82735c474eb9a8 +export RELATED_IMAGE_BARBICAN_OPERATOR_MANAGER_IMAGE_URL=quay.io/rh-ee-vfisarov/barbican-operator@sha256:bc8de744f58f16642c0394353bd6619fae98e07c6b28932b0d1660c6e468bec4 +export RELATED_IMAGE_CINDER_OPERATOR_MANAGER_IMAGE_URL=quay.io/rh-ee-vfisarov/cinder-operator@sha256:7ece03d39b09ebc3ad904fce2e43730768023ba4e1eb08a2075c326e5cb1b705 export RELATED_IMAGE_DESIGNATE_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/designate-operator@sha256:c20f1cf4f8a94c1658a253b546c96d4052cbee9cce3a3c1c884904ef1a1c4a25 -export RELATED_IMAGE_GLANCE_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/glance-operator@sha256:46875c236a83d6e07d3f817857e1ce4d21508ddaf326a2e320e2ee56d15b8123 +export RELATED_IMAGE_GLANCE_OPERATOR_MANAGER_IMAGE_URL=quay.io/rh-ee-vfisarov/glance-operator@sha256:ce414f728de2a3c807306647b8133f838439578888a0cbc4632f99f084df398c export RELATED_IMAGE_HEAT_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/heat-operator@sha256:25a0194f58a30b212ee9f4a8fb949cc834a9212374920d1bb6adedc14c72abf6 export RELATED_IMAGE_HORIZON_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/horizon-operator@sha256:f023985eb4e1830638f341ff409e4370d016b3b7508ff30e61744a8cfa67a155 -export RELATED_IMAGE_INFRA_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/infra-operator@sha256:810bea5c7caaace8aa8388545d110e7c6e412c6f7ba0e74d027970ec394690d0 +export RELATED_IMAGE_INFRA_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/infra-operator@sha256:81ad8f03c545397f27e1d100014ce452593d9010302e525772ceb40d3d2e82dc export RELATED_IMAGE_IRONIC_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/ironic-operator@sha256:fc00fca9f5462acded19bf9a866d7a879b2cc5eb126a4eb20dde9d43cc2f6392 -export RELATED_IMAGE_KEYSTONE_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/keystone-operator@sha256:cce57d1528476d1b22ee5d7cac3b178762f4e087b80feda35fbbcdd74ee2e378 -export RELATED_IMAGE_MANILA_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/manila-operator@sha256:c8a28d99a2de585df772e1d495c8dbc7e9b25a71f18c677b3f15aea6b275ca92 +export RELATED_IMAGE_KEYSTONE_OPERATOR_MANAGER_IMAGE_URL=quay.io/rh-ee-vfisarov/keystone-operator@sha256:a1056dcb69538dd2a508c665848ac0b7f909293856929c01cfea379e3cd405b7 +export RELATED_IMAGE_MANILA_OPERATOR_MANAGER_IMAGE_URL=quay.io/rh-ee-vfisarov/manila-operator@sha256:531052a1b971c25a6d4478884cff46200a3800ed96ca2c63a305ddbccd825e4a export RELATED_IMAGE_MARIADB_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/mariadb-operator@sha256:3451ff344ece308690d7ee33e376cef52e177e61f7795819d222d086cccbe951 -export RELATED_IMAGE_NEUTRON_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/neutron-operator@sha256:9b541a92154ae0d5e98e8c0ca0b31556daeffb603ca08ca5fc81d825adce1f16 +export RELATED_IMAGE_NEUTRON_OPERATOR_MANAGER_IMAGE_URL=quay.io/rh-ee-vfisarov/neutron-operator@sha256:cefeb1d97b8f3b38c4314d259d02d5a937b9112e5842d9764bebbd1a750b2f27 export RELATED_IMAGE_NOVA_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/nova-operator@sha256:d1b9745674b362cb2aad70c18db4da4ac01a0a1eafdeba6f5c902596e632c131 export RELATED_IMAGE_OCTAVIA_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/octavia-operator@sha256:c1ef935acd10a0793d089f495ffeb358fadea6701625b3b14a5bc6c6101180b0 export RELATED_IMAGE_OPENSTACK_BAREMETAL_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/openstack-baremetal-operator@sha256:6f14cbcb71da0fc6f849a4ca8b14a001c6fc62a1b9e78222f0d23f92fd51f5a0 export RELATED_IMAGE_OVN_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/ovn-operator@sha256:9ed3e90ad9a4613c6c9c924487006183539b153fc00136ed37b3732f9f6ca2f2 -export RELATED_IMAGE_PLACEMENT_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/placement-operator@sha256:f4ff739c066e6ba873376bd1cdb533b68b8ffa38f0e399b0d315476c05c6b322 +export RELATED_IMAGE_PLACEMENT_OPERATOR_MANAGER_IMAGE_URL=quay.io/rh-ee-vfisarov/placement-operator@sha256:712883ea4c3913b28a585ca030aa6fa4be0ba5fc544e5253bf1f6d4cf24e3f79 export RELATED_IMAGE_RABBITMQ_CLUSTER_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/rabbitmq-cluster-operator@sha256:893e66303c1b0bc1d00a299a3f0380bad55c8dc813c8a1c6a4aab379f5aa12a2 -export RELATED_IMAGE_SWIFT_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/swift-operator@sha256:8ed782cb1a952aa31950a9153a51c25fc30b130a928b58e0870e1071d5e5efbe +export RELATED_IMAGE_SWIFT_OPERATOR_MANAGER_IMAGE_URL=quay.io/rh-ee-vfisarov/swift-operator@sha256:aaf1a55bca9ec0a09a1fd519a982dd33bbf6fc9cc45b3641849d7d058f9d98ba export RELATED_IMAGE_TELEMETRY_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/telemetry-operator@sha256:7c7268354f4ce92a0112580323172c603f39eb8339098f40cda9a8e58b4a98e4 export RELATED_IMAGE_TEST_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/test-operator@sha256:f3c25c1112d6204499dfb41cc8b3c6882c46e6ba8008b3ed0e6d83e6f51a9d4a export RELATED_IMAGE_WATCHER_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/watcher-operator@sha256:a4ca61bbbddb0a1e849a8474dfc1e1474e891b161f82df38dccc75944671ad47 diff --git a/pkg/openstack/applicationcredential.go b/pkg/openstack/applicationcredential.go new file mode 100644 index 000000000..b3472619a --- /dev/null +++ b/pkg/openstack/applicationcredential.go @@ -0,0 +1,290 @@ +package openstack + +import ( + "context" + "fmt" + + keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" + "github.com/openstack-k8s-operators/lib-common/modules/common/helper" + corev1beta1 "github.com/openstack-k8s-operators/openstack-operator/apis/core/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +// mergeAppCred returns a new ApplicationCredentialSection by overlaying +// service-specific values on top of the global defaults. +func mergeAppCred( + global corev1beta1.ApplicationCredentialSection, + svc *corev1beta1.ServiceAppCredSection, +) corev1beta1.ApplicationCredentialSection { + out := global + if svc != nil { + out.Enabled = svc.Enabled + + // only override expiry/grace if specified + if svc.ExpirationDays != nil { + out.ExpirationDays = svc.ExpirationDays + } + if svc.GracePeriodDays != nil { + out.GracePeriodDays = svc.GracePeriodDays + } + + // only override Roles if user set them + if len(svc.Roles) > 0 { + out.Roles = svc.Roles + } + // only override Unrestricted if user set it + if svc.Unrestricted != nil { + out.Unrestricted = svc.Unrestricted + } + // only override AccessRules if user set them + if len(svc.AccessRules) > 0 { + out.AccessRules = svc.AccessRules + } + } + + return out +} + +// ReconcileApplicationCredentials ensures an AC CR per enabled service, +// propagating its secret name, passwordSelector, and serviceUser fields. +func ReconcileApplicationCredentials( + ctx context.Context, + instance *corev1beta1.OpenStackControlPlane, + _ *corev1beta1.OpenStackVersion, + helper *helper.Helper, +) (ctrl.Result, error) { + log := GetLogger(ctx) + + // If global disabled, delete all ACs: + if !instance.Spec.ApplicationCredential.Enabled { + log.Info("Global AC disabled; deleting per-service AC CRs") + for _, svc := range []string{"glance", "nova", "swift", "ceilometer", "barbican", "cinder", "placement", "neutron", "ironic", "heat", "octavia", "manila", "designate", "watcher", "aodh"} { + ac := &keystonev1.KeystoneApplicationCredential{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("ac-%s", svc), + Namespace: instance.Namespace, + }, + } + if res, err := EnsureDeleted(ctx, helper, ac); err != nil { + return res, err + } + } + return ctrl.Result{}, nil + } + + // Type definition for service AC configuration + type svcAC struct { + Key string + Enabled bool + ACSection *corev1beta1.ServiceAppCredSection + } + + // Collect each service's enabled flag and AC section + svcs := []svcAC{ + {"glance", instance.Spec.Glance.Enabled, instance.Spec.Glance.ApplicationCredential}, + {"nova", instance.Spec.Nova.Enabled, instance.Spec.Nova.ApplicationCredential}, + {"swift", instance.Spec.Swift.Enabled, instance.Spec.Swift.ApplicationCredential}, + {"ceilometer", instance.Spec.Telemetry.Enabled, instance.Spec.Telemetry.ApplicationCredential}, + {"barbican", instance.Spec.Barbican.Enabled, instance.Spec.Barbican.ApplicationCredential}, + {"cinder", instance.Spec.Cinder.Enabled, instance.Spec.Cinder.ApplicationCredential}, + {"placement", instance.Spec.Placement.Enabled, instance.Spec.Placement.ApplicationCredential}, + {"neutron", instance.Spec.Neutron.Enabled, instance.Spec.Neutron.ApplicationCredential}, + {"ironic", instance.Spec.Ironic.Enabled, instance.Spec.Ironic.ApplicationCredential}, + {"heat", instance.Spec.Heat.Enabled, instance.Spec.Heat.ApplicationCredential}, + {"octavia", instance.Spec.Octavia.Enabled, instance.Spec.Octavia.ApplicationCredential}, + {"manila", instance.Spec.Manila.Enabled, instance.Spec.Manila.ApplicationCredential}, + {"designate", instance.Spec.Designate.Enabled, instance.Spec.Designate.ApplicationCredential}, + {"watcher", instance.Spec.Watcher.Enabled, instance.Spec.Watcher.ApplicationCredential}, + {"aodh", instance.Spec.Telemetry.Enabled, instance.Spec.Telemetry.AodhApplicationCredential}, + } + global := instance.Spec.ApplicationCredential + + // Helper functions to safely access Watcher's pointer fields + getWatcherSecret := func() string { + if instance.Spec.Watcher.Template != nil && instance.Spec.Watcher.Template.Secret != nil { + return *instance.Spec.Watcher.Template.Secret + } + return "" + } + getWatcherServiceUser := func() string { + if instance.Spec.Watcher.Template != nil && instance.Spec.Watcher.Template.ServiceUser != nil { + return *instance.Spec.Watcher.Template.ServiceUser + } + return "" + } + getWatcherPasswordSelector := func() string { + if instance.Spec.Watcher.Template != nil && + instance.Spec.Watcher.Template.PasswordSelectors.Service != nil { + return *instance.Spec.Watcher.Template.PasswordSelectors.Service + } + return "" + } + + // getServiceInfo retrieves service info from Template + // When service is enabled, webhook ensures Template is initialized with defaults + // This function is only called after verifying service is enabled + getServiceInfo := func(key string) struct { + SecretName string + PasswordSelector string + ServiceUser string + } { + var secretName, passwordSelector, serviceUser string + + switch key { + case "glance": + secretName = instance.Spec.Glance.Template.Secret + passwordSelector = instance.Spec.Glance.Template.PasswordSelectors.Service + serviceUser = instance.Spec.Glance.Template.ServiceUser + case "nova": + secretName = instance.Spec.Nova.Template.Secret + passwordSelector = instance.Spec.Nova.Template.PasswordSelectors.Service + serviceUser = instance.Spec.Nova.Template.ServiceUser + case "swift": + secretName = instance.Spec.Swift.Template.SwiftProxy.Secret + passwordSelector = instance.Spec.Swift.Template.SwiftProxy.PasswordSelectors.Service + serviceUser = instance.Spec.Swift.Template.SwiftProxy.ServiceUser + case "ceilometer": + secretName = instance.Spec.Telemetry.Template.Ceilometer.Secret + passwordSelector = instance.Spec.Telemetry.Template.Ceilometer.PasswordSelectors.CeilometerService + serviceUser = instance.Spec.Telemetry.Template.Ceilometer.ServiceUser + case "barbican": + secretName = instance.Spec.Barbican.Template.Secret + passwordSelector = instance.Spec.Barbican.Template.PasswordSelectors.Service + serviceUser = instance.Spec.Barbican.Template.ServiceUser + case "cinder": + secretName = instance.Spec.Cinder.Template.Secret + passwordSelector = instance.Spec.Cinder.Template.PasswordSelectors.Service + serviceUser = instance.Spec.Cinder.Template.ServiceUser + case "placement": + secretName = instance.Spec.Placement.Template.Secret + passwordSelector = instance.Spec.Placement.Template.PasswordSelectors.Service + serviceUser = instance.Spec.Placement.Template.ServiceUser + case "neutron": + secretName = instance.Spec.Neutron.Template.Secret + passwordSelector = instance.Spec.Neutron.Template.PasswordSelectors.Service + serviceUser = instance.Spec.Neutron.Template.ServiceUser + case "ironic": + secretName = instance.Spec.Ironic.Template.Secret + passwordSelector = instance.Spec.Ironic.Template.PasswordSelectors.Service + serviceUser = instance.Spec.Ironic.Template.ServiceUser + case "heat": + secretName = instance.Spec.Heat.Template.Secret + passwordSelector = instance.Spec.Heat.Template.PasswordSelectors.Service + serviceUser = instance.Spec.Heat.Template.ServiceUser + case "octavia": + secretName = instance.Spec.Octavia.Template.Secret + passwordSelector = instance.Spec.Octavia.Template.PasswordSelectors.Service + serviceUser = instance.Spec.Octavia.Template.ServiceUser + case "manila": + secretName = instance.Spec.Manila.Template.Secret + passwordSelector = instance.Spec.Manila.Template.PasswordSelectors.Service + serviceUser = instance.Spec.Manila.Template.ServiceUser + case "designate": + secretName = instance.Spec.Designate.Template.Secret + passwordSelector = instance.Spec.Designate.Template.PasswordSelectors.Service + serviceUser = instance.Spec.Designate.Template.ServiceUser + case "watcher": + secretName = getWatcherSecret() + passwordSelector = getWatcherPasswordSelector() + serviceUser = getWatcherServiceUser() + case "aodh": + secretName = instance.Spec.Telemetry.Template.Autoscaling.Aodh.Secret + passwordSelector = instance.Spec.Telemetry.Template.Autoscaling.Aodh.PasswordSelectors.AodhService + serviceUser = instance.Spec.Telemetry.Template.Autoscaling.Aodh.ServiceUser + default: + return struct { + SecretName string + PasswordSelector string + ServiceUser string + }{} + } + + // If service-specific Secret is empty, use top-level Secret + if secretName == "" { + secretName = instance.Spec.Secret + } + + return struct { + SecretName string + PasswordSelector string + ServiceUser string + }{secretName, passwordSelector, serviceUser} + } + + // Loop, CreateOrPatch or delete each AC CR: + for _, svc := range svcs { + acName := fmt.Sprintf("ac-%s", svc.Key) + acObj := &keystonev1.KeystoneApplicationCredential{ + ObjectMeta: metav1.ObjectMeta{ + Name: acName, + Namespace: instance.Namespace, + }, + } + + // Only create AC if service is enabled AND AC is enabled + // Check service enabled first to avoid accessing Template for disabled services + if !svc.Enabled { + if res, err := EnsureDeleted(ctx, helper, acObj); err != nil { + return res, err + } + continue + } + + // merge flags - only check AC enabled after verifying service is enabled + effective := mergeAppCred(global, svc.ACSection) + if !effective.Enabled { + if res, err := EnsureDeleted(ctx, helper, acObj); err != nil { + return res, err + } + continue + } + + // Get service info - when service is enabled, webhook ensures Template is initialized + svcInfo := getServiceInfo(svc.Key) + if svcInfo.SecretName == "" || svcInfo.PasswordSelector == "" { + // This should not happen if webhook ran correctly, but handle gracefully + log.Info("Skipping AC creation: Template fields empty", "service", svc.Key) + if res, err := EnsureDeleted(ctx, helper, acObj); err != nil { + return res, err + } + continue + } + + // create/patch + op, err := controllerutil.CreateOrPatch(ctx, helper.GetClient(), acObj, func() error { + acObj.Spec.UserName = svcInfo.ServiceUser + acObj.Spec.ExpirationDays = *effective.ExpirationDays + acObj.Spec.GracePeriodDays = *effective.GracePeriodDays + acObj.Spec.Secret = svcInfo.SecretName + acObj.Spec.PasswordSelector = svcInfo.PasswordSelector + acObj.Spec.Roles = effective.Roles + acObj.Spec.Unrestricted = *effective.Unrestricted + + if len(effective.AccessRules) > 0 { + kr := make([]keystonev1.ACRule, 0, len(effective.AccessRules)) + for _, r := range effective.AccessRules { + kr = append(kr, keystonev1.ACRule{ + Service: r.Service, + Path: r.Path, + Method: r.Method, + }) + } + acObj.Spec.AccessRules = kr + } + + return controllerutil.SetControllerReference( + helper.GetBeforeObject(), acObj, helper.GetScheme(), + ) + }) + if err != nil { + return ctrl.Result{}, err + } + if op != controllerutil.OperationResultNone { + log.Info("Reconciled ApplicationCredential", "service", svc.Key, "operation", op) + } + } + + return ctrl.Result{}, nil +} diff --git a/tests/functional/ctlplane/openstackoperator_controller_test.go b/tests/functional/ctlplane/openstackoperator_controller_test.go index d7f18067c..9c8959d2d 100644 --- a/tests/functional/ctlplane/openstackoperator_controller_test.go +++ b/tests/functional/ctlplane/openstackoperator_controller_test.go @@ -4063,7 +4063,159 @@ var _ = Describe("OpenStackOperator controller nova cell deletion", func() { g.Expect(k8s_errors.IsNotFound(err)).To(BeTrue()) }, timeout, interval).Should(Succeed()) }) + }) + }) +}) + +var _ = Describe("Application Credentials configuration in control plane", func() { + When("global application credentials are enabled", func() { + BeforeEach(func() { + spec := GetDefaultOpenStackControlPlaneSpec() + spec["applicationCredential"] = map[string]interface{}{ + "enabled": true, + "expirationDays": 365, + "gracePeriodDays": 182, + "roles": []string{"service"}, + "unrestricted": false, + } + spec["cinder"] = map[string]interface{}{ + "enabled": true, + "applicationCredential": map[string]interface{}{ + "enabled": true, + "expirationDays": 100, + "gracePeriodDays": 50, + "roles": []string{"custom", "role"}, + "unrestricted": true, + }, + } + + DeferCleanup(th.DeleteInstance, + CreateOpenStackControlPlane(names.OpenStackControlplaneName, spec), + ) + }) + + It("should fill defaults correctly", func() { + Eventually(func(g Gomega) { + cp := GetOpenStackControlPlane(names.OpenStackControlplaneName) + g.Expect(cp.Spec.ApplicationCredential.Enabled).To(BeTrue()) + g.Expect(*cp.Spec.ApplicationCredential.ExpirationDays).To(Equal(365)) + g.Expect(*cp.Spec.ApplicationCredential.GracePeriodDays).To(Equal(182)) + g.Expect(cp.Spec.ApplicationCredential.Roles).To(ConsistOf("service")) + g.Expect(*cp.Spec.ApplicationCredential.Unrestricted).To(BeFalse()) + + ac := cp.Spec.Cinder.ApplicationCredential + g.Expect(ac).NotTo(BeNil()) + g.Expect(*ac.ExpirationDays).To(Equal(100)) + g.Expect(*ac.GracePeriodDays).To(Equal(50)) + g.Expect(ac.Roles).To(ConsistOf("custom", "role")) + g.Expect(*ac.Unrestricted).To(BeTrue()) + }, timeout, interval).Should(Succeed()) + }) + + It("should configure ApplicationCredential with service-specific overrides and global defaults", func() { + cp := GetOpenStackControlPlane(names.OpenStackControlplaneName) + + // Verify global AC configuration + global := cp.Spec.ApplicationCredential + Expect(global.Enabled).To(BeTrue()) + Expect(*global.ExpirationDays).To(Equal(365)) + Expect(*global.GracePeriodDays).To(Equal(182)) + Expect(global.Roles).To(ConsistOf("service")) + Expect(*global.Unrestricted).To(BeFalse()) + + // Verify Cinder has service-specific overrides + Expect(cp.Spec.Cinder.Enabled).To(BeTrue()) + Expect(cp.Spec.Cinder.ApplicationCredential).NotTo(BeNil()) + Expect(cp.Spec.Cinder.ApplicationCredential.Enabled).To(BeTrue()) + cinderAC := cp.Spec.Cinder.ApplicationCredential + Expect(*cinderAC.ExpirationDays).To(Equal(100)) + Expect(*cinderAC.GracePeriodDays).To(Equal(50)) + Expect(cinderAC.Roles).To(ConsistOf("custom", "role")) + Expect(*cinderAC.Unrestricted).To(BeTrue()) + + // Verify Glance and Manila inherit global defaults (no service-specific AC overrides) + // The service specific values are nil/empty, they inherit the global defaults with mergeAppCred function + Expect(cp.Spec.Glance.Enabled).To(BeTrue()) + Expect(cp.Spec.Manila.Enabled).To(BeTrue()) + Expect(cp.Spec.Manila.Template).NotTo(BeNil()) + + if cp.Spec.Glance.ApplicationCredential != nil { + glanceAC := cp.Spec.Glance.ApplicationCredential + Expect(glanceAC.ExpirationDays).To(BeNil()) + Expect(glanceAC.GracePeriodDays).To(BeNil()) + Expect(glanceAC.Roles).To(BeEmpty()) + Expect(glanceAC.Unrestricted).To(BeNil()) + } + + if cp.Spec.Manila.ApplicationCredential != nil { + manilaAC := cp.Spec.Manila.ApplicationCredential + Expect(manilaAC.ExpirationDays).To(BeNil()) + Expect(manilaAC.GracePeriodDays).To(BeNil()) + Expect(manilaAC.Roles).To(BeEmpty()) + Expect(manilaAC.Unrestricted).To(BeNil()) + } + }) + }) + + When("global application credentials are disabled", func() { + BeforeEach(func() { + spec := GetDefaultOpenStackControlPlaneSpec() + spec["applicationCredential"] = map[string]interface{}{"enabled": false} + spec["cinder"] = map[string]interface{}{ + "enabled": true, + "applicationCredential": map[string]interface{}{ + "enabled": true, + }, + } + spec["glance"] = map[string]interface{}{ + "enabled": true, + } + + DeferCleanup(th.DeleteInstance, + CreateOpenStackControlPlane(names.OpenStackControlplaneName, spec), + ) + }) + + It("should have global AC disabled in spec", func() { + cp := GetOpenStackControlPlane(names.OpenStackControlplaneName) + Expect(cp.Spec.ApplicationCredential.Enabled).To(BeFalse()) + }) + }) + + When("service-specific application credentials are disabled", func() { + BeforeEach(func() { + spec := GetDefaultOpenStackControlPlaneSpec() + spec["applicationCredential"] = map[string]interface{}{"enabled": true} + spec["glance"] = map[string]interface{}{ + "enabled": true, + "applicationCredential": map[string]interface{}{ + "enabled": false, + }, + } + spec["cinder"] = map[string]interface{}{ + "enabled": true, + "applicationCredential": map[string]interface{}{ + "enabled": true, + }, + } + + DeferCleanup(th.DeleteInstance, + CreateOpenStackControlPlane(names.OpenStackControlplaneName, spec), + ) + }) + + It("should have service-specific AC disabled in spec", func() { + cp := GetOpenStackControlPlane(names.OpenStackControlplaneName) + + // Glance is disabled + Expect(cp.Spec.Glance.Enabled).To(BeTrue()) + Expect(cp.Spec.Glance.ApplicationCredential).NotTo(BeNil()) + Expect(cp.Spec.Glance.ApplicationCredential.Enabled).To(BeFalse()) + // Cidner is enabled + Expect(cp.Spec.Cinder.Enabled).To(BeTrue()) + Expect(cp.Spec.Cinder.ApplicationCredential).NotTo(BeNil()) + Expect(cp.Spec.Cinder.ApplicationCredential.Enabled).To(BeTrue()) }) }) }) diff --git a/tests/kuttl/common/osp_check_appcred_id.sh b/tests/kuttl/common/osp_check_appcred_id.sh new file mode 100755 index 000000000..455dd9d5e --- /dev/null +++ b/tests/kuttl/common/osp_check_appcred_id.sh @@ -0,0 +1,249 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Script to verify Application Credential IDs and AC secrets are correctly configured in OpenStack service pods +# Usage: osp_check_appcred_id.sh + +if [[ $# -lt 2 ]]; then + echo "Usage: $0 " >&2 + echo " SERVICE: barbican, glance, swift, cinder, manila (or 'all' for supported services)" >&2 + exit 1 +fi + +NAMESPACE="$1" +REQUESTED_SERVICE="$2" +DEBUG=${DEBUG:-0} + +declare -a FAILED_CHECKS=() + +# Service definitions: service_name -> "config_path|resource_type/resource_name:container,resource_type/resource_name:container" +# resource_type can be: deploy (deployment) or sts (statefulset) +declare -A SERVICES=( + [barbican]="/etc/barbican/barbican.conf.d/00-default.conf|deploy/barbican-api:barbican-api" + [cinder]="/etc/cinder/cinder.conf.d/00-default.conf|sts/cinder-api:cinder-api,sts/cinder-scheduler:cinder-scheduler" + [glance]="/etc/glance/glance-api.conf.d/00-default.conf|sts/glance-default-external-api:glance-api,sts/glance-default-internal-api:glance-api" + [swift]="/etc/swift/proxy-server.conf.d/00-proxy-server.conf|deploy/swift-proxy:proxy-server" + [manila]="/etc/manila/manila.conf.d/00-config.conf|sts/manila-api:manila-api,sts/manila-scheduler:manila-scheduler" + # TODO: Add remaining services when they support application credentials in their operators: + # [nova]="/etc/nova/nova.conf|sts/nova-api:nova-api,sts/nova-cell0-conductor:nova-conductor,sts/nova-cell1-conductor:nova-conductor,sts/nova-metadata:nova-metadata,sts/nova-scheduler:nova-scheduler" + [neutron]="/etc/neutron/neutron.conf.d/01-default.conf|deploy/neutron:neutron-server" + [placement]="/etc/placement/placement.conf|deploy/placement:placement-api" + # [ceilometer]="/etc/ceilometer/ceilometer.conf|sts/ceilometer:ceilometer-central" + # [aodh]="/etc/aodh/aodh.conf|sts/aodh-api:aodh-api" + # [heat]="/etc/heat/heat.conf|sts/heat-api:heat-api" + # [ironic]="/etc/ironic/ironic.conf|sts/ironic-api:ironic-api" + [octavia]="/etc/octavia/octavia.conf|sts/octavia-api:octavia-api" + # [designate]="/etc/designate/designate.conf|sts/designate-api:designate-api" + # [watcher]="/etc/watcher/watcher.conf|sts/watcher-api:watcher-api" +) + +RESOURCE_TYPE="keystoneapplicationcredential" + +debug() { + [[ $DEBUG -ge 1 ]] && echo "[DEBUG] $*" >&2 +} + +error() { + echo "[ERROR] $*" >&2 +} + +# Add a failed check to the global list +add_failed_check() { + local service="$1" resource_spec="$2" container="$3" reason="$4" + FAILED_CHECKS+=("$service: $resource_spec/$container - $reason") +} + +# Convert resource type shorthand to full name +get_resource_type() { + case "$1" in + deploy) echo "deployment" ;; + sts) echo "statefulset" ;; + *) echo "$1" ;; + esac +} + +# Extract application credential field from config file in pod +get_app_cred_field_from_pod() { + local resource_spec="$1" container="$2" config_path="$3" field_name="$4" + local output + + debug "Executing: oc exec -n $NAMESPACE $resource_spec -c $container -- sh -c \"grep '^[[:space:]]*${field_name}[[:space:]]*=' '$config_path' | sed 's/^[^=]*=[[:space:]]*//' | sed 's/[[:space:]]*$//' | head -1\"" + + if output=$(oc exec -n "$NAMESPACE" "$resource_spec" -c "$container" -- \ + sh -c "grep '^[[:space:]]*${field_name}[[:space:]]*=' '$config_path' | sed 's/^[^=]*=[[:space:]]*//' | sed 's/[[:space:]]*$//' | head -1" 2>/dev/null); then + debug "Successfully extracted $field_name from $resource_spec/$container: $output" + echo "$output" + return 0 + fi + + error "Failed to extract $field_name from $resource_spec/$container" + return 1 +} + +# Check a single service +check_service() { + local service="$1" + local service_def="${SERVICES[$service]}" + local config_path="${service_def%%|*}" + local targets="${service_def##*|}" + + echo "Checking service: $service" + + # Get expected Application Credential data from Kubernetes resources + local cr_name="ac-$service" + local expected_id expected_secret + + # Get AC ID from the KeystoneApplicationCredential status + if ! expected_id=$(oc get "$RESOURCE_TYPE" "$cr_name" -n "$NAMESPACE" -o jsonpath='{.status.acID}' 2>/dev/null); then + error "Failed to get Application Credential ID from $RESOURCE_TYPE/$cr_name" + add_failed_check "$service" "$cr_name" "N/A" "Failed to get Application Credential ID from Kubernetes resource" + return 1 + fi + + if [[ -z "$expected_id" ]]; then + error "$RESOURCE_TYPE/$cr_name has empty .status.acID" + add_failed_check "$service" "$cr_name" "N/A" "Empty .status.acID in Kubernetes resource" + return 1 + fi + + # Get AC Secret from the associated secret (base64 decoded) + local secret_name + if ! secret_name=$(oc get "$RESOURCE_TYPE" "$cr_name" -n "$NAMESPACE" -o jsonpath='{.status.secretName}' 2>/dev/null); then + error "Failed to get secret name from $RESOURCE_TYPE/$cr_name" + add_failed_check "$service" "$cr_name" "N/A" "Failed to get secret name from Kubernetes resource" + return 1 + fi + + if [[ -z "$secret_name" ]]; then + error "$RESOURCE_TYPE/$cr_name has empty .status.secretName" + add_failed_check "$service" "$cr_name" "N/A" "Empty .status.secretName in Kubernetes resource" + return 1 + fi + + # Get and decode the AC_SECRET from the Kubernetes secret + if ! expected_secret=$(oc get secret "$secret_name" -n "$NAMESPACE" -o jsonpath='{.data.AC_SECRET}' 2>/dev/null | base64 -d); then + error "Failed to get AC_SECRET from secret/$secret_name" + add_failed_check "$service" "$secret_name" "N/A" "Failed to get AC_SECRET from Kubernetes secret" + return 1 + fi + + if [[ -z "$expected_secret" ]]; then + error "secret/$secret_name has empty AC_SECRET" + add_failed_check "$service" "$secret_name" "N/A" "Empty AC_SECRET in Kubernetes secret" + return 1 + fi + + echo " Expected ID: $expected_id" + echo " Expected Secret: ${expected_secret:0:20}..." + + local failed=0 + + # Check each resource/container pair + IFS=',' read -ra TARGET_LIST <<< "$targets" + for target in "${TARGET_LIST[@]}"; do + local resource_spec="${target%%:*}" # e.g., "deploy/swift-proxy" + local container="${target##*:}" # e.g., "proxy-server" + + # Parse resource type and name + local resource_type_short="${resource_spec%%/*}" # e.g., "deploy" + local resource_name="${resource_spec##*/}" # e.g., "swift-proxy" + local resource_type_full=$(get_resource_type "$resource_type_short") + + # Skip if resource doesn't exist + if ! oc get "$resource_type_full" "$resource_name" -n "$NAMESPACE" >/dev/null 2>&1; then + echo " Skipping $resource_type_full/$resource_name (not found)" + continue + fi + + # Check Application Credential ID + local actual_id + if ! actual_id=$(get_app_cred_field_from_pod "$resource_type_full/$resource_name" "$container" "$config_path" "application_credential_id"); then + add_failed_check "$service" "$resource_spec" "$container" "Failed to extract application_credential_id from pod" + failed=1 + elif [[ -z "$actual_id" ]]; then + error " $resource_spec/$container: application_credential_id not found in $config_path" + add_failed_check "$service" "$resource_spec" "$container" "application_credential_id not found in config file" + failed=1 + elif [[ "$actual_id" != "$expected_id" ]]; then + echo " $resource_spec/$container: Found ID: $actual_id" + error " $resource_spec/$container: ID mismatch (got: $actual_id, expected: $expected_id)" + add_failed_check "$service" "$resource_spec" "$container" "ID mismatch (got: $actual_id, expected: $expected_id)" + failed=1 + else + echo " $resource_spec/$container: Found ID: $actual_id" + echo " $resource_spec/$container: ID matches" + fi + + # Check Application Credential Secret + local actual_secret + if ! actual_secret=$(get_app_cred_field_from_pod "$resource_type_full/$resource_name" "$container" "$config_path" "application_credential_secret"); then + add_failed_check "$service" "$resource_spec" "$container" "Failed to extract application_credential_secret from pod" + failed=1 + elif [[ -z "$actual_secret" ]]; then + error " $resource_spec/$container: application_credential_secret not found in $config_path" + add_failed_check "$service" "$resource_spec" "$container" "application_credential_secret not found in config file" + failed=1 + elif [[ "$actual_secret" != "$expected_secret" ]]; then + echo " $resource_spec/$container: Found Secret: ${actual_secret:0:20}..." + error " $resource_spec/$container: Secret mismatch (got: ${actual_secret:0:20}..., expected: ${expected_secret:0:20}...)" + add_failed_check "$service" "$resource_spec" "$container" "Secret mismatch" + failed=1 + else + echo " $resource_spec/$container: Found Secret: ${actual_secret:0:20}..." + echo " $resource_spec/$container: Secret matches" + fi + done + + return $failed +} + +# Print summary of failed checks +print_failed_checks_summary() { + if [[ ${#FAILED_CHECKS[@]} -eq 0 ]]; then + return + fi + + echo + echo "FAILED APPLICATION CREDENTIAL CHECKS:" + for failure in "${FAILED_CHECKS[@]}"; do + echo " $failure" + done +} + +# Main execution +main() { + local services_to_check=() + + if [[ "$REQUESTED_SERVICE" == "all" ]]; then + services_to_check=("${!SERVICES[@]}") + else + if [[ -z "${SERVICES[$REQUESTED_SERVICE]:-}" ]]; then + error "Service '$REQUESTED_SERVICE' is not supported" + echo "Supported services: ${!SERVICES[*]}" >&2 + exit 1 + fi + services_to_check=("$REQUESTED_SERVICE") + fi + + local overall_failed=0 + + for service in "${services_to_check[@]}"; do + if ! check_service "$service"; then + overall_failed=1 + fi + echo + done + + # Print summary of failures + print_failed_checks_summary + + if [[ $overall_failed -eq 0 ]]; then + echo "All Application Credential checks passed" + else + echo "Some Application Credential checks failed" + fi + + exit $overall_failed +} + +main diff --git a/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/01-assert-deploy-openstack.yaml b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/01-assert-deploy-openstack.yaml new file mode 120000 index 000000000..762a8cf31 --- /dev/null +++ b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/01-assert-deploy-openstack.yaml @@ -0,0 +1 @@ +../../common/assert-sample-deployment.yaml \ No newline at end of file diff --git a/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/01-deploy-openstack.yaml b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/01-deploy-openstack.yaml new file mode 100644 index 000000000..6c9d0887d --- /dev/null +++ b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/01-deploy-openstack.yaml @@ -0,0 +1,5 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: | + oc kustomize ../../../../config/samples/base/openstackcontrolplane | oc apply -n $NAMESPACE -f - diff --git a/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/02-assert-appcred-crs.yaml b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/02-assert-appcred-crs.yaml new file mode 100644 index 000000000..8e526419a --- /dev/null +++ b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/02-assert-appcred-crs.yaml @@ -0,0 +1,84 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +commands: + - script: |- + set -euo pipefail + NS="${NAMESPACE}" + + wait_ready() { oc wait appcred/$1 -n "$NS" --for=condition=Ready --timeout=120s; } + + # ---- ac-barbican ---- + wait_ready ac-barbican + + EXP=$(oc get appcred ac-barbican -n "$NS" -o jsonpath='{.spec.expirationDays}') + [ "${EXP:-}" -eq 200 ] + + GRP=$(oc get appcred ac-barbican -n "$NS" -o jsonpath='{.spec.gracePeriodDays}') + [ "${GRP:-}" -eq 90 ] + + ROL=$(oc get appcred ac-barbican -n "$NS" -o jsonpath='{.spec.roles[*]}') + case " $ROL " in *" service "*) ;; *) exit 1;; esac + + UNR=$(oc get appcred ac-barbican -n "$NS" -o jsonpath='{.spec.unrestricted}' 2>/dev/null || echo "") + [ "${UNR:-false}" = "false" ] + + # ---- ac-cinder ---- + wait_ready ac-cinder + + EXP=$(oc get appcred ac-cinder -n "$NS" -o jsonpath='{.spec.expirationDays}') + [ "${EXP:-}" -eq 10 ] + + GRP=$(oc get appcred ac-cinder -n "$NS" -o jsonpath='{.spec.gracePeriodDays}') + [ "${GRP:-}" -eq 5 ] + + ROL=$(oc get appcred ac-cinder -n "$NS" -o jsonpath='{.spec.roles[*]}') + case " $ROL " in *" admin "*) ;; *) exit 1;; esac + case " $ROL " in *" service "*) ;; *) exit 1;; esac + + UNR=$(oc get appcred ac-cinder -n "$NS" -o jsonpath='{.spec.unrestricted}' 2>/dev/null || echo "") + [ "${UNR}" = "true" ] + + # ---- ac-swift ---- + wait_ready ac-swift + + EXP=$(oc get appcred ac-swift -n "$NS" -o jsonpath='{.spec.expirationDays}') + [ "${EXP:-}" -eq 200 ] + + GRP=$(oc get appcred ac-swift -n "$NS" -o jsonpath='{.spec.gracePeriodDays}') + [ "${GRP:-}" -eq 90 ] + + ROL=$(oc get appcred ac-swift -n "$NS" -o jsonpath='{.spec.roles[*]}') + case " $ROL " in *" service "*) ;; *) exit 1;; esac + + UNR=$(oc get appcred ac-swift -n "$NS" -o jsonpath='{.spec.unrestricted}' 2>/dev/null || echo "") + [ "${UNR:-false}" = "false" ] + + # ---- ac-glance ---- + wait_ready ac-glance + + EXP=$(oc get appcred ac-glance -n "$NS" -o jsonpath='{.spec.expirationDays}') + [ "${EXP:-}" -eq 200 ] + + GRP=$(oc get appcred ac-glance -n "$NS" -o jsonpath='{.spec.gracePeriodDays}') + [ "${GRP:-}" -eq 90 ] + + ROL=$(oc get appcred ac-glance -n "$NS" -o jsonpath='{.spec.roles[*]}') + case " $ROL " in *" service "*) ;; *) exit 1;; esac + + UNR=$(oc get appcred ac-glance -n "$NS" -o jsonpath='{.spec.unrestricted}' 2>/dev/null || echo "") + [ "${UNR:-false}" = "false" ] + + # ---- ac-manila ---- + wait_ready ac-manila + + EXP=$(oc get appcred ac-manila -n "$NS" -o jsonpath='{.spec.expirationDays}') + [ "${EXP:-}" -eq 200 ] + + GRP=$(oc get appcred ac-manila -n "$NS" -o jsonpath='{.spec.gracePeriodDays}') + [ "${GRP:-}" -eq 90 ] + + ROL=$(oc get appcred ac-manila -n "$NS" -o jsonpath='{.spec.roles[*]}') + case " $ROL " in *" service "*) ;; *) exit 1;; esac + + UNR=$(oc get appcred ac-manila -n "$NS" -o jsonpath='{.spec.unrestricted}' 2>/dev/null || echo "") + [ "${UNR:-false}" = "false" ] diff --git a/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/02-deploy-appcred-config.yaml b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/02-deploy-appcred-config.yaml new file mode 100644 index 000000000..3cb5652ca --- /dev/null +++ b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/02-deploy-appcred-config.yaml @@ -0,0 +1,5 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: | + oc kustomize ../../../../config/samples/applicationcredentials | oc apply -n $NAMESPACE -f - diff --git a/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/03-get-appcred-ids.yaml b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/03-get-appcred-ids.yaml new file mode 100644 index 000000000..d0491d3cb --- /dev/null +++ b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/03-get-appcred-ids.yaml @@ -0,0 +1,28 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: | + echo "Waiting 60 seconds for OpenStack control plane to be fully ready..." + echo "Control plane switches to ready state before service pods catch up with AC changes" + sleep 60 + + echo "Gather and save appcred IDs" + # TODO: Uncomment services here when they support application credentials in their operators + # Currently implemented: barbican, cinder, glance, swift, manila + # Future support: nova, neutron, placement, ceilometer, ironic, heat, octavia, designate, watcher, aodh + bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE barbican + bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE cinder + bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE glance + bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE swift + bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE manila + # bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE nova + # bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE neutron + # bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE placement + # bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE ceilometer + # bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE ironic + # bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE heat + # bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE octavia + # bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE designate + # bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE watcher + # bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE aodh + # bash -s < ../../common/osp_check_appcred_id.sh $NAMESPACE all diff --git a/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/07-cleanup.yaml b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/07-cleanup.yaml new file mode 100644 index 000000000..df9df9fe0 --- /dev/null +++ b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/07-cleanup.yaml @@ -0,0 +1,11 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +delete: +- apiVersion: core.openstack.org/v1beta1 + kind: OpenStackControlPlane + name: openstack +commands: +- script: | + oc delete secret --ignore-not-found=true combined-ca-bundle -n $NAMESPACE + oc delete secret -l service-cert -n $NAMESPACE + oc delete secret -l ca-cert -n $NAMESPACE diff --git a/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/07-errors-cleanup.yaml b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/07-errors-cleanup.yaml new file mode 120000 index 000000000..4d7b8362e --- /dev/null +++ b/tests/kuttl/tests/ctlplane-basic-deployment-with-appcred/07-errors-cleanup.yaml @@ -0,0 +1 @@ +../../common/errors_cleanup_openstack.yaml \ No newline at end of file