From 468549ce5f06fb572033976dfc47a29422760cff Mon Sep 17 00:00:00 2001 From: Jaromir Wysoglad Date: Mon, 20 Nov 2023 05:36:47 -0500 Subject: [PATCH 1/3] Rewrite telemetry resource Rewrite the telemetry resource to use a similar pattern to the openstack control plane resource. The telemetry resource is an umbrela resource for other telemetry related resources, which for right now are "ceilometer" and "autoscaling". These resources can be enabled and customized by using the "enabled" and "template" fields similarly to how openstack services are enabled and customized in the openstack control plane CR. The "secret" field in the telemetry resource can be used to set the "secret" fields for both ceilometer and autoscaling. The autoscaling is disabled by default and ceilometer is enabled by default. Look at the config/samples/telemetry_v1beta1_telemetry.yaml for an example CR. --- .../telemetry.openstack.org_telemetries.yaml | 695 +++++++++--------- api/v1beta1/conditions.go | 12 + api/v1beta1/telemetry_types.go | 45 +- api/v1beta1/telemetry_webhook.go | 40 +- api/v1beta1/zz_generated.deepcopy.go | 32 + .../telemetry.openstack.org_telemetries.yaml | 695 +++++++++--------- .../samples/telemetry_v1beta1_telemetry.yaml | 19 +- controllers/telemetry_controller.go | 175 +++-- .../kuttl/suites/default/tests/01-deploy.yaml | 32 +- 9 files changed, 989 insertions(+), 756 deletions(-) diff --git a/api/bases/telemetry.openstack.org_telemetries.yaml b/api/bases/telemetry.openstack.org_telemetries.yaml index 15adf1a0..578c8b03 100644 --- a/api/bases/telemetry.openstack.org_telemetries.yaml +++ b/api/bases/telemetry.openstack.org_telemetries.yaml @@ -36,13 +36,352 @@ spec: description: TelemetrySpec defines the desired state of Telemetry properties: autoscaling: - description: Autoscaling - Spec definition for the Autoscaling service - of this Telemetry deployment + description: Autoscaling - Parameters related to the autoscaling service properties: - aodh: - description: Aodh spec + enabled: + default: false + description: Enabled - Whether OpenStack autoscaling service should + be deployed and managed + type: boolean + template: + description: Template - Overrides to use when creating the OpenStack + autoscaling service properties: - apiImage: + aodh: + description: Aodh spec + properties: + apiImage: + type: string + customServiceConfig: + default: '# add your customization here' + description: CustomServiceConfig - customize the service + config using this parameter to change service defaults, + or overwrite rendered information using raw OpenStack + config format. The content gets added to to /etc//.conf.d + directory as custom.conf file. + type: string + databaseInstance: + description: MariaDB instance name Right now required + by the maridb-operator to get the credentials from the + instance to create the DB Might not be required in future + type: string + databaseUser: + default: aodh + description: Database user name Needed to connect to a + database used by aodh + type: string + defaultConfigOverwrite: + additionalProperties: + type: string + description: 'ConfigOverwrite - interface to overwrite + default config files like e.g. logging.conf or policy.json. + But can also be used to add additional files. Those + get added to the service config dir in /etc/ + . TODO: -> implement' + type: object + evaluatorImage: + type: string + listenerImage: + type: string + memcachedInstance: + default: memcached + description: Memcached instance name. + type: string + networkAttachmentDefinitions: + description: NetworkAttachmentDefinitions list of network + attachment definitions the service pod gets attached + to + items: + type: string + type: array + notifierImage: + type: string + override: + description: Override, provides the ability to override + the generated manifest of several child resources. + properties: + service: + description: Override configuration for the Service + created to serve traffic to the cluster. + properties: + endpointURL: + type: string + metadata: + description: EmbeddedLabelsAnnotations is an embedded + subset of the fields included in k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta. + Only labels and annotations are included. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured + key value map stored with a resource that + may be set by external tools to store and + retrieve arbitrary metadata. They are not + queryable and should be preserved when modifying + objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values + that can be used to organize and categorize + (scope and select) objects. May match selectors + of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + type: object + spec: + description: OverrideServiceSpec is a subset of + the fields included in https://pkg.go.dev/k8s.io/api@v0.26.6/core/v1#ServiceSpec + Limited to Type, SessionAffinity, LoadBalancerSourceRanges, + ExternalName, ExternalTrafficPolicy, SessionAffinityConfig, + IPFamilyPolicy, LoadBalancerClass and InternalTrafficPolicy + properties: + externalName: + description: externalName is the external + reference that discovery mechanisms will + return as an alias for this service (e.g. + a DNS CNAME record). No proxying will be + involved. Must be a lowercase RFC-1123 + hostname (https://tools.ietf.org/html/rfc1123) + and requires `type` to be "ExternalName". + type: string + externalTrafficPolicy: + description: externalTrafficPolicy describes + how nodes distribute service traffic they + receive on one of the Service's "externally-facing" + addresses (NodePorts, ExternalIPs, and LoadBalancer + IPs). If set to "Local", the proxy will + configure the service in a way that assumes + that external load balancers will take care + of balancing the service traffic between + nodes, and so each node will deliver traffic + only to the node-local endpoints of the + service, without masquerading the client + source IP. (Traffic mistakenly sent to a + node with no endpoints will be dropped.) + The default value, "Cluster", uses the standard + behavior of routing to all endpoints evenly + (possibly modified by topology and other + features). Note that traffic sent to an + External IP or LoadBalancer IP from within + the cluster will always get "Cluster" semantics, + but clients sending to a NodePort from within + the cluster may need to take traffic policy + into account when picking a node. + type: string + internalTrafficPolicy: + description: InternalTrafficPolicy describes + how nodes distribute service traffic they + receive on the ClusterIP. If set to "Local", + the proxy will assume that pods only want + to talk to endpoints of the service on the + same node as the pod, dropping the traffic + if there are no local endpoints. The default + value, "Cluster", uses the standard behavior + of routing to all endpoints evenly (possibly + modified by topology and other features). + type: string + ipFamilyPolicy: + description: IPFamilyPolicy represents the + dual-stack-ness requested or required by + this Service. If there is no value provided, + then this field will be set to SingleStack. + Services can be "SingleStack" (a single + IP family), "PreferDualStack" (two IP families + on dual-stack configured clusters or a single + IP family on single-stack clusters), or + "RequireDualStack" (two IP families on dual-stack + configured clusters, otherwise fail). The + ipFamilies and clusterIPs fields depend + on the value of this field. This field will + be wiped when updating a service to type + ExternalName. + type: string + loadBalancerClass: + description: loadBalancerClass is the class + of the load balancer implementation this + Service belongs to. If specified, the value + of this field must be a label-style identifier, + with an optional prefix, e.g. "internal-vip" + or "example.com/internal-vip". Unprefixed + names are reserved for end-users. This field + can only be set when the Service type is + 'LoadBalancer'. If not set, the default + load balancer implementation is used, today + this is typically done through the cloud + provider integration, but should apply for + any default implementation. If set, it is + assumed that a load balancer implementation + is watching for Services with a matching + class. Any default load balancer implementation + (e.g. cloud providers) should ignore Services + that set this field. This field can only + be set when creating or updating a Service + to type 'LoadBalancer'. Once set, it can + not be changed. This field will be wiped + when a service is updated to a non 'LoadBalancer' + type. + type: string + loadBalancerSourceRanges: + description: 'If specified and supported by + the platform, this will restrict traffic + through the cloud-provider load-balancer + will be restricted to the specified client + IPs. This field will be ignored if the cloud-provider + does not support the feature." More info: + https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/' + items: + type: string + type: array + sessionAffinity: + description: 'Supports "ClientIP" and "None". + Used to maintain session affinity. Enable + client IP based session affinity. Must be + ClientIP or None. Defaults to None. More + info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies' + type: string + sessionAffinityConfig: + description: sessionAffinityConfig contains + the configurations of session affinity. + properties: + clientIP: + description: clientIP contains the configurations + of Client IP based session affinity. + properties: + timeoutSeconds: + description: timeoutSeconds specifies + the seconds of ClientIP type session + sticky time. The value must be >0 + && <=86400(for 1 day) if ServiceAffinity + == "ClientIP". Default value is + 10800(for 3 hours). + format: int32 + type: integer + type: object + type: object + type: + description: 'type determines how the Service + is exposed. Defaults to ClusterIP. Valid + options are ExternalName, ClusterIP, NodePort, + and LoadBalancer. "ClusterIP" allocates + a cluster-internal IP address for load-balancing + to endpoints. Endpoints are determined by + the selector or if that is not specified, + by manual construction of an Endpoints object + or EndpointSlice objects. If clusterIP is + "None", no virtual IP is allocated and the + endpoints are published as a set of endpoints + rather than a virtual IP. "NodePort" builds + on ClusterIP and allocates a port on every + node which routes to the same endpoints + as the clusterIP. "LoadBalancer" builds + on NodePort and creates an external load-balancer + (if supported in the current cloud) which + routes to the same endpoints as the clusterIP. + "ExternalName" aliases this service to the + specified externalName. Several other fields + do not apply to ExternalName services. More + info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types' + type: string + type: object + type: object + type: object + passwordSelector: + default: + aodhService: AodhPassword + database: AodhDatabasePassword + description: PasswordSelectors - Selectors to identify + the service from the Secret + properties: + aodhService: + default: AodhPassword + description: AodhService - Selector to get the aodh + service password from the Secret + type: string + database: + default: AodhDatabasePassword + description: Database - Selector to get the aodh database + user password from the Secret + type: string + service: + default: CeilometerPassword + description: Service - Selector to get the ceilometer + service password from the Secret + type: string + type: object + preserveJobs: + default: false + description: PreserveJobs - do not delete jobs after they + finished e.g. to check logs + type: boolean + rabbitMqClusterName: + default: rabbitmq + description: RabbitMQ instance name Needed to request + a transportURL that is created and used in Aodh + type: string + secret: + description: Secret containing OpenStack password information + for aodh + type: string + serviceUser: + default: aodh + description: ServiceUser - optional username used for + this service to register in keystone + type: string + required: + - apiImage + - databaseInstance + - evaluatorImage + - listenerImage + - memcachedInstance + - notifierImage + - secret + type: object + heatInstance: + default: heat + description: Heat instance name. + type: string + prometheus: + description: Specification of which prometheus to use for + autoscaling + properties: + deployPrometheus: + default: false + description: Enables the deployment of autoscaling prometheus + type: boolean + host: + description: Host of user deployed prometheus if deployPrometheus + is set to false + type: string + port: + description: Port of user deployed prometheus if deployPrometheus + is set to false + format: int32 + maximum: 65535 + minimum: 1 + type: integer + type: object + required: + - heatInstance + type: object + type: object + ceilometer: + description: Ceilometer - Parameters related to the ceilometer service + properties: + enabled: + default: true + description: Enabled - Whether OpenStack Ceilometer service should + be deployed and managed + type: boolean + template: + description: Template - Overrides to use when creating the OpenStack + Ceilometer service + properties: + centralImage: + type: string + computeImage: type: string customServiceConfig: default: '# add your customization here' @@ -52,16 +391,6 @@ spec: The content gets added to to /etc//.conf.d directory as custom.conf file. type: string - databaseInstance: - description: MariaDB instance name Right now required by the - maridb-operator to get the credentials from the instance - to create the DB Might not be required in future - type: string - databaseUser: - default: aodh - description: Database user name Needed to connect to a database - used by aodh - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -70,13 +399,7 @@ spec: can also be used to add additional files. Those get added to the service config dir in /etc/ . TODO: -> implement' type: object - evaluatorImage: - type: string - listenerImage: - type: string - memcachedInstance: - default: memcached - description: Memcached instance name. + ipmiImage: type: string networkAttachmentDefinitions: description: NetworkAttachmentDefinitions list of network @@ -84,193 +407,13 @@ spec: items: type: string type: array - notifierImage: + nodeExporterImage: + type: string + notificationImage: type: string - override: - description: Override, provides the ability to override the - generated manifest of several child resources. - properties: - service: - description: Override configuration for the Service created - to serve traffic to the cluster. - properties: - endpointURL: - type: string - metadata: - description: EmbeddedLabelsAnnotations is an embedded - subset of the fields included in k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta. - Only labels and annotations are included. - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key - value map stored with a resource that may be - set by external tools to store and retrieve - arbitrary metadata. They are not queryable and - should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values that - can be used to organize and categorize (scope - and select) objects. May match selectors of - replication controllers and services. More info: - http://kubernetes.io/docs/user-guide/labels' - type: object - type: object - spec: - description: OverrideServiceSpec is a subset of the - fields included in https://pkg.go.dev/k8s.io/api@v0.26.6/core/v1#ServiceSpec - Limited to Type, SessionAffinity, LoadBalancerSourceRanges, - ExternalName, ExternalTrafficPolicy, SessionAffinityConfig, - IPFamilyPolicy, LoadBalancerClass and InternalTrafficPolicy - properties: - externalName: - description: externalName is the external reference - that discovery mechanisms will return as an - alias for this service (e.g. a DNS CNAME record). - No proxying will be involved. Must be a lowercase - RFC-1123 hostname (https://tools.ietf.org/html/rfc1123) - and requires `type` to be "ExternalName". - type: string - externalTrafficPolicy: - description: externalTrafficPolicy describes how - nodes distribute service traffic they receive - on one of the Service's "externally-facing" - addresses (NodePorts, ExternalIPs, and LoadBalancer - IPs). If set to "Local", the proxy will configure - the service in a way that assumes that external - load balancers will take care of balancing the - service traffic between nodes, and so each node - will deliver traffic only to the node-local - endpoints of the service, without masquerading - the client source IP. (Traffic mistakenly sent - to a node with no endpoints will be dropped.) - The default value, "Cluster", uses the standard - behavior of routing to all endpoints evenly - (possibly modified by topology and other features). - Note that traffic sent to an External IP or - LoadBalancer IP from within the cluster will - always get "Cluster" semantics, but clients - sending to a NodePort from within the cluster - may need to take traffic policy into account - when picking a node. - type: string - internalTrafficPolicy: - description: InternalTrafficPolicy describes how - nodes distribute service traffic they receive - on the ClusterIP. If set to "Local", the proxy - will assume that pods only want to talk to endpoints - of the service on the same node as the pod, - dropping the traffic if there are no local endpoints. - The default value, "Cluster", uses the standard - behavior of routing to all endpoints evenly - (possibly modified by topology and other features). - type: string - ipFamilyPolicy: - description: IPFamilyPolicy represents the dual-stack-ness - requested or required by this Service. If there - is no value provided, then this field will be - set to SingleStack. Services can be "SingleStack" - (a single IP family), "PreferDualStack" (two - IP families on dual-stack configured clusters - or a single IP family on single-stack clusters), - or "RequireDualStack" (two IP families on dual-stack - configured clusters, otherwise fail). The ipFamilies - and clusterIPs fields depend on the value of - this field. This field will be wiped when updating - a service to type ExternalName. - type: string - loadBalancerClass: - description: loadBalancerClass is the class of - the load balancer implementation this Service - belongs to. If specified, the value of this - field must be a label-style identifier, with - an optional prefix, e.g. "internal-vip" or "example.com/internal-vip". - Unprefixed names are reserved for end-users. - This field can only be set when the Service - type is 'LoadBalancer'. If not set, the default - load balancer implementation is used, today - this is typically done through the cloud provider - integration, but should apply for any default - implementation. If set, it is assumed that a - load balancer implementation is watching for - Services with a matching class. Any default - load balancer implementation (e.g. cloud providers) - should ignore Services that set this field. - This field can only be set when creating or - updating a Service to type 'LoadBalancer'. Once - set, it can not be changed. This field will - be wiped when a service is updated to a non - 'LoadBalancer' type. - type: string - loadBalancerSourceRanges: - description: 'If specified and supported by the - platform, this will restrict traffic through - the cloud-provider load-balancer will be restricted - to the specified client IPs. This field will - be ignored if the cloud-provider does not support - the feature." More info: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/' - items: - type: string - type: array - sessionAffinity: - description: 'Supports "ClientIP" and "None". - Used to maintain session affinity. Enable client - IP based session affinity. Must be ClientIP - or None. Defaults to None. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies' - type: string - sessionAffinityConfig: - description: sessionAffinityConfig contains the - configurations of session affinity. - properties: - clientIP: - description: clientIP contains the configurations - of Client IP based session affinity. - properties: - timeoutSeconds: - description: timeoutSeconds specifies - the seconds of ClientIP type session - sticky time. The value must be >0 && - <=86400(for 1 day) if ServiceAffinity - == "ClientIP". Default value is 10800(for - 3 hours). - format: int32 - type: integer - type: object - type: object - type: - description: 'type determines how the Service - is exposed. Defaults to ClusterIP. Valid options - are ExternalName, ClusterIP, NodePort, and LoadBalancer. - "ClusterIP" allocates a cluster-internal IP - address for load-balancing to endpoints. Endpoints - are determined by the selector or if that is - not specified, by manual construction of an - Endpoints object or EndpointSlice objects. If - clusterIP is "None", no virtual IP is allocated - and the endpoints are published as a set of - endpoints rather than a virtual IP. "NodePort" - builds on ClusterIP and allocates a port on - every node which routes to the same endpoints - as the clusterIP. "LoadBalancer" builds on NodePort - and creates an external load-balancer (if supported - in the current cloud) which routes to the same - endpoints as the clusterIP. "ExternalName" aliases - this service to the specified externalName. - Several other fields do not apply to ExternalName - services. More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types' - type: string - type: object - type: object - type: object passwordSelector: default: - aodhService: AodhPassword - database: AodhDatabasePassword + service: CeilometerPassword description: PasswordSelectors - Selectors to identify the service from the Secret properties: @@ -290,146 +433,38 @@ spec: service password from the Secret type: string type: object - preserveJobs: - default: false - description: PreserveJobs - do not delete jobs after they - finished e.g. to check logs - type: boolean rabbitMqClusterName: default: rabbitmq description: RabbitMQ instance name Needed to request a transportURL - that is created and used in Aodh + that is created and used in Telemetry type: string secret: description: Secret containing OpenStack password information - for aodh + for ceilometer type: string serviceUser: - default: aodh + default: ceilometer description: ServiceUser - optional username used for this service to register in keystone type: string + sgCoreImage: + type: string required: - - apiImage - - databaseInstance - - evaluatorImage - - listenerImage - - memcachedInstance - - notifierImage + - centralImage + - computeImage + - ipmiImage + - nodeExporterImage + - notificationImage - secret + - sgCoreImage type: object - heatInstance: - default: heat - description: Heat instance name. - type: string - prometheus: - description: Specification of which prometheus to use for autoscaling - properties: - deployPrometheus: - default: false - description: Enables the deployment of autoscaling prometheus - type: boolean - host: - description: Host of user deployed prometheus if deployPrometheus - is set to false - type: string - port: - description: Port of user deployed prometheus if deployPrometheus - is set to false - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - required: - - heatInstance - type: object - ceilometer: - description: Ceilometer - Spec definition for the Ceilometer service - of this Telemetry deployment - properties: - centralImage: - type: string - computeImage: - type: string - customServiceConfig: - default: '# add your customization here' - description: CustomServiceConfig - customize the service config - using this parameter to change service defaults, or overwrite - rendered information using raw OpenStack config format. The - content gets added to to /etc//.conf.d directory - as custom.conf file. - type: string - defaultConfigOverwrite: - additionalProperties: - type: string - description: 'ConfigOverwrite - interface to overwrite default - config files like e.g. logging.conf or policy.json. But can - also be used to add additional files. Those get added to the - service config dir in /etc/ . TODO: -> implement' - type: object - ipmiImage: - type: string - networkAttachmentDefinitions: - description: NetworkAttachmentDefinitions list of network attachment - definitions the service pod gets attached to - items: - type: string - type: array - nodeExporterImage: - type: string - notificationImage: - type: string - passwordSelector: - default: - service: CeilometerPassword - description: PasswordSelectors - Selectors to identify the service - from the Secret - properties: - aodhService: - default: AodhPassword - description: AodhService - Selector to get the aodh service - password from the Secret - type: string - database: - default: AodhDatabasePassword - description: Database - Selector to get the aodh database - user password from the Secret - type: string - service: - default: CeilometerPassword - description: Service - Selector to get the ceilometer service - password from the Secret - type: string - type: object - rabbitMqClusterName: - default: rabbitmq - description: RabbitMQ instance name Needed to request a transportURL - that is created and used in Telemetry - type: string - secret: - description: Secret containing OpenStack password information - for ceilometer - type: string - serviceUser: - default: ceilometer - description: ServiceUser - optional username used for this service - to register in keystone - type: string - sgCoreImage: - type: string - required: - - centralImage - - computeImage - - ipmiImage - - nodeExporterImage - - notificationImage - - secret - - sgCoreImage type: object + secret: + description: Secret containing OpenStack password information for + telemetry services + type: string required: - - autoscaling - - ceilometer + - secret type: object status: description: TelemetryStatus defines the observed state of Telemetry diff --git a/api/v1beta1/conditions.go b/api/v1beta1/conditions.go index f1eec66d..dbcf25e2 100644 --- a/api/v1beta1/conditions.go +++ b/api/v1beta1/conditions.go @@ -45,18 +45,30 @@ const ( // CeilometerReadyInitMessage CeilometerReadyInitMessage = "Ceilometer not started" + // CeilometerReadyMessage + CeilometerReadyMessage = "Ceilometer completed" + // CeilometerReadyErrorMessage CeilometerReadyErrorMessage = "Ceilometer error occured %s" + // CeilometerReadyRunningMessage + CeilometerReadyRunningMessage = "Ceilometer in progress" + // // AutoscalingReady condition messages // // AutoscalingReadyInitMessage AutoscalingReadyInitMessage = "Autoscaling not started" + // AutoscalingReadyMessage + AutoscalingReadyMessage = "Autoscaling completed" + // AutoscalingReadyErrorMessage AutoscalingReadyErrorMessage = "Autoscaling error occured %s" + // AutoscalingReadyRunningMessage + AutoscalingReadyRunningMessage = "Autoscaling in progress" + // HeatReadyInitMessage HeatReadyInitMessage = "Heat not started" diff --git a/api/v1beta1/telemetry_types.go b/api/v1beta1/telemetry_types.go index b58679ab..d8c69c7e 100644 --- a/api/v1beta1/telemetry_types.go +++ b/api/v1beta1/telemetry_types.go @@ -45,13 +45,46 @@ type PasswordsSelector struct { // TelemetrySpec defines the desired state of Telemetry type TelemetrySpec struct { - // +kubebuilder:validation:Required - // Autoscaling - Spec definition for the Autoscaling service of this Telemetry deployment - Autoscaling AutoscalingSpec `json:"autoscaling"` + // +kubebuilder:validation:Optional + // Autoscaling - Parameters related to the autoscaling service + Autoscaling AutoscalingSection `json:"autoscaling,omitempty"` + + // +kubebuilder:validation:Optional + // Ceilometer - Parameters related to the ceilometer service + Ceilometer CeilometerSection `json:"ceilometer,omitempty"` + + // Secret containing OpenStack password information for telemetry services + // +kubebuilder:validation:Required + Secret string `json:"secret"` + +} + +// CeilometerSection defines the desired state of the ceilometer service +type CeilometerSection struct { + // +kubebuilder:validation:Optional + // +kubebuilder:default=true + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + // Enabled - Whether OpenStack Ceilometer service should be deployed and managed + Enabled bool `json:"enabled"` + + // +kubebuilder:validation:Optional + //+operator-sdk:csv:customresourcedefinitions:type=spec + // Template - Overrides to use when creating the OpenStack Ceilometer service + Template CeilometerSpec `json:"template,omitempty"` +} - // +kubebuilder:validation:Required - // Ceilometer - Spec definition for the Ceilometer service of this Telemetry deployment - Ceilometer CeilometerSpec `json:"ceilometer"` +// AutoscalingSection defines the desired state of the autoscaling service +type AutoscalingSection struct { + // +kubebuilder:validation:Optional + // +kubebuilder:default=false + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + // Enabled - Whether OpenStack autoscaling service should be deployed and managed + Enabled bool `json:"enabled"` + + // +kubebuilder:validation:Optional + //+operator-sdk:csv:customresourcedefinitions:type=spec + // Template - Overrides to use when creating the OpenStack autoscaling service + Template AutoscalingSpec `json:"template,omitempty"` } // TelemetryStatus defines the observed state of Telemetry diff --git a/api/v1beta1/telemetry_webhook.go b/api/v1beta1/telemetry_webhook.go index a92f6bdf..fe4aa7a0 100644 --- a/api/v1beta1/telemetry_webhook.go +++ b/api/v1beta1/telemetry_webhook.go @@ -72,35 +72,35 @@ func (r *Telemetry) Default() { // Default - set defaults for this Telemetry spec func (spec *TelemetrySpec) Default() { - if spec.Ceilometer.CentralImage == "" { - spec.Ceilometer.CentralImage = telemetryDefaults.CentralContainerImageURL + if spec.Ceilometer.Template.CentralImage == "" { + spec.Ceilometer.Template.CentralImage = telemetryDefaults.CentralContainerImageURL } - if spec.Ceilometer.ComputeImage == "" { - spec.Ceilometer.ComputeImage = telemetryDefaults.ComputeContainerImageURL + if spec.Ceilometer.Template.ComputeImage == "" { + spec.Ceilometer.Template.ComputeImage = telemetryDefaults.ComputeContainerImageURL } - if spec.Ceilometer.IpmiImage == "" { - spec.Ceilometer.IpmiImage = telemetryDefaults.IpmiContainerImageURL + if spec.Ceilometer.Template.IpmiImage == "" { + spec.Ceilometer.Template.IpmiImage = telemetryDefaults.IpmiContainerImageURL } - if spec.Ceilometer.NotificationImage == "" { - spec.Ceilometer.NotificationImage = telemetryDefaults.NotificationContainerImageURL + if spec.Ceilometer.Template.NotificationImage == "" { + spec.Ceilometer.Template.NotificationImage = telemetryDefaults.NotificationContainerImageURL } - if spec.Ceilometer.SgCoreImage == "" { - spec.Ceilometer.SgCoreImage = telemetryDefaults.SgCoreContainerImageURL + if spec.Ceilometer.Template.SgCoreImage == "" { + spec.Ceilometer.Template.SgCoreImage = telemetryDefaults.SgCoreContainerImageURL } - if spec.Ceilometer.NodeExporterImage == "" { - spec.Ceilometer.NodeExporterImage = telemetryDefaults.NodeExporterContainerImageURL + if spec.Ceilometer.Template.NodeExporterImage == "" { + spec.Ceilometer.Template.NodeExporterImage = telemetryDefaults.NodeExporterContainerImageURL } - if spec.Autoscaling.Aodh.APIImage == "" { - spec.Autoscaling.Aodh.APIImage = telemetryDefaults.AodhAPIContainerImageURL + if spec.Autoscaling.Template.Aodh.APIImage == "" { + spec.Autoscaling.Template.Aodh.APIImage = telemetryDefaults.AodhAPIContainerImageURL } - if spec.Autoscaling.Aodh.EvaluatorImage == "" { - spec.Autoscaling.Aodh.EvaluatorImage = telemetryDefaults.AodhEvaluatorContainerImageURL + if spec.Autoscaling.Template.Aodh.EvaluatorImage == "" { + spec.Autoscaling.Template.Aodh.EvaluatorImage = telemetryDefaults.AodhEvaluatorContainerImageURL } - if spec.Autoscaling.Aodh.NotifierImage == "" { - spec.Autoscaling.Aodh.NotifierImage = telemetryDefaults.AodhNotifierContainerImageURL + if spec.Autoscaling.Template.Aodh.NotifierImage == "" { + spec.Autoscaling.Template.Aodh.NotifierImage = telemetryDefaults.AodhNotifierContainerImageURL } - if spec.Autoscaling.Aodh.ListenerImage == "" { - spec.Autoscaling.Aodh.ListenerImage = telemetryDefaults.AodhListenerContainerImageURL + if spec.Autoscaling.Template.Aodh.ListenerImage == "" { + spec.Autoscaling.Template.Aodh.ListenerImage = telemetryDefaults.AodhListenerContainerImageURL } } diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index d23916c6..c0f8de3b 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -150,6 +150,22 @@ func (in *AutoscalingList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AutoscalingSection) DeepCopyInto(out *AutoscalingSection) { + *out = *in + in.Template.DeepCopyInto(&out.Template) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscalingSection. +func (in *AutoscalingSection) DeepCopy() *AutoscalingSection { + if in == nil { + return nil + } + out := new(AutoscalingSection) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AutoscalingSpec) DeepCopyInto(out *AutoscalingSpec) { *out = *in @@ -282,6 +298,22 @@ func (in *CeilometerList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CeilometerSection) DeepCopyInto(out *CeilometerSection) { + *out = *in + in.Template.DeepCopyInto(&out.Template) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CeilometerSection. +func (in *CeilometerSection) DeepCopy() *CeilometerSection { + if in == nil { + return nil + } + out := new(CeilometerSection) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CeilometerSpec) DeepCopyInto(out *CeilometerSpec) { *out = *in diff --git a/config/crd/bases/telemetry.openstack.org_telemetries.yaml b/config/crd/bases/telemetry.openstack.org_telemetries.yaml index 15adf1a0..578c8b03 100644 --- a/config/crd/bases/telemetry.openstack.org_telemetries.yaml +++ b/config/crd/bases/telemetry.openstack.org_telemetries.yaml @@ -36,13 +36,352 @@ spec: description: TelemetrySpec defines the desired state of Telemetry properties: autoscaling: - description: Autoscaling - Spec definition for the Autoscaling service - of this Telemetry deployment + description: Autoscaling - Parameters related to the autoscaling service properties: - aodh: - description: Aodh spec + enabled: + default: false + description: Enabled - Whether OpenStack autoscaling service should + be deployed and managed + type: boolean + template: + description: Template - Overrides to use when creating the OpenStack + autoscaling service properties: - apiImage: + aodh: + description: Aodh spec + properties: + apiImage: + type: string + customServiceConfig: + default: '# add your customization here' + description: CustomServiceConfig - customize the service + config using this parameter to change service defaults, + or overwrite rendered information using raw OpenStack + config format. The content gets added to to /etc//.conf.d + directory as custom.conf file. + type: string + databaseInstance: + description: MariaDB instance name Right now required + by the maridb-operator to get the credentials from the + instance to create the DB Might not be required in future + type: string + databaseUser: + default: aodh + description: Database user name Needed to connect to a + database used by aodh + type: string + defaultConfigOverwrite: + additionalProperties: + type: string + description: 'ConfigOverwrite - interface to overwrite + default config files like e.g. logging.conf or policy.json. + But can also be used to add additional files. Those + get added to the service config dir in /etc/ + . TODO: -> implement' + type: object + evaluatorImage: + type: string + listenerImage: + type: string + memcachedInstance: + default: memcached + description: Memcached instance name. + type: string + networkAttachmentDefinitions: + description: NetworkAttachmentDefinitions list of network + attachment definitions the service pod gets attached + to + items: + type: string + type: array + notifierImage: + type: string + override: + description: Override, provides the ability to override + the generated manifest of several child resources. + properties: + service: + description: Override configuration for the Service + created to serve traffic to the cluster. + properties: + endpointURL: + type: string + metadata: + description: EmbeddedLabelsAnnotations is an embedded + subset of the fields included in k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta. + Only labels and annotations are included. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured + key value map stored with a resource that + may be set by external tools to store and + retrieve arbitrary metadata. They are not + queryable and should be preserved when modifying + objects. More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values + that can be used to organize and categorize + (scope and select) objects. May match selectors + of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object + type: object + spec: + description: OverrideServiceSpec is a subset of + the fields included in https://pkg.go.dev/k8s.io/api@v0.26.6/core/v1#ServiceSpec + Limited to Type, SessionAffinity, LoadBalancerSourceRanges, + ExternalName, ExternalTrafficPolicy, SessionAffinityConfig, + IPFamilyPolicy, LoadBalancerClass and InternalTrafficPolicy + properties: + externalName: + description: externalName is the external + reference that discovery mechanisms will + return as an alias for this service (e.g. + a DNS CNAME record). No proxying will be + involved. Must be a lowercase RFC-1123 + hostname (https://tools.ietf.org/html/rfc1123) + and requires `type` to be "ExternalName". + type: string + externalTrafficPolicy: + description: externalTrafficPolicy describes + how nodes distribute service traffic they + receive on one of the Service's "externally-facing" + addresses (NodePorts, ExternalIPs, and LoadBalancer + IPs). If set to "Local", the proxy will + configure the service in a way that assumes + that external load balancers will take care + of balancing the service traffic between + nodes, and so each node will deliver traffic + only to the node-local endpoints of the + service, without masquerading the client + source IP. (Traffic mistakenly sent to a + node with no endpoints will be dropped.) + The default value, "Cluster", uses the standard + behavior of routing to all endpoints evenly + (possibly modified by topology and other + features). Note that traffic sent to an + External IP or LoadBalancer IP from within + the cluster will always get "Cluster" semantics, + but clients sending to a NodePort from within + the cluster may need to take traffic policy + into account when picking a node. + type: string + internalTrafficPolicy: + description: InternalTrafficPolicy describes + how nodes distribute service traffic they + receive on the ClusterIP. If set to "Local", + the proxy will assume that pods only want + to talk to endpoints of the service on the + same node as the pod, dropping the traffic + if there are no local endpoints. The default + value, "Cluster", uses the standard behavior + of routing to all endpoints evenly (possibly + modified by topology and other features). + type: string + ipFamilyPolicy: + description: IPFamilyPolicy represents the + dual-stack-ness requested or required by + this Service. If there is no value provided, + then this field will be set to SingleStack. + Services can be "SingleStack" (a single + IP family), "PreferDualStack" (two IP families + on dual-stack configured clusters or a single + IP family on single-stack clusters), or + "RequireDualStack" (two IP families on dual-stack + configured clusters, otherwise fail). The + ipFamilies and clusterIPs fields depend + on the value of this field. This field will + be wiped when updating a service to type + ExternalName. + type: string + loadBalancerClass: + description: loadBalancerClass is the class + of the load balancer implementation this + Service belongs to. If specified, the value + of this field must be a label-style identifier, + with an optional prefix, e.g. "internal-vip" + or "example.com/internal-vip". Unprefixed + names are reserved for end-users. This field + can only be set when the Service type is + 'LoadBalancer'. If not set, the default + load balancer implementation is used, today + this is typically done through the cloud + provider integration, but should apply for + any default implementation. If set, it is + assumed that a load balancer implementation + is watching for Services with a matching + class. Any default load balancer implementation + (e.g. cloud providers) should ignore Services + that set this field. This field can only + be set when creating or updating a Service + to type 'LoadBalancer'. Once set, it can + not be changed. This field will be wiped + when a service is updated to a non 'LoadBalancer' + type. + type: string + loadBalancerSourceRanges: + description: 'If specified and supported by + the platform, this will restrict traffic + through the cloud-provider load-balancer + will be restricted to the specified client + IPs. This field will be ignored if the cloud-provider + does not support the feature." More info: + https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/' + items: + type: string + type: array + sessionAffinity: + description: 'Supports "ClientIP" and "None". + Used to maintain session affinity. Enable + client IP based session affinity. Must be + ClientIP or None. Defaults to None. More + info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies' + type: string + sessionAffinityConfig: + description: sessionAffinityConfig contains + the configurations of session affinity. + properties: + clientIP: + description: clientIP contains the configurations + of Client IP based session affinity. + properties: + timeoutSeconds: + description: timeoutSeconds specifies + the seconds of ClientIP type session + sticky time. The value must be >0 + && <=86400(for 1 day) if ServiceAffinity + == "ClientIP". Default value is + 10800(for 3 hours). + format: int32 + type: integer + type: object + type: object + type: + description: 'type determines how the Service + is exposed. Defaults to ClusterIP. Valid + options are ExternalName, ClusterIP, NodePort, + and LoadBalancer. "ClusterIP" allocates + a cluster-internal IP address for load-balancing + to endpoints. Endpoints are determined by + the selector or if that is not specified, + by manual construction of an Endpoints object + or EndpointSlice objects. If clusterIP is + "None", no virtual IP is allocated and the + endpoints are published as a set of endpoints + rather than a virtual IP. "NodePort" builds + on ClusterIP and allocates a port on every + node which routes to the same endpoints + as the clusterIP. "LoadBalancer" builds + on NodePort and creates an external load-balancer + (if supported in the current cloud) which + routes to the same endpoints as the clusterIP. + "ExternalName" aliases this service to the + specified externalName. Several other fields + do not apply to ExternalName services. More + info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types' + type: string + type: object + type: object + type: object + passwordSelector: + default: + aodhService: AodhPassword + database: AodhDatabasePassword + description: PasswordSelectors - Selectors to identify + the service from the Secret + properties: + aodhService: + default: AodhPassword + description: AodhService - Selector to get the aodh + service password from the Secret + type: string + database: + default: AodhDatabasePassword + description: Database - Selector to get the aodh database + user password from the Secret + type: string + service: + default: CeilometerPassword + description: Service - Selector to get the ceilometer + service password from the Secret + type: string + type: object + preserveJobs: + default: false + description: PreserveJobs - do not delete jobs after they + finished e.g. to check logs + type: boolean + rabbitMqClusterName: + default: rabbitmq + description: RabbitMQ instance name Needed to request + a transportURL that is created and used in Aodh + type: string + secret: + description: Secret containing OpenStack password information + for aodh + type: string + serviceUser: + default: aodh + description: ServiceUser - optional username used for + this service to register in keystone + type: string + required: + - apiImage + - databaseInstance + - evaluatorImage + - listenerImage + - memcachedInstance + - notifierImage + - secret + type: object + heatInstance: + default: heat + description: Heat instance name. + type: string + prometheus: + description: Specification of which prometheus to use for + autoscaling + properties: + deployPrometheus: + default: false + description: Enables the deployment of autoscaling prometheus + type: boolean + host: + description: Host of user deployed prometheus if deployPrometheus + is set to false + type: string + port: + description: Port of user deployed prometheus if deployPrometheus + is set to false + format: int32 + maximum: 65535 + minimum: 1 + type: integer + type: object + required: + - heatInstance + type: object + type: object + ceilometer: + description: Ceilometer - Parameters related to the ceilometer service + properties: + enabled: + default: true + description: Enabled - Whether OpenStack Ceilometer service should + be deployed and managed + type: boolean + template: + description: Template - Overrides to use when creating the OpenStack + Ceilometer service + properties: + centralImage: + type: string + computeImage: type: string customServiceConfig: default: '# add your customization here' @@ -52,16 +391,6 @@ spec: The content gets added to to /etc//.conf.d directory as custom.conf file. type: string - databaseInstance: - description: MariaDB instance name Right now required by the - maridb-operator to get the credentials from the instance - to create the DB Might not be required in future - type: string - databaseUser: - default: aodh - description: Database user name Needed to connect to a database - used by aodh - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -70,13 +399,7 @@ spec: can also be used to add additional files. Those get added to the service config dir in /etc/ . TODO: -> implement' type: object - evaluatorImage: - type: string - listenerImage: - type: string - memcachedInstance: - default: memcached - description: Memcached instance name. + ipmiImage: type: string networkAttachmentDefinitions: description: NetworkAttachmentDefinitions list of network @@ -84,193 +407,13 @@ spec: items: type: string type: array - notifierImage: + nodeExporterImage: + type: string + notificationImage: type: string - override: - description: Override, provides the ability to override the - generated manifest of several child resources. - properties: - service: - description: Override configuration for the Service created - to serve traffic to the cluster. - properties: - endpointURL: - type: string - metadata: - description: EmbeddedLabelsAnnotations is an embedded - subset of the fields included in k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta. - Only labels and annotations are included. - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key - value map stored with a resource that may be - set by external tools to store and retrieve - arbitrary metadata. They are not queryable and - should be preserved when modifying objects. - More info: http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values that - can be used to organize and categorize (scope - and select) objects. May match selectors of - replication controllers and services. More info: - http://kubernetes.io/docs/user-guide/labels' - type: object - type: object - spec: - description: OverrideServiceSpec is a subset of the - fields included in https://pkg.go.dev/k8s.io/api@v0.26.6/core/v1#ServiceSpec - Limited to Type, SessionAffinity, LoadBalancerSourceRanges, - ExternalName, ExternalTrafficPolicy, SessionAffinityConfig, - IPFamilyPolicy, LoadBalancerClass and InternalTrafficPolicy - properties: - externalName: - description: externalName is the external reference - that discovery mechanisms will return as an - alias for this service (e.g. a DNS CNAME record). - No proxying will be involved. Must be a lowercase - RFC-1123 hostname (https://tools.ietf.org/html/rfc1123) - and requires `type` to be "ExternalName". - type: string - externalTrafficPolicy: - description: externalTrafficPolicy describes how - nodes distribute service traffic they receive - on one of the Service's "externally-facing" - addresses (NodePorts, ExternalIPs, and LoadBalancer - IPs). If set to "Local", the proxy will configure - the service in a way that assumes that external - load balancers will take care of balancing the - service traffic between nodes, and so each node - will deliver traffic only to the node-local - endpoints of the service, without masquerading - the client source IP. (Traffic mistakenly sent - to a node with no endpoints will be dropped.) - The default value, "Cluster", uses the standard - behavior of routing to all endpoints evenly - (possibly modified by topology and other features). - Note that traffic sent to an External IP or - LoadBalancer IP from within the cluster will - always get "Cluster" semantics, but clients - sending to a NodePort from within the cluster - may need to take traffic policy into account - when picking a node. - type: string - internalTrafficPolicy: - description: InternalTrafficPolicy describes how - nodes distribute service traffic they receive - on the ClusterIP. If set to "Local", the proxy - will assume that pods only want to talk to endpoints - of the service on the same node as the pod, - dropping the traffic if there are no local endpoints. - The default value, "Cluster", uses the standard - behavior of routing to all endpoints evenly - (possibly modified by topology and other features). - type: string - ipFamilyPolicy: - description: IPFamilyPolicy represents the dual-stack-ness - requested or required by this Service. If there - is no value provided, then this field will be - set to SingleStack. Services can be "SingleStack" - (a single IP family), "PreferDualStack" (two - IP families on dual-stack configured clusters - or a single IP family on single-stack clusters), - or "RequireDualStack" (two IP families on dual-stack - configured clusters, otherwise fail). The ipFamilies - and clusterIPs fields depend on the value of - this field. This field will be wiped when updating - a service to type ExternalName. - type: string - loadBalancerClass: - description: loadBalancerClass is the class of - the load balancer implementation this Service - belongs to. If specified, the value of this - field must be a label-style identifier, with - an optional prefix, e.g. "internal-vip" or "example.com/internal-vip". - Unprefixed names are reserved for end-users. - This field can only be set when the Service - type is 'LoadBalancer'. If not set, the default - load balancer implementation is used, today - this is typically done through the cloud provider - integration, but should apply for any default - implementation. If set, it is assumed that a - load balancer implementation is watching for - Services with a matching class. Any default - load balancer implementation (e.g. cloud providers) - should ignore Services that set this field. - This field can only be set when creating or - updating a Service to type 'LoadBalancer'. Once - set, it can not be changed. This field will - be wiped when a service is updated to a non - 'LoadBalancer' type. - type: string - loadBalancerSourceRanges: - description: 'If specified and supported by the - platform, this will restrict traffic through - the cloud-provider load-balancer will be restricted - to the specified client IPs. This field will - be ignored if the cloud-provider does not support - the feature." More info: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/' - items: - type: string - type: array - sessionAffinity: - description: 'Supports "ClientIP" and "None". - Used to maintain session affinity. Enable client - IP based session affinity. Must be ClientIP - or None. Defaults to None. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies' - type: string - sessionAffinityConfig: - description: sessionAffinityConfig contains the - configurations of session affinity. - properties: - clientIP: - description: clientIP contains the configurations - of Client IP based session affinity. - properties: - timeoutSeconds: - description: timeoutSeconds specifies - the seconds of ClientIP type session - sticky time. The value must be >0 && - <=86400(for 1 day) if ServiceAffinity - == "ClientIP". Default value is 10800(for - 3 hours). - format: int32 - type: integer - type: object - type: object - type: - description: 'type determines how the Service - is exposed. Defaults to ClusterIP. Valid options - are ExternalName, ClusterIP, NodePort, and LoadBalancer. - "ClusterIP" allocates a cluster-internal IP - address for load-balancing to endpoints. Endpoints - are determined by the selector or if that is - not specified, by manual construction of an - Endpoints object or EndpointSlice objects. If - clusterIP is "None", no virtual IP is allocated - and the endpoints are published as a set of - endpoints rather than a virtual IP. "NodePort" - builds on ClusterIP and allocates a port on - every node which routes to the same endpoints - as the clusterIP. "LoadBalancer" builds on NodePort - and creates an external load-balancer (if supported - in the current cloud) which routes to the same - endpoints as the clusterIP. "ExternalName" aliases - this service to the specified externalName. - Several other fields do not apply to ExternalName - services. More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types' - type: string - type: object - type: object - type: object passwordSelector: default: - aodhService: AodhPassword - database: AodhDatabasePassword + service: CeilometerPassword description: PasswordSelectors - Selectors to identify the service from the Secret properties: @@ -290,146 +433,38 @@ spec: service password from the Secret type: string type: object - preserveJobs: - default: false - description: PreserveJobs - do not delete jobs after they - finished e.g. to check logs - type: boolean rabbitMqClusterName: default: rabbitmq description: RabbitMQ instance name Needed to request a transportURL - that is created and used in Aodh + that is created and used in Telemetry type: string secret: description: Secret containing OpenStack password information - for aodh + for ceilometer type: string serviceUser: - default: aodh + default: ceilometer description: ServiceUser - optional username used for this service to register in keystone type: string + sgCoreImage: + type: string required: - - apiImage - - databaseInstance - - evaluatorImage - - listenerImage - - memcachedInstance - - notifierImage + - centralImage + - computeImage + - ipmiImage + - nodeExporterImage + - notificationImage - secret + - sgCoreImage type: object - heatInstance: - default: heat - description: Heat instance name. - type: string - prometheus: - description: Specification of which prometheus to use for autoscaling - properties: - deployPrometheus: - default: false - description: Enables the deployment of autoscaling prometheus - type: boolean - host: - description: Host of user deployed prometheus if deployPrometheus - is set to false - type: string - port: - description: Port of user deployed prometheus if deployPrometheus - is set to false - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - required: - - heatInstance - type: object - ceilometer: - description: Ceilometer - Spec definition for the Ceilometer service - of this Telemetry deployment - properties: - centralImage: - type: string - computeImage: - type: string - customServiceConfig: - default: '# add your customization here' - description: CustomServiceConfig - customize the service config - using this parameter to change service defaults, or overwrite - rendered information using raw OpenStack config format. The - content gets added to to /etc//.conf.d directory - as custom.conf file. - type: string - defaultConfigOverwrite: - additionalProperties: - type: string - description: 'ConfigOverwrite - interface to overwrite default - config files like e.g. logging.conf or policy.json. But can - also be used to add additional files. Those get added to the - service config dir in /etc/ . TODO: -> implement' - type: object - ipmiImage: - type: string - networkAttachmentDefinitions: - description: NetworkAttachmentDefinitions list of network attachment - definitions the service pod gets attached to - items: - type: string - type: array - nodeExporterImage: - type: string - notificationImage: - type: string - passwordSelector: - default: - service: CeilometerPassword - description: PasswordSelectors - Selectors to identify the service - from the Secret - properties: - aodhService: - default: AodhPassword - description: AodhService - Selector to get the aodh service - password from the Secret - type: string - database: - default: AodhDatabasePassword - description: Database - Selector to get the aodh database - user password from the Secret - type: string - service: - default: CeilometerPassword - description: Service - Selector to get the ceilometer service - password from the Secret - type: string - type: object - rabbitMqClusterName: - default: rabbitmq - description: RabbitMQ instance name Needed to request a transportURL - that is created and used in Telemetry - type: string - secret: - description: Secret containing OpenStack password information - for ceilometer - type: string - serviceUser: - default: ceilometer - description: ServiceUser - optional username used for this service - to register in keystone - type: string - sgCoreImage: - type: string - required: - - centralImage - - computeImage - - ipmiImage - - nodeExporterImage - - notificationImage - - secret - - sgCoreImage type: object + secret: + description: Secret containing OpenStack password information for + telemetry services + type: string required: - - autoscaling - - ceilometer + - secret type: object status: description: TelemetryStatus defines the observed state of Telemetry diff --git a/config/samples/telemetry_v1beta1_telemetry.yaml b/config/samples/telemetry_v1beta1_telemetry.yaml index 53769c06..28d8c16c 100644 --- a/config/samples/telemetry_v1beta1_telemetry.yaml +++ b/config/samples/telemetry_v1beta1_telemetry.yaml @@ -2,8 +2,21 @@ apiVersion: telemetry.openstack.org/v1beta1 kind: Telemetry metadata: name: telemetry - namespace: openstack spec: autoscaling: - prometheus: - deployPrometheus: false + enabled: false + template: + prometheus: + deployPrometheus: true + aodh: + secret: osp-secret + passwordSelectors: + databaseUser: aodh + databaseInstance: openstack + memcachedInstance: memcached + heatInstance: heat + ceilometer: + enabled: true + template: + secret: osp-secret + secret: osp-secret diff --git a/controllers/telemetry_controller.go b/controllers/telemetry_controller.go index 6cf93bab..c15e56e8 100644 --- a/controllers/telemetry_controller.go +++ b/controllers/telemetry_controller.go @@ -35,6 +35,7 @@ import ( "k8s.io/client-go/kubernetes" telemetryv1 "github.com/openstack-k8s-operators/telemetry-operator/api/v1beta1" + ceilometer "github.com/openstack-k8s-operators/telemetry-operator/pkg/ceilometer" telemetry "github.com/openstack-k8s-operators/telemetry-operator/pkg/telemetry" ) @@ -186,98 +187,166 @@ func (r *TelemetryReconciler) reconcileNormal(ctx context.Context, instance *tel Log := r.GetLogger(ctx) Log.Info(fmt.Sprintf("Reconciling Service '%s'", instance.Name)) - // deploy autoscaling - autoscaling, op, err := r.autoscalingCreateOrUpdate(instance) + ctrlResult, err := reconcileAutoscaling(ctx, instance, helper) if err != nil { - instance.Status.Conditions.Set(condition.FalseCondition( - telemetryv1.AutoscalingReadyCondition, - condition.ErrorReason, - condition.SeverityWarning, - telemetryv1.AutoscalingReadyErrorMessage, - err.Error())) return ctrl.Result{}, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil } - if op != controllerutil.OperationResultNone { - Log.Info(fmt.Sprintf("Deployment %s successfully reconciled - operation: %s", instance.Name, string(op))) - } - // Mirror autoscaling's condition status - as := autoscaling.Status.Conditions.Mirror(telemetryv1.AutoscalingReadyCondition) - if as != nil { - instance.Status.Conditions.Set(as) - } - // end deploy autoscaling - // deploy ceilometer - ceilometer, op, err := r.ceilometerCreateOrUpdate(instance) + ctrlResult, err = reconcileCeilometer(ctx, instance, helper) if err != nil { - instance.Status.Conditions.Set(condition.FalseCondition( - telemetryv1.CeilometerReadyCondition, - condition.ErrorReason, - condition.SeverityWarning, - telemetryv1.CeilometerReadyErrorMessage, - err.Error())) return ctrl.Result{}, err - } - if op != controllerutil.OperationResultNone { - Log.Info(fmt.Sprintf("Deployment %s successfully reconciled - operation: %s", instance.Name, string(op))) + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil } - // Mirror ceilometer's status ReadyCount to this parent CR - instance.Status.CeilometerReadyCount = ceilometer.Status.ReadyCount + Log.Info("Reconciled Service successfully") + return ctrl.Result{}, nil +} - // Mirror ceilometer's condition status - ccentral := ceilometer.Status.Conditions.Mirror(telemetryv1.CeilometerReadyCondition) - if ccentral != nil { - instance.Status.Conditions.Set(ccentral) +// ensureDeleted - Delete the object which in turn will clean the sub resources +func ensureDeleted(ctx context.Context, helper *helper.Helper, obj client.Object) (ctrl.Result, error) { + key := client.ObjectKeyFromObject(obj) + if err := helper.GetClient().Get(ctx, key, obj); err != nil { + if k8s_errors.IsNotFound(err) { + return ctrl.Result{}, nil + } + return ctrl.Result{}, err + } + // Delete the object + if obj.GetDeletionTimestamp().IsZero() { + if err := helper.GetClient().Delete(ctx, obj); err != nil { + return ctrl.Result{}, err + } } - // end deploy ceilometer - - Log.Info("Reconciled Service successfully") return ctrl.Result{}, nil + } -func (r *TelemetryReconciler) autoscalingCreateOrUpdate(instance *telemetryv1.Telemetry) (*telemetryv1.Autoscaling, controllerutil.OperationResult, error) { - autoscaling := &telemetryv1.Autoscaling{ +// reconcileCeilometer ... +func reconcileCeilometer(ctx context.Context, instance *telemetryv1.Telemetry, helper *helper.Helper) (ctrl.Result, error) { + const ( + ceilometerNamespaceLabel = "Ceilometer.Namespace" + ceilometerNameLabel = "Ceilometer.Name" + ) + ceilometerInstance := &telemetryv1.Ceilometer{ ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-autoscaling", instance.Name), + Name: ceilometer.ServiceName, Namespace: instance.Namespace, }, } - op, err := controllerutil.CreateOrUpdate(context.TODO(), r.Client, autoscaling, func() error { - autoscaling.Spec = instance.Spec.Autoscaling + if !instance.Spec.Ceilometer.Enabled { + if res, err := ensureDeleted(ctx, helper, ceilometerInstance); err != nil { + return res, err + } + instance.Status.Conditions.Remove(telemetryv1.CeilometerReadyCondition) + return ctrl.Result{}, nil + } + + helper.GetLogger().Info("Reconciling Ceilometer", ceilometerNamespaceLabel, instance.Namespace, ceilometerNameLabel, ceilometer.ServiceName) + op, err := controllerutil.CreateOrPatch(ctx, helper.GetClient(), ceilometerInstance, func() error { + instance.Spec.Ceilometer.Template.DeepCopyInto(&ceilometerInstance.Spec) + + if ceilometerInstance.Spec.Secret == "" { + ceilometerInstance.Spec.Secret = instance.Spec.Secret + } - err := controllerutil.SetControllerReference(instance, autoscaling, r.Scheme) + err := controllerutil.SetControllerReference(helper.GetBeforeObject(), ceilometerInstance, helper.GetScheme()) if err != nil { return err } - return nil }) - return autoscaling, op, err + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + telemetryv1.CeilometerReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + telemetryv1.CeilometerReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } + if op != controllerutil.OperationResultNone { + helper.GetLogger().Info(fmt.Sprintf("%s %s - %s", ceilometer.ServiceName, ceilometerInstance.Name, op)) + } + + if ceilometerInstance.IsReady() { + instance.Status.Conditions.MarkTrue(telemetryv1.CeilometerReadyCondition, telemetryv1.CeilometerReadyMessage) + } else { + instance.Status.Conditions.Set(condition.FalseCondition( + telemetryv1.CeilometerReadyCondition, + condition.RequestedReason, + condition.SeverityInfo, + telemetryv1.CeilometerReadyRunningMessage)) + } + + return ctrl.Result{}, nil } -func (r *TelemetryReconciler) ceilometerCreateOrUpdate(instance *telemetryv1.Telemetry) (*telemetryv1.Ceilometer, controllerutil.OperationResult, error) { - ccentral := &telemetryv1.Ceilometer{ +// reconcileAutoscaling ... +func reconcileAutoscaling(ctx context.Context, instance *telemetryv1.Telemetry, helper *helper.Helper) (ctrl.Result, error) { + const ( + autoscalingNamespaceLabel = "Autoscaling.Namespace" + autoscalingNameLabel = "Autoscaling.Name" + autoscalingName = "autoscaling" + ) + autoscalingInstance := &telemetryv1.Autoscaling{ ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-ceilometer-central", instance.Name), + Name: autoscalingName, Namespace: instance.Namespace, }, } - op, err := controllerutil.CreateOrUpdate(context.TODO(), r.Client, ccentral, func() error { - ccentral.Spec = instance.Spec.Ceilometer + if !instance.Spec.Autoscaling.Enabled { + if res, err := ensureDeleted(ctx, helper, autoscalingInstance); err != nil { + return res, err + } + instance.Status.Conditions.Remove(telemetryv1.AutoscalingReadyCondition) + return ctrl.Result{}, nil + } + + helper.GetLogger().Info("Reconciling Autoscaling", autoscalingNamespaceLabel, instance.Namespace, autoscalingNameLabel, autoscalingName) + op, err := controllerutil.CreateOrPatch(ctx, helper.GetClient(), autoscalingInstance, func() error { + instance.Spec.Autoscaling.Template.DeepCopyInto(&autoscalingInstance.Spec) - err := controllerutil.SetControllerReference(instance, ccentral, r.Scheme) + if autoscalingInstance.Spec.Aodh.Secret == "" { + autoscalingInstance.Spec.Aodh.Secret = instance.Spec.Secret + } + + err := controllerutil.SetControllerReference(helper.GetBeforeObject(), autoscalingInstance, helper.GetScheme()) if err != nil { return err } - return nil }) - return ccentral, op, err + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + telemetryv1.AutoscalingReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + telemetryv1.AutoscalingReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } + if op != controllerutil.OperationResultNone { + helper.GetLogger().Info(fmt.Sprintf("%s %s - %s", autoscalingName, autoscalingInstance.Name, op)) + } + + if autoscalingInstance.IsReady() { + instance.Status.Conditions.MarkTrue(telemetryv1.AutoscalingReadyCondition, telemetryv1.AutoscalingReadyMessage) + } else { + instance.Status.Conditions.Set(condition.FalseCondition( + telemetryv1.AutoscalingReadyCondition, + condition.RequestedReason, + condition.SeverityInfo, + telemetryv1.AutoscalingReadyRunningMessage)) + } + + return ctrl.Result{}, nil } // SetupWithManager sets up the controller with the Manager. diff --git a/tests/kuttl/suites/default/tests/01-deploy.yaml b/tests/kuttl/suites/default/tests/01-deploy.yaml index 2f6f82da..cff4b9ff 100644 --- a/tests/kuttl/suites/default/tests/01-deploy.yaml +++ b/tests/kuttl/suites/default/tests/01-deploy.yaml @@ -4,18 +4,22 @@ metadata: name: telemetry spec: autoscaling: - prometheus: - deployPrometheus: true - aodh: - secret: osp-secret - apiImage: "quay.io/mmagr/openstack-aodh-api:current-podified" - evaluatorImage: "quay.io/mmagr/openstack-aodh-evaluator:current-podified" - notifierImage: "quay.io/mmagr/openstack-aodh-notifier:current-podified" - listenerImage: "quay.io/mmagr/openstack-aodh-listener:current-podified" - passwordSelectors: - databaseUser: aodh - databaseInstance: openstack - memcachedInstance: memcached - heatInstance: heat + enabled: true + template: + prometheus: + deployPrometheus: true + aodh: + secret: osp-secret + apiImage: "quay.io/mmagr/openstack-aodh-api:current-podified" + evaluatorImage: "quay.io/mmagr/openstack-aodh-evaluator:current-podified" + notifierImage: "quay.io/mmagr/openstack-aodh-notifier:current-podified" + listenerImage: "quay.io/mmagr/openstack-aodh-listener:current-podified" + passwordSelectors: + databaseUser: aodh + databaseInstance: openstack + memcachedInstance: memcached + heatInstance: heat ceilometer: - secret: osp-secret + enabled: true + template: + secret: osp-secret From d564042050c48cd34322738cc48b05e4eaa5a90c Mon Sep 17 00:00:00 2001 From: Jaromir Wysoglad Date: Tue, 21 Nov 2023 02:43:28 -0500 Subject: [PATCH 2/3] Remove "template" from telemetry CRD --- .../telemetry.openstack.org_telemetries.yaml | 694 +++++++++--------- api/v1beta1/telemetry_types.go | 4 +- api/v1beta1/telemetry_webhook.go | 40 +- api/v1beta1/zz_generated.deepcopy.go | 4 +- .../telemetry.openstack.org_telemetries.yaml | 694 +++++++++--------- .../samples/telemetry_v1beta1_telemetry.yaml | 20 +- controllers/telemetry_controller.go | 4 +- .../kuttl/suites/default/tests/01-deploy.yaml | 30 +- 8 files changed, 718 insertions(+), 772 deletions(-) diff --git a/api/bases/telemetry.openstack.org_telemetries.yaml b/api/bases/telemetry.openstack.org_telemetries.yaml index 578c8b03..8f834aa4 100644 --- a/api/bases/telemetry.openstack.org_telemetries.yaml +++ b/api/bases/telemetry.openstack.org_telemetries.yaml @@ -38,350 +38,10 @@ spec: autoscaling: description: Autoscaling - Parameters related to the autoscaling service properties: - enabled: - default: false - description: Enabled - Whether OpenStack autoscaling service should - be deployed and managed - type: boolean - template: - description: Template - Overrides to use when creating the OpenStack - autoscaling service - properties: - aodh: - description: Aodh spec - properties: - apiImage: - type: string - customServiceConfig: - default: '# add your customization here' - description: CustomServiceConfig - customize the service - config using this parameter to change service defaults, - or overwrite rendered information using raw OpenStack - config format. The content gets added to to /etc//.conf.d - directory as custom.conf file. - type: string - databaseInstance: - description: MariaDB instance name Right now required - by the maridb-operator to get the credentials from the - instance to create the DB Might not be required in future - type: string - databaseUser: - default: aodh - description: Database user name Needed to connect to a - database used by aodh - type: string - defaultConfigOverwrite: - additionalProperties: - type: string - description: 'ConfigOverwrite - interface to overwrite - default config files like e.g. logging.conf or policy.json. - But can also be used to add additional files. Those - get added to the service config dir in /etc/ - . TODO: -> implement' - type: object - evaluatorImage: - type: string - listenerImage: - type: string - memcachedInstance: - default: memcached - description: Memcached instance name. - type: string - networkAttachmentDefinitions: - description: NetworkAttachmentDefinitions list of network - attachment definitions the service pod gets attached - to - items: - type: string - type: array - notifierImage: - type: string - override: - description: Override, provides the ability to override - the generated manifest of several child resources. - properties: - service: - description: Override configuration for the Service - created to serve traffic to the cluster. - properties: - endpointURL: - type: string - metadata: - description: EmbeddedLabelsAnnotations is an embedded - subset of the fields included in k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta. - Only labels and annotations are included. - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured - key value map stored with a resource that - may be set by external tools to store and - retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying - objects. More info: http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values - that can be used to organize and categorize - (scope and select) objects. May match selectors - of replication controllers and services. - More info: http://kubernetes.io/docs/user-guide/labels' - type: object - type: object - spec: - description: OverrideServiceSpec is a subset of - the fields included in https://pkg.go.dev/k8s.io/api@v0.26.6/core/v1#ServiceSpec - Limited to Type, SessionAffinity, LoadBalancerSourceRanges, - ExternalName, ExternalTrafficPolicy, SessionAffinityConfig, - IPFamilyPolicy, LoadBalancerClass and InternalTrafficPolicy - properties: - externalName: - description: externalName is the external - reference that discovery mechanisms will - return as an alias for this service (e.g. - a DNS CNAME record). No proxying will be - involved. Must be a lowercase RFC-1123 - hostname (https://tools.ietf.org/html/rfc1123) - and requires `type` to be "ExternalName". - type: string - externalTrafficPolicy: - description: externalTrafficPolicy describes - how nodes distribute service traffic they - receive on one of the Service's "externally-facing" - addresses (NodePorts, ExternalIPs, and LoadBalancer - IPs). If set to "Local", the proxy will - configure the service in a way that assumes - that external load balancers will take care - of balancing the service traffic between - nodes, and so each node will deliver traffic - only to the node-local endpoints of the - service, without masquerading the client - source IP. (Traffic mistakenly sent to a - node with no endpoints will be dropped.) - The default value, "Cluster", uses the standard - behavior of routing to all endpoints evenly - (possibly modified by topology and other - features). Note that traffic sent to an - External IP or LoadBalancer IP from within - the cluster will always get "Cluster" semantics, - but clients sending to a NodePort from within - the cluster may need to take traffic policy - into account when picking a node. - type: string - internalTrafficPolicy: - description: InternalTrafficPolicy describes - how nodes distribute service traffic they - receive on the ClusterIP. If set to "Local", - the proxy will assume that pods only want - to talk to endpoints of the service on the - same node as the pod, dropping the traffic - if there are no local endpoints. The default - value, "Cluster", uses the standard behavior - of routing to all endpoints evenly (possibly - modified by topology and other features). - type: string - ipFamilyPolicy: - description: IPFamilyPolicy represents the - dual-stack-ness requested or required by - this Service. If there is no value provided, - then this field will be set to SingleStack. - Services can be "SingleStack" (a single - IP family), "PreferDualStack" (two IP families - on dual-stack configured clusters or a single - IP family on single-stack clusters), or - "RequireDualStack" (two IP families on dual-stack - configured clusters, otherwise fail). The - ipFamilies and clusterIPs fields depend - on the value of this field. This field will - be wiped when updating a service to type - ExternalName. - type: string - loadBalancerClass: - description: loadBalancerClass is the class - of the load balancer implementation this - Service belongs to. If specified, the value - of this field must be a label-style identifier, - with an optional prefix, e.g. "internal-vip" - or "example.com/internal-vip". Unprefixed - names are reserved for end-users. This field - can only be set when the Service type is - 'LoadBalancer'. If not set, the default - load balancer implementation is used, today - this is typically done through the cloud - provider integration, but should apply for - any default implementation. If set, it is - assumed that a load balancer implementation - is watching for Services with a matching - class. Any default load balancer implementation - (e.g. cloud providers) should ignore Services - that set this field. This field can only - be set when creating or updating a Service - to type 'LoadBalancer'. Once set, it can - not be changed. This field will be wiped - when a service is updated to a non 'LoadBalancer' - type. - type: string - loadBalancerSourceRanges: - description: 'If specified and supported by - the platform, this will restrict traffic - through the cloud-provider load-balancer - will be restricted to the specified client - IPs. This field will be ignored if the cloud-provider - does not support the feature." More info: - https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/' - items: - type: string - type: array - sessionAffinity: - description: 'Supports "ClientIP" and "None". - Used to maintain session affinity. Enable - client IP based session affinity. Must be - ClientIP or None. Defaults to None. More - info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies' - type: string - sessionAffinityConfig: - description: sessionAffinityConfig contains - the configurations of session affinity. - properties: - clientIP: - description: clientIP contains the configurations - of Client IP based session affinity. - properties: - timeoutSeconds: - description: timeoutSeconds specifies - the seconds of ClientIP type session - sticky time. The value must be >0 - && <=86400(for 1 day) if ServiceAffinity - == "ClientIP". Default value is - 10800(for 3 hours). - format: int32 - type: integer - type: object - type: object - type: - description: 'type determines how the Service - is exposed. Defaults to ClusterIP. Valid - options are ExternalName, ClusterIP, NodePort, - and LoadBalancer. "ClusterIP" allocates - a cluster-internal IP address for load-balancing - to endpoints. Endpoints are determined by - the selector or if that is not specified, - by manual construction of an Endpoints object - or EndpointSlice objects. If clusterIP is - "None", no virtual IP is allocated and the - endpoints are published as a set of endpoints - rather than a virtual IP. "NodePort" builds - on ClusterIP and allocates a port on every - node which routes to the same endpoints - as the clusterIP. "LoadBalancer" builds - on NodePort and creates an external load-balancer - (if supported in the current cloud) which - routes to the same endpoints as the clusterIP. - "ExternalName" aliases this service to the - specified externalName. Several other fields - do not apply to ExternalName services. More - info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types' - type: string - type: object - type: object - type: object - passwordSelector: - default: - aodhService: AodhPassword - database: AodhDatabasePassword - description: PasswordSelectors - Selectors to identify - the service from the Secret - properties: - aodhService: - default: AodhPassword - description: AodhService - Selector to get the aodh - service password from the Secret - type: string - database: - default: AodhDatabasePassword - description: Database - Selector to get the aodh database - user password from the Secret - type: string - service: - default: CeilometerPassword - description: Service - Selector to get the ceilometer - service password from the Secret - type: string - type: object - preserveJobs: - default: false - description: PreserveJobs - do not delete jobs after they - finished e.g. to check logs - type: boolean - rabbitMqClusterName: - default: rabbitmq - description: RabbitMQ instance name Needed to request - a transportURL that is created and used in Aodh - type: string - secret: - description: Secret containing OpenStack password information - for aodh - type: string - serviceUser: - default: aodh - description: ServiceUser - optional username used for - this service to register in keystone - type: string - required: - - apiImage - - databaseInstance - - evaluatorImage - - listenerImage - - memcachedInstance - - notifierImage - - secret - type: object - heatInstance: - default: heat - description: Heat instance name. - type: string - prometheus: - description: Specification of which prometheus to use for - autoscaling - properties: - deployPrometheus: - default: false - description: Enables the deployment of autoscaling prometheus - type: boolean - host: - description: Host of user deployed prometheus if deployPrometheus - is set to false - type: string - port: - description: Port of user deployed prometheus if deployPrometheus - is set to false - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - required: - - heatInstance - type: object - type: object - ceilometer: - description: Ceilometer - Parameters related to the ceilometer service - properties: - enabled: - default: true - description: Enabled - Whether OpenStack Ceilometer service should - be deployed and managed - type: boolean - template: - description: Template - Overrides to use when creating the OpenStack - Ceilometer service + aodh: + description: Aodh spec properties: - centralImage: - type: string - computeImage: + apiImage: type: string customServiceConfig: default: '# add your customization here' @@ -391,6 +51,16 @@ spec: The content gets added to to /etc//.conf.d directory as custom.conf file. type: string + databaseInstance: + description: MariaDB instance name Right now required by the + maridb-operator to get the credentials from the instance + to create the DB Might not be required in future + type: string + databaseUser: + default: aodh + description: Database user name Needed to connect to a database + used by aodh + type: string defaultConfigOverwrite: additionalProperties: type: string @@ -399,7 +69,13 @@ spec: can also be used to add additional files. Those get added to the service config dir in /etc/ . TODO: -> implement' type: object - ipmiImage: + evaluatorImage: + type: string + listenerImage: + type: string + memcachedInstance: + default: memcached + description: Memcached instance name. type: string networkAttachmentDefinitions: description: NetworkAttachmentDefinitions list of network @@ -407,13 +83,193 @@ spec: items: type: string type: array - nodeExporterImage: - type: string - notificationImage: + notifierImage: type: string + override: + description: Override, provides the ability to override the + generated manifest of several child resources. + properties: + service: + description: Override configuration for the Service created + to serve traffic to the cluster. + properties: + endpointURL: + type: string + metadata: + description: EmbeddedLabelsAnnotations is an embedded + subset of the fields included in k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta. + Only labels and annotations are included. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key + value map stored with a resource that may be + set by external tools to store and retrieve + arbitrary metadata. They are not queryable and + should be preserved when modifying objects. + More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values that + can be used to organize and categorize (scope + and select) objects. May match selectors of + replication controllers and services. More info: + http://kubernetes.io/docs/user-guide/labels' + type: object + type: object + spec: + description: OverrideServiceSpec is a subset of the + fields included in https://pkg.go.dev/k8s.io/api@v0.26.6/core/v1#ServiceSpec + Limited to Type, SessionAffinity, LoadBalancerSourceRanges, + ExternalName, ExternalTrafficPolicy, SessionAffinityConfig, + IPFamilyPolicy, LoadBalancerClass and InternalTrafficPolicy + properties: + externalName: + description: externalName is the external reference + that discovery mechanisms will return as an + alias for this service (e.g. a DNS CNAME record). + No proxying will be involved. Must be a lowercase + RFC-1123 hostname (https://tools.ietf.org/html/rfc1123) + and requires `type` to be "ExternalName". + type: string + externalTrafficPolicy: + description: externalTrafficPolicy describes how + nodes distribute service traffic they receive + on one of the Service's "externally-facing" + addresses (NodePorts, ExternalIPs, and LoadBalancer + IPs). If set to "Local", the proxy will configure + the service in a way that assumes that external + load balancers will take care of balancing the + service traffic between nodes, and so each node + will deliver traffic only to the node-local + endpoints of the service, without masquerading + the client source IP. (Traffic mistakenly sent + to a node with no endpoints will be dropped.) + The default value, "Cluster", uses the standard + behavior of routing to all endpoints evenly + (possibly modified by topology and other features). + Note that traffic sent to an External IP or + LoadBalancer IP from within the cluster will + always get "Cluster" semantics, but clients + sending to a NodePort from within the cluster + may need to take traffic policy into account + when picking a node. + type: string + internalTrafficPolicy: + description: InternalTrafficPolicy describes how + nodes distribute service traffic they receive + on the ClusterIP. If set to "Local", the proxy + will assume that pods only want to talk to endpoints + of the service on the same node as the pod, + dropping the traffic if there are no local endpoints. + The default value, "Cluster", uses the standard + behavior of routing to all endpoints evenly + (possibly modified by topology and other features). + type: string + ipFamilyPolicy: + description: IPFamilyPolicy represents the dual-stack-ness + requested or required by this Service. If there + is no value provided, then this field will be + set to SingleStack. Services can be "SingleStack" + (a single IP family), "PreferDualStack" (two + IP families on dual-stack configured clusters + or a single IP family on single-stack clusters), + or "RequireDualStack" (two IP families on dual-stack + configured clusters, otherwise fail). The ipFamilies + and clusterIPs fields depend on the value of + this field. This field will be wiped when updating + a service to type ExternalName. + type: string + loadBalancerClass: + description: loadBalancerClass is the class of + the load balancer implementation this Service + belongs to. If specified, the value of this + field must be a label-style identifier, with + an optional prefix, e.g. "internal-vip" or "example.com/internal-vip". + Unprefixed names are reserved for end-users. + This field can only be set when the Service + type is 'LoadBalancer'. If not set, the default + load balancer implementation is used, today + this is typically done through the cloud provider + integration, but should apply for any default + implementation. If set, it is assumed that a + load balancer implementation is watching for + Services with a matching class. Any default + load balancer implementation (e.g. cloud providers) + should ignore Services that set this field. + This field can only be set when creating or + updating a Service to type 'LoadBalancer'. Once + set, it can not be changed. This field will + be wiped when a service is updated to a non + 'LoadBalancer' type. + type: string + loadBalancerSourceRanges: + description: 'If specified and supported by the + platform, this will restrict traffic through + the cloud-provider load-balancer will be restricted + to the specified client IPs. This field will + be ignored if the cloud-provider does not support + the feature." More info: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/' + items: + type: string + type: array + sessionAffinity: + description: 'Supports "ClientIP" and "None". + Used to maintain session affinity. Enable client + IP based session affinity. Must be ClientIP + or None. Defaults to None. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies' + type: string + sessionAffinityConfig: + description: sessionAffinityConfig contains the + configurations of session affinity. + properties: + clientIP: + description: clientIP contains the configurations + of Client IP based session affinity. + properties: + timeoutSeconds: + description: timeoutSeconds specifies + the seconds of ClientIP type session + sticky time. The value must be >0 && + <=86400(for 1 day) if ServiceAffinity + == "ClientIP". Default value is 10800(for + 3 hours). + format: int32 + type: integer + type: object + type: object + type: + description: 'type determines how the Service + is exposed. Defaults to ClusterIP. Valid options + are ExternalName, ClusterIP, NodePort, and LoadBalancer. + "ClusterIP" allocates a cluster-internal IP + address for load-balancing to endpoints. Endpoints + are determined by the selector or if that is + not specified, by manual construction of an + Endpoints object or EndpointSlice objects. If + clusterIP is "None", no virtual IP is allocated + and the endpoints are published as a set of + endpoints rather than a virtual IP. "NodePort" + builds on ClusterIP and allocates a port on + every node which routes to the same endpoints + as the clusterIP. "LoadBalancer" builds on NodePort + and creates an external load-balancer (if supported + in the current cloud) which routes to the same + endpoints as the clusterIP. "ExternalName" aliases + this service to the specified externalName. + Several other fields do not apply to ExternalName + services. More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types' + type: string + type: object + type: object + type: object passwordSelector: default: - service: CeilometerPassword + aodhService: AodhPassword + database: AodhDatabasePassword description: PasswordSelectors - Selectors to identify the service from the Secret properties: @@ -433,31 +289,151 @@ spec: service password from the Secret type: string type: object + preserveJobs: + default: false + description: PreserveJobs - do not delete jobs after they + finished e.g. to check logs + type: boolean rabbitMqClusterName: default: rabbitmq description: RabbitMQ instance name Needed to request a transportURL - that is created and used in Telemetry + that is created and used in Aodh type: string secret: description: Secret containing OpenStack password information - for ceilometer + for aodh type: string serviceUser: - default: ceilometer + default: aodh description: ServiceUser - optional username used for this service to register in keystone type: string - sgCoreImage: - type: string required: - - centralImage - - computeImage - - ipmiImage - - nodeExporterImage - - notificationImage + - apiImage + - databaseInstance + - evaluatorImage + - listenerImage + - memcachedInstance + - notifierImage - secret - - sgCoreImage type: object + enabled: + default: false + description: Enabled - Whether OpenStack autoscaling service should + be deployed and managed + type: boolean + heatInstance: + default: heat + description: Heat instance name. + type: string + prometheus: + description: Specification of which prometheus to use for autoscaling + properties: + deployPrometheus: + default: false + description: Enables the deployment of autoscaling prometheus + type: boolean + host: + description: Host of user deployed prometheus if deployPrometheus + is set to false + type: string + port: + description: Port of user deployed prometheus if deployPrometheus + is set to false + format: int32 + maximum: 65535 + minimum: 1 + type: integer + type: object + required: + - heatInstance + type: object + ceilometer: + description: Ceilometer - Parameters related to the ceilometer service + properties: + centralImage: + type: string + computeImage: + type: string + customServiceConfig: + default: '# add your customization here' + description: CustomServiceConfig - customize the service config + using this parameter to change service defaults, or overwrite + rendered information using raw OpenStack config format. The + content gets added to to /etc//.conf.d directory + as custom.conf file. + type: string + defaultConfigOverwrite: + additionalProperties: + type: string + description: 'ConfigOverwrite - interface to overwrite default + config files like e.g. logging.conf or policy.json. But can + also be used to add additional files. Those get added to the + service config dir in /etc/ . TODO: -> implement' + type: object + enabled: + default: true + description: Enabled - Whether OpenStack Ceilometer service should + be deployed and managed + type: boolean + ipmiImage: + type: string + networkAttachmentDefinitions: + description: NetworkAttachmentDefinitions list of network attachment + definitions the service pod gets attached to + items: + type: string + type: array + nodeExporterImage: + type: string + notificationImage: + type: string + passwordSelector: + default: + service: CeilometerPassword + description: PasswordSelectors - Selectors to identify the service + from the Secret + properties: + aodhService: + default: AodhPassword + description: AodhService - Selector to get the aodh service + password from the Secret + type: string + database: + default: AodhDatabasePassword + description: Database - Selector to get the aodh database + user password from the Secret + type: string + service: + default: CeilometerPassword + description: Service - Selector to get the ceilometer service + password from the Secret + type: string + type: object + rabbitMqClusterName: + default: rabbitmq + description: RabbitMQ instance name Needed to request a transportURL + that is created and used in Telemetry + type: string + secret: + description: Secret containing OpenStack password information + for ceilometer + type: string + serviceUser: + default: ceilometer + description: ServiceUser - optional username used for this service + to register in keystone + type: string + sgCoreImage: + type: string + required: + - centralImage + - computeImage + - ipmiImage + - nodeExporterImage + - notificationImage + - secret + - sgCoreImage type: object secret: description: Secret containing OpenStack password information for diff --git a/api/v1beta1/telemetry_types.go b/api/v1beta1/telemetry_types.go index d8c69c7e..be9ee589 100644 --- a/api/v1beta1/telemetry_types.go +++ b/api/v1beta1/telemetry_types.go @@ -70,7 +70,7 @@ type CeilometerSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the OpenStack Ceilometer service - Template CeilometerSpec `json:"template,omitempty"` + CeilometerSpec `json:",inline"` } // AutoscalingSection defines the desired state of the autoscaling service @@ -84,7 +84,7 @@ type AutoscalingSection struct { // +kubebuilder:validation:Optional //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the OpenStack autoscaling service - Template AutoscalingSpec `json:"template,omitempty"` + AutoscalingSpec `json:",inline"` } // TelemetryStatus defines the observed state of Telemetry diff --git a/api/v1beta1/telemetry_webhook.go b/api/v1beta1/telemetry_webhook.go index fe4aa7a0..bec49e39 100644 --- a/api/v1beta1/telemetry_webhook.go +++ b/api/v1beta1/telemetry_webhook.go @@ -72,35 +72,35 @@ func (r *Telemetry) Default() { // Default - set defaults for this Telemetry spec func (spec *TelemetrySpec) Default() { - if spec.Ceilometer.Template.CentralImage == "" { - spec.Ceilometer.Template.CentralImage = telemetryDefaults.CentralContainerImageURL + if spec.Ceilometer.CeilometerSpec.CentralImage == "" { + spec.Ceilometer.CeilometerSpec.CentralImage = telemetryDefaults.CentralContainerImageURL } - if spec.Ceilometer.Template.ComputeImage == "" { - spec.Ceilometer.Template.ComputeImage = telemetryDefaults.ComputeContainerImageURL + if spec.Ceilometer.CeilometerSpec.ComputeImage == "" { + spec.Ceilometer.CeilometerSpec.ComputeImage = telemetryDefaults.ComputeContainerImageURL } - if spec.Ceilometer.Template.IpmiImage == "" { - spec.Ceilometer.Template.IpmiImage = telemetryDefaults.IpmiContainerImageURL + if spec.Ceilometer.CeilometerSpec.IpmiImage == "" { + spec.Ceilometer.CeilometerSpec.IpmiImage = telemetryDefaults.IpmiContainerImageURL } - if spec.Ceilometer.Template.NotificationImage == "" { - spec.Ceilometer.Template.NotificationImage = telemetryDefaults.NotificationContainerImageURL + if spec.Ceilometer.CeilometerSpec.NotificationImage == "" { + spec.Ceilometer.CeilometerSpec.NotificationImage = telemetryDefaults.NotificationContainerImageURL } - if spec.Ceilometer.Template.SgCoreImage == "" { - spec.Ceilometer.Template.SgCoreImage = telemetryDefaults.SgCoreContainerImageURL + if spec.Ceilometer.CeilometerSpec.SgCoreImage == "" { + spec.Ceilometer.CeilometerSpec.SgCoreImage = telemetryDefaults.SgCoreContainerImageURL } - if spec.Ceilometer.Template.NodeExporterImage == "" { - spec.Ceilometer.Template.NodeExporterImage = telemetryDefaults.NodeExporterContainerImageURL + if spec.Ceilometer.CeilometerSpec.NodeExporterImage == "" { + spec.Ceilometer.CeilometerSpec.NodeExporterImage = telemetryDefaults.NodeExporterContainerImageURL } - if spec.Autoscaling.Template.Aodh.APIImage == "" { - spec.Autoscaling.Template.Aodh.APIImage = telemetryDefaults.AodhAPIContainerImageURL + if spec.Autoscaling.AutoscalingSpec.Aodh.APIImage == "" { + spec.Autoscaling.AutoscalingSpec.Aodh.APIImage = telemetryDefaults.AodhAPIContainerImageURL } - if spec.Autoscaling.Template.Aodh.EvaluatorImage == "" { - spec.Autoscaling.Template.Aodh.EvaluatorImage = telemetryDefaults.AodhEvaluatorContainerImageURL + if spec.Autoscaling.AutoscalingSpec.Aodh.EvaluatorImage == "" { + spec.Autoscaling.AutoscalingSpec.Aodh.EvaluatorImage = telemetryDefaults.AodhEvaluatorContainerImageURL } - if spec.Autoscaling.Template.Aodh.NotifierImage == "" { - spec.Autoscaling.Template.Aodh.NotifierImage = telemetryDefaults.AodhNotifierContainerImageURL + if spec.Autoscaling.AutoscalingSpec.Aodh.NotifierImage == "" { + spec.Autoscaling.AutoscalingSpec.Aodh.NotifierImage = telemetryDefaults.AodhNotifierContainerImageURL } - if spec.Autoscaling.Template.Aodh.ListenerImage == "" { - spec.Autoscaling.Template.Aodh.ListenerImage = telemetryDefaults.AodhListenerContainerImageURL + if spec.Autoscaling.AutoscalingSpec.Aodh.ListenerImage == "" { + spec.Autoscaling.AutoscalingSpec.Aodh.ListenerImage = telemetryDefaults.AodhListenerContainerImageURL } } diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index c0f8de3b..33e097bb 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -153,7 +153,7 @@ func (in *AutoscalingList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AutoscalingSection) DeepCopyInto(out *AutoscalingSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + in.AutoscalingSpec.DeepCopyInto(&out.AutoscalingSpec) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscalingSection. @@ -301,7 +301,7 @@ func (in *CeilometerList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CeilometerSection) DeepCopyInto(out *CeilometerSection) { *out = *in - in.Template.DeepCopyInto(&out.Template) + in.CeilometerSpec.DeepCopyInto(&out.CeilometerSpec) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CeilometerSection. diff --git a/config/crd/bases/telemetry.openstack.org_telemetries.yaml b/config/crd/bases/telemetry.openstack.org_telemetries.yaml index 578c8b03..8f834aa4 100644 --- a/config/crd/bases/telemetry.openstack.org_telemetries.yaml +++ b/config/crd/bases/telemetry.openstack.org_telemetries.yaml @@ -38,350 +38,10 @@ spec: autoscaling: description: Autoscaling - Parameters related to the autoscaling service properties: - enabled: - default: false - description: Enabled - Whether OpenStack autoscaling service should - be deployed and managed - type: boolean - template: - description: Template - Overrides to use when creating the OpenStack - autoscaling service - properties: - aodh: - description: Aodh spec - properties: - apiImage: - type: string - customServiceConfig: - default: '# add your customization here' - description: CustomServiceConfig - customize the service - config using this parameter to change service defaults, - or overwrite rendered information using raw OpenStack - config format. The content gets added to to /etc//.conf.d - directory as custom.conf file. - type: string - databaseInstance: - description: MariaDB instance name Right now required - by the maridb-operator to get the credentials from the - instance to create the DB Might not be required in future - type: string - databaseUser: - default: aodh - description: Database user name Needed to connect to a - database used by aodh - type: string - defaultConfigOverwrite: - additionalProperties: - type: string - description: 'ConfigOverwrite - interface to overwrite - default config files like e.g. logging.conf or policy.json. - But can also be used to add additional files. Those - get added to the service config dir in /etc/ - . TODO: -> implement' - type: object - evaluatorImage: - type: string - listenerImage: - type: string - memcachedInstance: - default: memcached - description: Memcached instance name. - type: string - networkAttachmentDefinitions: - description: NetworkAttachmentDefinitions list of network - attachment definitions the service pod gets attached - to - items: - type: string - type: array - notifierImage: - type: string - override: - description: Override, provides the ability to override - the generated manifest of several child resources. - properties: - service: - description: Override configuration for the Service - created to serve traffic to the cluster. - properties: - endpointURL: - type: string - metadata: - description: EmbeddedLabelsAnnotations is an embedded - subset of the fields included in k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta. - Only labels and annotations are included. - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured - key value map stored with a resource that - may be set by external tools to store and - retrieve arbitrary metadata. They are not - queryable and should be preserved when modifying - objects. More info: http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values - that can be used to organize and categorize - (scope and select) objects. May match selectors - of replication controllers and services. - More info: http://kubernetes.io/docs/user-guide/labels' - type: object - type: object - spec: - description: OverrideServiceSpec is a subset of - the fields included in https://pkg.go.dev/k8s.io/api@v0.26.6/core/v1#ServiceSpec - Limited to Type, SessionAffinity, LoadBalancerSourceRanges, - ExternalName, ExternalTrafficPolicy, SessionAffinityConfig, - IPFamilyPolicy, LoadBalancerClass and InternalTrafficPolicy - properties: - externalName: - description: externalName is the external - reference that discovery mechanisms will - return as an alias for this service (e.g. - a DNS CNAME record). No proxying will be - involved. Must be a lowercase RFC-1123 - hostname (https://tools.ietf.org/html/rfc1123) - and requires `type` to be "ExternalName". - type: string - externalTrafficPolicy: - description: externalTrafficPolicy describes - how nodes distribute service traffic they - receive on one of the Service's "externally-facing" - addresses (NodePorts, ExternalIPs, and LoadBalancer - IPs). If set to "Local", the proxy will - configure the service in a way that assumes - that external load balancers will take care - of balancing the service traffic between - nodes, and so each node will deliver traffic - only to the node-local endpoints of the - service, without masquerading the client - source IP. (Traffic mistakenly sent to a - node with no endpoints will be dropped.) - The default value, "Cluster", uses the standard - behavior of routing to all endpoints evenly - (possibly modified by topology and other - features). Note that traffic sent to an - External IP or LoadBalancer IP from within - the cluster will always get "Cluster" semantics, - but clients sending to a NodePort from within - the cluster may need to take traffic policy - into account when picking a node. - type: string - internalTrafficPolicy: - description: InternalTrafficPolicy describes - how nodes distribute service traffic they - receive on the ClusterIP. If set to "Local", - the proxy will assume that pods only want - to talk to endpoints of the service on the - same node as the pod, dropping the traffic - if there are no local endpoints. The default - value, "Cluster", uses the standard behavior - of routing to all endpoints evenly (possibly - modified by topology and other features). - type: string - ipFamilyPolicy: - description: IPFamilyPolicy represents the - dual-stack-ness requested or required by - this Service. If there is no value provided, - then this field will be set to SingleStack. - Services can be "SingleStack" (a single - IP family), "PreferDualStack" (two IP families - on dual-stack configured clusters or a single - IP family on single-stack clusters), or - "RequireDualStack" (two IP families on dual-stack - configured clusters, otherwise fail). The - ipFamilies and clusterIPs fields depend - on the value of this field. This field will - be wiped when updating a service to type - ExternalName. - type: string - loadBalancerClass: - description: loadBalancerClass is the class - of the load balancer implementation this - Service belongs to. If specified, the value - of this field must be a label-style identifier, - with an optional prefix, e.g. "internal-vip" - or "example.com/internal-vip". Unprefixed - names are reserved for end-users. This field - can only be set when the Service type is - 'LoadBalancer'. If not set, the default - load balancer implementation is used, today - this is typically done through the cloud - provider integration, but should apply for - any default implementation. If set, it is - assumed that a load balancer implementation - is watching for Services with a matching - class. Any default load balancer implementation - (e.g. cloud providers) should ignore Services - that set this field. This field can only - be set when creating or updating a Service - to type 'LoadBalancer'. Once set, it can - not be changed. This field will be wiped - when a service is updated to a non 'LoadBalancer' - type. - type: string - loadBalancerSourceRanges: - description: 'If specified and supported by - the platform, this will restrict traffic - through the cloud-provider load-balancer - will be restricted to the specified client - IPs. This field will be ignored if the cloud-provider - does not support the feature." More info: - https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/' - items: - type: string - type: array - sessionAffinity: - description: 'Supports "ClientIP" and "None". - Used to maintain session affinity. Enable - client IP based session affinity. Must be - ClientIP or None. Defaults to None. More - info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies' - type: string - sessionAffinityConfig: - description: sessionAffinityConfig contains - the configurations of session affinity. - properties: - clientIP: - description: clientIP contains the configurations - of Client IP based session affinity. - properties: - timeoutSeconds: - description: timeoutSeconds specifies - the seconds of ClientIP type session - sticky time. The value must be >0 - && <=86400(for 1 day) if ServiceAffinity - == "ClientIP". Default value is - 10800(for 3 hours). - format: int32 - type: integer - type: object - type: object - type: - description: 'type determines how the Service - is exposed. Defaults to ClusterIP. Valid - options are ExternalName, ClusterIP, NodePort, - and LoadBalancer. "ClusterIP" allocates - a cluster-internal IP address for load-balancing - to endpoints. Endpoints are determined by - the selector or if that is not specified, - by manual construction of an Endpoints object - or EndpointSlice objects. If clusterIP is - "None", no virtual IP is allocated and the - endpoints are published as a set of endpoints - rather than a virtual IP. "NodePort" builds - on ClusterIP and allocates a port on every - node which routes to the same endpoints - as the clusterIP. "LoadBalancer" builds - on NodePort and creates an external load-balancer - (if supported in the current cloud) which - routes to the same endpoints as the clusterIP. - "ExternalName" aliases this service to the - specified externalName. Several other fields - do not apply to ExternalName services. More - info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types' - type: string - type: object - type: object - type: object - passwordSelector: - default: - aodhService: AodhPassword - database: AodhDatabasePassword - description: PasswordSelectors - Selectors to identify - the service from the Secret - properties: - aodhService: - default: AodhPassword - description: AodhService - Selector to get the aodh - service password from the Secret - type: string - database: - default: AodhDatabasePassword - description: Database - Selector to get the aodh database - user password from the Secret - type: string - service: - default: CeilometerPassword - description: Service - Selector to get the ceilometer - service password from the Secret - type: string - type: object - preserveJobs: - default: false - description: PreserveJobs - do not delete jobs after they - finished e.g. to check logs - type: boolean - rabbitMqClusterName: - default: rabbitmq - description: RabbitMQ instance name Needed to request - a transportURL that is created and used in Aodh - type: string - secret: - description: Secret containing OpenStack password information - for aodh - type: string - serviceUser: - default: aodh - description: ServiceUser - optional username used for - this service to register in keystone - type: string - required: - - apiImage - - databaseInstance - - evaluatorImage - - listenerImage - - memcachedInstance - - notifierImage - - secret - type: object - heatInstance: - default: heat - description: Heat instance name. - type: string - prometheus: - description: Specification of which prometheus to use for - autoscaling - properties: - deployPrometheus: - default: false - description: Enables the deployment of autoscaling prometheus - type: boolean - host: - description: Host of user deployed prometheus if deployPrometheus - is set to false - type: string - port: - description: Port of user deployed prometheus if deployPrometheus - is set to false - format: int32 - maximum: 65535 - minimum: 1 - type: integer - type: object - required: - - heatInstance - type: object - type: object - ceilometer: - description: Ceilometer - Parameters related to the ceilometer service - properties: - enabled: - default: true - description: Enabled - Whether OpenStack Ceilometer service should - be deployed and managed - type: boolean - template: - description: Template - Overrides to use when creating the OpenStack - Ceilometer service + aodh: + description: Aodh spec properties: - centralImage: - type: string - computeImage: + apiImage: type: string customServiceConfig: default: '# add your customization here' @@ -391,6 +51,16 @@ spec: The content gets added to to /etc//.conf.d directory as custom.conf file. type: string + databaseInstance: + description: MariaDB instance name Right now required by the + maridb-operator to get the credentials from the instance + to create the DB Might not be required in future + type: string + databaseUser: + default: aodh + description: Database user name Needed to connect to a database + used by aodh + type: string defaultConfigOverwrite: additionalProperties: type: string @@ -399,7 +69,13 @@ spec: can also be used to add additional files. Those get added to the service config dir in /etc/ . TODO: -> implement' type: object - ipmiImage: + evaluatorImage: + type: string + listenerImage: + type: string + memcachedInstance: + default: memcached + description: Memcached instance name. type: string networkAttachmentDefinitions: description: NetworkAttachmentDefinitions list of network @@ -407,13 +83,193 @@ spec: items: type: string type: array - nodeExporterImage: - type: string - notificationImage: + notifierImage: type: string + override: + description: Override, provides the ability to override the + generated manifest of several child resources. + properties: + service: + description: Override configuration for the Service created + to serve traffic to the cluster. + properties: + endpointURL: + type: string + metadata: + description: EmbeddedLabelsAnnotations is an embedded + subset of the fields included in k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta. + Only labels and annotations are included. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key + value map stored with a resource that may be + set by external tools to store and retrieve + arbitrary metadata. They are not queryable and + should be preserved when modifying objects. + More info: http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values that + can be used to organize and categorize (scope + and select) objects. May match selectors of + replication controllers and services. More info: + http://kubernetes.io/docs/user-guide/labels' + type: object + type: object + spec: + description: OverrideServiceSpec is a subset of the + fields included in https://pkg.go.dev/k8s.io/api@v0.26.6/core/v1#ServiceSpec + Limited to Type, SessionAffinity, LoadBalancerSourceRanges, + ExternalName, ExternalTrafficPolicy, SessionAffinityConfig, + IPFamilyPolicy, LoadBalancerClass and InternalTrafficPolicy + properties: + externalName: + description: externalName is the external reference + that discovery mechanisms will return as an + alias for this service (e.g. a DNS CNAME record). + No proxying will be involved. Must be a lowercase + RFC-1123 hostname (https://tools.ietf.org/html/rfc1123) + and requires `type` to be "ExternalName". + type: string + externalTrafficPolicy: + description: externalTrafficPolicy describes how + nodes distribute service traffic they receive + on one of the Service's "externally-facing" + addresses (NodePorts, ExternalIPs, and LoadBalancer + IPs). If set to "Local", the proxy will configure + the service in a way that assumes that external + load balancers will take care of balancing the + service traffic between nodes, and so each node + will deliver traffic only to the node-local + endpoints of the service, without masquerading + the client source IP. (Traffic mistakenly sent + to a node with no endpoints will be dropped.) + The default value, "Cluster", uses the standard + behavior of routing to all endpoints evenly + (possibly modified by topology and other features). + Note that traffic sent to an External IP or + LoadBalancer IP from within the cluster will + always get "Cluster" semantics, but clients + sending to a NodePort from within the cluster + may need to take traffic policy into account + when picking a node. + type: string + internalTrafficPolicy: + description: InternalTrafficPolicy describes how + nodes distribute service traffic they receive + on the ClusterIP. If set to "Local", the proxy + will assume that pods only want to talk to endpoints + of the service on the same node as the pod, + dropping the traffic if there are no local endpoints. + The default value, "Cluster", uses the standard + behavior of routing to all endpoints evenly + (possibly modified by topology and other features). + type: string + ipFamilyPolicy: + description: IPFamilyPolicy represents the dual-stack-ness + requested or required by this Service. If there + is no value provided, then this field will be + set to SingleStack. Services can be "SingleStack" + (a single IP family), "PreferDualStack" (two + IP families on dual-stack configured clusters + or a single IP family on single-stack clusters), + or "RequireDualStack" (two IP families on dual-stack + configured clusters, otherwise fail). The ipFamilies + and clusterIPs fields depend on the value of + this field. This field will be wiped when updating + a service to type ExternalName. + type: string + loadBalancerClass: + description: loadBalancerClass is the class of + the load balancer implementation this Service + belongs to. If specified, the value of this + field must be a label-style identifier, with + an optional prefix, e.g. "internal-vip" or "example.com/internal-vip". + Unprefixed names are reserved for end-users. + This field can only be set when the Service + type is 'LoadBalancer'. If not set, the default + load balancer implementation is used, today + this is typically done through the cloud provider + integration, but should apply for any default + implementation. If set, it is assumed that a + load balancer implementation is watching for + Services with a matching class. Any default + load balancer implementation (e.g. cloud providers) + should ignore Services that set this field. + This field can only be set when creating or + updating a Service to type 'LoadBalancer'. Once + set, it can not be changed. This field will + be wiped when a service is updated to a non + 'LoadBalancer' type. + type: string + loadBalancerSourceRanges: + description: 'If specified and supported by the + platform, this will restrict traffic through + the cloud-provider load-balancer will be restricted + to the specified client IPs. This field will + be ignored if the cloud-provider does not support + the feature." More info: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/' + items: + type: string + type: array + sessionAffinity: + description: 'Supports "ClientIP" and "None". + Used to maintain session affinity. Enable client + IP based session affinity. Must be ClientIP + or None. Defaults to None. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies' + type: string + sessionAffinityConfig: + description: sessionAffinityConfig contains the + configurations of session affinity. + properties: + clientIP: + description: clientIP contains the configurations + of Client IP based session affinity. + properties: + timeoutSeconds: + description: timeoutSeconds specifies + the seconds of ClientIP type session + sticky time. The value must be >0 && + <=86400(for 1 day) if ServiceAffinity + == "ClientIP". Default value is 10800(for + 3 hours). + format: int32 + type: integer + type: object + type: object + type: + description: 'type determines how the Service + is exposed. Defaults to ClusterIP. Valid options + are ExternalName, ClusterIP, NodePort, and LoadBalancer. + "ClusterIP" allocates a cluster-internal IP + address for load-balancing to endpoints. Endpoints + are determined by the selector or if that is + not specified, by manual construction of an + Endpoints object or EndpointSlice objects. If + clusterIP is "None", no virtual IP is allocated + and the endpoints are published as a set of + endpoints rather than a virtual IP. "NodePort" + builds on ClusterIP and allocates a port on + every node which routes to the same endpoints + as the clusterIP. "LoadBalancer" builds on NodePort + and creates an external load-balancer (if supported + in the current cloud) which routes to the same + endpoints as the clusterIP. "ExternalName" aliases + this service to the specified externalName. + Several other fields do not apply to ExternalName + services. More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types' + type: string + type: object + type: object + type: object passwordSelector: default: - service: CeilometerPassword + aodhService: AodhPassword + database: AodhDatabasePassword description: PasswordSelectors - Selectors to identify the service from the Secret properties: @@ -433,31 +289,151 @@ spec: service password from the Secret type: string type: object + preserveJobs: + default: false + description: PreserveJobs - do not delete jobs after they + finished e.g. to check logs + type: boolean rabbitMqClusterName: default: rabbitmq description: RabbitMQ instance name Needed to request a transportURL - that is created and used in Telemetry + that is created and used in Aodh type: string secret: description: Secret containing OpenStack password information - for ceilometer + for aodh type: string serviceUser: - default: ceilometer + default: aodh description: ServiceUser - optional username used for this service to register in keystone type: string - sgCoreImage: - type: string required: - - centralImage - - computeImage - - ipmiImage - - nodeExporterImage - - notificationImage + - apiImage + - databaseInstance + - evaluatorImage + - listenerImage + - memcachedInstance + - notifierImage - secret - - sgCoreImage type: object + enabled: + default: false + description: Enabled - Whether OpenStack autoscaling service should + be deployed and managed + type: boolean + heatInstance: + default: heat + description: Heat instance name. + type: string + prometheus: + description: Specification of which prometheus to use for autoscaling + properties: + deployPrometheus: + default: false + description: Enables the deployment of autoscaling prometheus + type: boolean + host: + description: Host of user deployed prometheus if deployPrometheus + is set to false + type: string + port: + description: Port of user deployed prometheus if deployPrometheus + is set to false + format: int32 + maximum: 65535 + minimum: 1 + type: integer + type: object + required: + - heatInstance + type: object + ceilometer: + description: Ceilometer - Parameters related to the ceilometer service + properties: + centralImage: + type: string + computeImage: + type: string + customServiceConfig: + default: '# add your customization here' + description: CustomServiceConfig - customize the service config + using this parameter to change service defaults, or overwrite + rendered information using raw OpenStack config format. The + content gets added to to /etc//.conf.d directory + as custom.conf file. + type: string + defaultConfigOverwrite: + additionalProperties: + type: string + description: 'ConfigOverwrite - interface to overwrite default + config files like e.g. logging.conf or policy.json. But can + also be used to add additional files. Those get added to the + service config dir in /etc/ . TODO: -> implement' + type: object + enabled: + default: true + description: Enabled - Whether OpenStack Ceilometer service should + be deployed and managed + type: boolean + ipmiImage: + type: string + networkAttachmentDefinitions: + description: NetworkAttachmentDefinitions list of network attachment + definitions the service pod gets attached to + items: + type: string + type: array + nodeExporterImage: + type: string + notificationImage: + type: string + passwordSelector: + default: + service: CeilometerPassword + description: PasswordSelectors - Selectors to identify the service + from the Secret + properties: + aodhService: + default: AodhPassword + description: AodhService - Selector to get the aodh service + password from the Secret + type: string + database: + default: AodhDatabasePassword + description: Database - Selector to get the aodh database + user password from the Secret + type: string + service: + default: CeilometerPassword + description: Service - Selector to get the ceilometer service + password from the Secret + type: string + type: object + rabbitMqClusterName: + default: rabbitmq + description: RabbitMQ instance name Needed to request a transportURL + that is created and used in Telemetry + type: string + secret: + description: Secret containing OpenStack password information + for ceilometer + type: string + serviceUser: + default: ceilometer + description: ServiceUser - optional username used for this service + to register in keystone + type: string + sgCoreImage: + type: string + required: + - centralImage + - computeImage + - ipmiImage + - nodeExporterImage + - notificationImage + - secret + - sgCoreImage type: object secret: description: Secret containing OpenStack password information for diff --git a/config/samples/telemetry_v1beta1_telemetry.yaml b/config/samples/telemetry_v1beta1_telemetry.yaml index 28d8c16c..5a734458 100644 --- a/config/samples/telemetry_v1beta1_telemetry.yaml +++ b/config/samples/telemetry_v1beta1_telemetry.yaml @@ -5,18 +5,14 @@ metadata: spec: autoscaling: enabled: false - template: - prometheus: - deployPrometheus: true - aodh: - secret: osp-secret - passwordSelectors: - databaseUser: aodh - databaseInstance: openstack - memcachedInstance: memcached - heatInstance: heat + prometheus: + deployPrometheus: true + aodh: + passwordSelectors: + databaseUser: aodh + databaseInstance: openstack + memcachedInstance: memcached + heatInstance: heat ceilometer: enabled: true - template: - secret: osp-secret secret: osp-secret diff --git a/controllers/telemetry_controller.go b/controllers/telemetry_controller.go index c15e56e8..4b70d30e 100644 --- a/controllers/telemetry_controller.go +++ b/controllers/telemetry_controller.go @@ -247,7 +247,7 @@ func reconcileCeilometer(ctx context.Context, instance *telemetryv1.Telemetry, h helper.GetLogger().Info("Reconciling Ceilometer", ceilometerNamespaceLabel, instance.Namespace, ceilometerNameLabel, ceilometer.ServiceName) op, err := controllerutil.CreateOrPatch(ctx, helper.GetClient(), ceilometerInstance, func() error { - instance.Spec.Ceilometer.Template.DeepCopyInto(&ceilometerInstance.Spec) + instance.Spec.Ceilometer.CeilometerSpec.DeepCopyInto(&ceilometerInstance.Spec) if ceilometerInstance.Spec.Secret == "" { ceilometerInstance.Spec.Secret = instance.Spec.Secret @@ -310,7 +310,7 @@ func reconcileAutoscaling(ctx context.Context, instance *telemetryv1.Telemetry, helper.GetLogger().Info("Reconciling Autoscaling", autoscalingNamespaceLabel, instance.Namespace, autoscalingNameLabel, autoscalingName) op, err := controllerutil.CreateOrPatch(ctx, helper.GetClient(), autoscalingInstance, func() error { - instance.Spec.Autoscaling.Template.DeepCopyInto(&autoscalingInstance.Spec) + instance.Spec.Autoscaling.AutoscalingSpec.DeepCopyInto(&autoscalingInstance.Spec) if autoscalingInstance.Spec.Aodh.Secret == "" { autoscalingInstance.Spec.Aodh.Secret = instance.Spec.Secret diff --git a/tests/kuttl/suites/default/tests/01-deploy.yaml b/tests/kuttl/suites/default/tests/01-deploy.yaml index cff4b9ff..389ebfb1 100644 --- a/tests/kuttl/suites/default/tests/01-deploy.yaml +++ b/tests/kuttl/suites/default/tests/01-deploy.yaml @@ -5,21 +5,19 @@ metadata: spec: autoscaling: enabled: true - template: - prometheus: - deployPrometheus: true - aodh: - secret: osp-secret - apiImage: "quay.io/mmagr/openstack-aodh-api:current-podified" - evaluatorImage: "quay.io/mmagr/openstack-aodh-evaluator:current-podified" - notifierImage: "quay.io/mmagr/openstack-aodh-notifier:current-podified" - listenerImage: "quay.io/mmagr/openstack-aodh-listener:current-podified" - passwordSelectors: - databaseUser: aodh - databaseInstance: openstack - memcachedInstance: memcached - heatInstance: heat + prometheus: + deployPrometheus: true + aodh: + secret: osp-secret + apiImage: "quay.io/mmagr/openstack-aodh-api:current-podified" + evaluatorImage: "quay.io/mmagr/openstack-aodh-evaluator:current-podified" + notifierImage: "quay.io/mmagr/openstack-aodh-notifier:current-podified" + listenerImage: "quay.io/mmagr/openstack-aodh-listener:current-podified" + passwordSelectors: + databaseUser: aodh + databaseInstance: openstack + memcachedInstance: memcached + heatInstance: heat ceilometer: enabled: true - template: - secret: osp-secret + secret: osp-secret From cfcdea81862a9c5bd0d3e12a211f783eef4216ad Mon Sep 17 00:00:00 2001 From: Jaromir Wysoglad Date: Tue, 21 Nov 2023 04:02:00 -0500 Subject: [PATCH 3/3] Fix tests for telemetry resource --- .../kuttl/suites/default/tests/01-assert.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/kuttl/suites/default/tests/01-assert.yaml b/tests/kuttl/suites/default/tests/01-assert.yaml index 6c4857ae..248efc0c 100644 --- a/tests/kuttl/suites/default/tests/01-assert.yaml +++ b/tests/kuttl/suites/default/tests/01-assert.yaml @@ -6,7 +6,7 @@ metadata: name: ceilometer ownerReferences: - kind: Ceilometer - name: telemetry-ceilometer-central + name: ceilometer spec: ports: - port: 3000 @@ -21,7 +21,7 @@ metadata: name: ceilometer ownerReferences: - kind: Ceilometer - name: telemetry-ceilometer-central + name: ceilometer spec: template: spec: @@ -50,8 +50,8 @@ apiVersion: v1 kind: Pod metadata: labels: - prometheus: telemetry-autoscaling-prometheus - name: prometheus-telemetry-autoscaling-prometheus-0 + prometheus: autoscaling-prometheus + name: prometheus-autoscaling-prometheus-0 status: containerStatuses: - name: config-reloader @@ -67,10 +67,10 @@ status: apiVersion: v1 kind: Service metadata: - name: telemetry-autoscaling-prometheus-prometheus + name: autoscaling-prometheus-prometheus ownerReferences: - kind: MonitoringStack - name: telemetry-autoscaling-prometheus + name: autoscaling-prometheus spec: ports: - name: web @@ -87,7 +87,7 @@ metadata: name: aodh-internal ownerReferences: - kind: Autoscaling - name: telemetry-autoscaling + name: autoscaling spec: ports: - name: aodh-internal @@ -104,7 +104,7 @@ metadata: name: aodh-public ownerReferences: - kind: Autoscaling - name: telemetry-autoscaling + name: autoscaling spec: ports: - name: aodh-public @@ -120,7 +120,7 @@ metadata: name: aodh ownerReferences: - kind: Autoscaling - name: telemetry-autoscaling + name: autoscaling spec: template: spec: