From 86f5c74dc26803e3500ccb21fff2c24207e61e75 Mon Sep 17 00:00:00 2001 From: Martin Schuppert Date: Wed, 25 Jan 2023 13:21:27 +0100 Subject: [PATCH] Add metallb service support Depends-On: https://github.com/openstack-k8s-operators/lib-common/pull/160 --- .../keystone.openstack.org_keystoneapis.yaml | 51 ++++++++-- api/go.mod | 2 + api/go.sum | 4 +- api/v1beta1/keystoneapi_types.go | 34 ++++++- api/v1beta1/zz_generated.deepcopy.go | 41 +++++++- .../keystone.openstack.org_keystoneapis.yaml | 51 ++++++++-- config/rbac/role.yaml | 8 ++ controllers/keystoneapi_controller.go | 98 +++++++++++++++---- go.mod | 4 + go.sum | 6 +- main.go | 2 + pkg/keystone/bootstrap.go | 20 ++-- pkg/keystone/dbsync.go | 21 ++-- pkg/keystone/deployment.go | 20 +--- 14 files changed, 271 insertions(+), 91 deletions(-) diff --git a/api/bases/keystone.openstack.org_keystoneapis.yaml b/api/bases/keystone.openstack.org_keystoneapis.yaml index 5b2a196b8..d616e4186 100644 --- a/api/bases/keystone.openstack.org_keystoneapis.yaml +++ b/api/bases/keystone.openstack.org_keystoneapis.yaml @@ -17,7 +17,7 @@ spec: versions: - additionalPrinterColumns: - description: NetworkAttachments - jsonPath: .status.networkAttachments + jsonPath: .spec.networkAttachments name: NetworkAttachments type: string - description: Status @@ -109,9 +109,43 @@ spec: to add additional files. Those get added to the service config dir in /etc/ . TODO: -> implement' type: object + externalEndpoints: + description: ExternalEndpoints, expose a VIP using a pre-created IPAddressPool + items: + description: MetalLBConfig to configure the MetalLB loadbalancer + service + properties: + endpoint: + description: Endpoint, OpenStack endpoint this service maps + to + enum: + - admin + - internal + - public + type: string + ipAddressPool: + description: IPAddressPool expose VIP via MetalLB on the IPAddressPool + minLength: 1 + type: string + loadBalancerIPs: + description: LoadBalancerIPs, request given IPs from the pool + if available. Using a list to allow dual stack (IPv4/IPv6) + support + items: + type: string + type: array + sharedIP: + default: true + description: SharedIP if true, VIP/VIPs get shared with multiple + services + type: boolean + required: + - ipAddressPool + type: object + type: array networkAttachments: - description: Networks list of NetworkAttachment to expose the services - to + description: NetworkAttachments is a list of NetworkAttachment resource + names to expose the services to the given network items: type: string type: array @@ -271,11 +305,12 @@ spec: description: Map of hashes to track e.g. job status type: object networkAttachments: - description: NetworkAttachments in addtion to the cluster network, - the service is attached to - items: - type: string - type: array + additionalProperties: + items: + type: string + type: array + description: NetworkAttachments status of the deployment pods + type: object readyCount: description: ReadyCount of keystone API instances format: int32 diff --git a/api/go.mod b/api/go.mod index 6321df668..6639b6729 100644 --- a/api/go.mod +++ b/api/go.mod @@ -67,3 +67,5 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) + +replace github.com/openstack-k8s-operators/lib-common/modules/common => github.com/stuggi/lib-common/modules/common v0.0.0-20230213111010-7458e283a386 diff --git a/api/go.sum b/api/go.sum index 22f73a8a4..9d5f1ad59 100644 --- a/api/go.sum +++ b/api/go.sum @@ -221,8 +221,6 @@ github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc= github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= github.com/openshift/api v3.9.0+incompatible h1:fJ/KsefYuZAjmrr3+5U9yZIZbTOpVkDDLDLFresAeYs= github.com/openshift/api v3.9.0+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY= -github.com/openstack-k8s-operators/lib-common/modules/common v0.0.0-20230208113903-f7b52e2a2ccb h1:GL2gr48Uj07HAR4m4iShujzCrHwy/vH78FIKKjgtIR0= -github.com/openstack-k8s-operators/lib-common/modules/common v0.0.0-20230208113903-f7b52e2a2ccb/go.mod h1:qV9OlokZRpqbHI3lmeN5EOmIKynWphw6GPl3zP9KOGM= github.com/openstack-k8s-operators/lib-common/modules/openstack v0.0.0-20230208113903-f7b52e2a2ccb h1:J4/Q3K0zkdUwtTRcXaxvoMK+ZgggxVtNjzEvqBu/siQ= github.com/openstack-k8s-operators/lib-common/modules/openstack v0.0.0-20230208113903-f7b52e2a2ccb/go.mod h1:9tj29SmyP9izLIEKj5E44F7M7a82UwcPdIufc3MQpcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -278,6 +276,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stuggi/lib-common/modules/common v0.0.0-20230213111010-7458e283a386 h1:ETecHuZuuw8JcV8ovdnygpi+RrW9UX7o2fymH9pUi4w= +github.com/stuggi/lib-common/modules/common v0.0.0-20230213111010-7458e283a386/go.mod h1:+EDQmWZRA8ruHnWPcw9s/el3UMi6u4EZkcSe7dCQ50k= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= diff --git a/api/v1beta1/keystoneapi_types.go b/api/v1beta1/keystoneapi_types.go index 70c2505a2..f7e5716e9 100644 --- a/api/v1beta1/keystoneapi_types.go +++ b/api/v1beta1/keystoneapi_types.go @@ -127,8 +127,34 @@ type KeystoneAPISpec struct { Resources corev1.ResourceRequirements `json:"resources,omitempty"` // +kubebuilder:validation:Optional - // Networks list of NetworkAttachment to expose the services to + // NetworkAttachments is a list of NetworkAttachment resource names to expose the services to the given network NetworkAttachments []string `json:"networkAttachments"` + + // +kubebuilder:validation:Optional + // ExternalEndpoints, expose a VIP using a pre-created IPAddressPool + ExternalEndpoints []MetalLBConfig `json:"externalEndpoints"` +} + +// MetalLBConfig to configure the MetalLB loadbalancer service +type MetalLBConfig struct { + // +kubebuilder:validation:Optional + // +kubebuilder:validation:Enum=admin;internal;public + // Endpoint, OpenStack endpoint this service maps to + Endpoint endpoint.Endpoint `json:"endpoint"` + + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + // IPAddressPool expose VIP via MetalLB on the IPAddressPool + IPAddressPool string `json:"ipAddressPool"` + + // +kubebuilder:validation:Optional + // +kubebuilder:default=true + // SharedIP if true, VIP/VIPs get shared with multiple services + SharedIP bool `json:"sharedIP"` + + // +kubebuilder:validation:Optional + // LoadBalancerIPs, request given IPs from the pool if available. Using a list to allow dual stack (IPv4/IPv6) support + LoadBalancerIPs []string `json:"loadBalancerIPs"` } // PasswordSelector to identify the DB and AdminUser password from the Secret @@ -177,13 +203,13 @@ type KeystoneAPIStatus struct { // Keystone Database Hostname DatabaseHostname string `json:"databaseHostname,omitempty"` - // NetworkAttachments in addtion to the cluster network, the service is attached to - NetworkAttachments []string `json:"networkAttachments,omitempty"` + // NetworkAttachments status of the deployment pods + NetworkAttachments map[string][]string `json:"networkAttachments,omitempty"` } //+kubebuilder:object:root=true //+kubebuilder:subresource:status -//+kubebuilder:printcolumn:name="NetworkAttachments",type="string",JSONPath=".status.networkAttachments",description="NetworkAttachments" +//+kubebuilder:printcolumn:name="NetworkAttachments",type="string",JSONPath=".spec.networkAttachments",description="NetworkAttachments" //+kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[0].status",description="Status" //+kubebuilder:printcolumn:name="Message",type="string",JSONPath=".status.conditions[0].message",description="Message" diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index c208c19e4..1d80c8e5e 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -110,6 +110,13 @@ func (in *KeystoneAPISpec) DeepCopyInto(out *KeystoneAPISpec) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.ExternalEndpoints != nil { + in, out := &in.ExternalEndpoints, &out.ExternalEndpoints + *out = make([]MetalLBConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeystoneAPISpec. @@ -148,8 +155,18 @@ func (in *KeystoneAPIStatus) DeepCopyInto(out *KeystoneAPIStatus) { } if in.NetworkAttachments != nil { in, out := &in.NetworkAttachments, &out.NetworkAttachments - *out = make([]string, len(*in)) - copy(*out, *in) + *out = make(map[string][]string, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } } } @@ -445,6 +462,26 @@ func (in *KeystoneServiceStatus) DeepCopy() *KeystoneServiceStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetalLBConfig) DeepCopyInto(out *MetalLBConfig) { + *out = *in + if in.LoadBalancerIPs != nil { + in, out := &in.LoadBalancerIPs, &out.LoadBalancerIPs + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetalLBConfig. +func (in *MetalLBConfig) DeepCopy() *MetalLBConfig { + if in == nil { + return nil + } + out := new(MetalLBConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PasswordSelector) DeepCopyInto(out *PasswordSelector) { *out = *in diff --git a/config/crd/bases/keystone.openstack.org_keystoneapis.yaml b/config/crd/bases/keystone.openstack.org_keystoneapis.yaml index 5b2a196b8..d616e4186 100644 --- a/config/crd/bases/keystone.openstack.org_keystoneapis.yaml +++ b/config/crd/bases/keystone.openstack.org_keystoneapis.yaml @@ -17,7 +17,7 @@ spec: versions: - additionalPrinterColumns: - description: NetworkAttachments - jsonPath: .status.networkAttachments + jsonPath: .spec.networkAttachments name: NetworkAttachments type: string - description: Status @@ -109,9 +109,43 @@ spec: to add additional files. Those get added to the service config dir in /etc/ . TODO: -> implement' type: object + externalEndpoints: + description: ExternalEndpoints, expose a VIP using a pre-created IPAddressPool + items: + description: MetalLBConfig to configure the MetalLB loadbalancer + service + properties: + endpoint: + description: Endpoint, OpenStack endpoint this service maps + to + enum: + - admin + - internal + - public + type: string + ipAddressPool: + description: IPAddressPool expose VIP via MetalLB on the IPAddressPool + minLength: 1 + type: string + loadBalancerIPs: + description: LoadBalancerIPs, request given IPs from the pool + if available. Using a list to allow dual stack (IPv4/IPv6) + support + items: + type: string + type: array + sharedIP: + default: true + description: SharedIP if true, VIP/VIPs get shared with multiple + services + type: boolean + required: + - ipAddressPool + type: object + type: array networkAttachments: - description: Networks list of NetworkAttachment to expose the services - to + description: NetworkAttachments is a list of NetworkAttachment resource + names to expose the services to the given network items: type: string type: array @@ -271,11 +305,12 @@ spec: description: Map of hashes to track e.g. job status type: object networkAttachments: - description: NetworkAttachments in addtion to the cluster network, - the service is attached to - items: - type: string - type: array + additionalProperties: + items: + type: string + type: array + description: NetworkAttachments status of the deployment pods + type: object readyCount: description: ReadyCount of keystone API instances format: int32 diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 086443bca..26b5043d8 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -65,6 +65,14 @@ rules: - patch - update - watch +- apiGroups: + - k8s.cni.cncf.io + resources: + - network-attachment-definitions + verbs: + - get + - list + - watch - apiGroups: - keystone.openstack.org resources: diff --git a/controllers/keystoneapi_controller.go b/controllers/keystoneapi_controller.go index 17dc015e3..adfb6c721 100644 --- a/controllers/keystoneapi_controller.go +++ b/controllers/keystoneapi_controller.go @@ -33,6 +33,7 @@ import ( helper "github.com/openstack-k8s-operators/lib-common/modules/common/helper" job "github.com/openstack-k8s-operators/lib-common/modules/common/job" labels "github.com/openstack-k8s-operators/lib-common/modules/common/labels" + nad "github.com/openstack-k8s-operators/lib-common/modules/common/networkattachment" oko_secret "github.com/openstack-k8s-operators/lib-common/modules/common/secret" util "github.com/openstack-k8s-operators/lib-common/modules/common/util" database "github.com/openstack-k8s-operators/lib-common/modules/database" @@ -90,6 +91,7 @@ type KeystoneAPIReconciler struct { // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete; // +kubebuilder:rbac:groups=route.openshift.io,resources=routes,verbs=get;list;watch;create;update;patch;delete; // +kubebuilder:rbac:groups=mariadb.openstack.org,resources=mariadbdatabases,verbs=get;list;watch;create;update;patch;delete; +// +kubebuilder:rbac:groups=k8s.cni.cncf.io,resources=network-attachment-definitions,verbs=get;list;watch // Reconcile reconcile keystone API requests func (r *KeystoneAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, _err error) { @@ -152,7 +154,8 @@ func (r *KeystoneAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request) condition.UnknownCondition(condition.BootstrapReadyCondition, condition.InitReason, condition.BootstrapReadyInitMessage), condition.UnknownCondition(condition.InputReadyCondition, condition.InitReason, condition.InputReadyInitMessage), condition.UnknownCondition(condition.ServiceConfigReadyCondition, condition.InitReason, condition.ServiceConfigReadyInitMessage), - condition.UnknownCondition(condition.DeploymentReadyCondition, condition.InitReason, condition.DeploymentReadyInitMessage)) + condition.UnknownCondition(condition.DeploymentReadyCondition, condition.InitReason, condition.DeploymentReadyInitMessage), + condition.UnknownCondition(condition.NetworkAttachmentsReadyCondition, condition.InitReason, condition.NetworkAttachmentsReadyInitMessage)) instance.Status.Conditions.Init(&cl) @@ -165,6 +168,9 @@ func (r *KeystoneAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request) if instance.Status.APIEndpoints == nil { instance.Status.APIEndpoints = map[string]string{} } + if instance.Status.NetworkAttachments == nil { + instance.Status.NetworkAttachments = map[string][]string{} + } // Handle service delete if !instance.DeletionTimestamp.IsZero() { @@ -216,6 +222,7 @@ func (r *KeystoneAPIReconciler) reconcileInit( instance *keystonev1.KeystoneAPI, helper *helper.Helper, serviceLabels map[string]string, + serviceAnnotations map[string]string, ) (ctrl.Result, error) { r.Log.Info("Reconciling Service init") @@ -282,11 +289,7 @@ func (r *KeystoneAPIReconciler) reconcileInit( // run keystone db sync // dbSyncHash := instance.Status.Hash[keystonev1.DbSyncHash] - jobDef, err := keystone.DbSyncJob(instance, serviceLabels) - if err != nil { - return ctrl.Result{}, err - } - + jobDef := keystone.DbSyncJob(instance, serviceLabels, serviceAnnotations) dbSyncjob := job.NewJob( jobDef, keystonev1.DbSyncHash, @@ -327,15 +330,26 @@ func (r *KeystoneAPIReconciler) reconcileInit( // expose the service (create service, route and return the created endpoint URLs) // var keystonePorts = map[endpoint.Endpoint]endpoint.Data{ - endpoint.EndpointAdmin: endpoint.Data{ - Port: keystone.KeystoneAdminPort, - }, endpoint.EndpointPublic: endpoint.Data{ Port: keystone.KeystonePublicPort, }, endpoint.EndpointInternal: endpoint.Data{ Port: keystone.KeystoneInternalPort, }, + endpoint.EndpointAdmin: endpoint.Data{ + Port: keystone.KeystoneAdminPort, + }, + } + + for _, metallbcfg := range instance.Spec.ExternalEndpoints { + portCfg := keystonePorts[metallbcfg.Endpoint] + portCfg.MetalLB = &endpoint.MetalLBData{ + IPAddressPool: metallbcfg.IPAddressPool, + SharedIP: metallbcfg.SharedIP, + LoadBalancerIPs: metallbcfg.LoadBalancerIPs, + } + + keystonePorts[metallbcfg.Endpoint] = portCfg } apiEndpoints, ctrlResult, err := endpoint.ExposeEndpoints( @@ -378,11 +392,7 @@ func (r *KeystoneAPIReconciler) reconcileInit( // // BootStrap Job // - jobDef, err = keystone.BootstrapJob(instance, serviceLabels, instance.Status.APIEndpoints) - if err != nil { - return ctrl.Result{}, err - } - + jobDef = keystone.BootstrapJob(instance, serviceLabels, serviceAnnotations, instance.Status.APIEndpoints) bootstrapjob := job.NewJob( jobDef, keystonev1.BootstrapHash, @@ -537,8 +547,37 @@ func (r *KeystoneAPIReconciler) reconcileNormal(ctx context.Context, instance *k common.AppSelector: keystone.ServiceName, } + // networks to attach to + for _, netAtt := range instance.Spec.NetworkAttachments { + _, err := nad.GetNADWithName(ctx, helper, netAtt, instance.Namespace) + if err != nil { + if k8s_errors.IsNotFound(err) { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.NetworkAttachmentsReadyCondition, + condition.RequestedReason, + condition.SeverityInfo, + condition.NetworkAttachmentsReadyWaitingMessage, + netAtt)) + return ctrl.Result{RequeueAfter: time.Second * 10}, fmt.Errorf("network-attachment-definition %s not found", netAtt) + } + instance.Status.Conditions.Set(condition.FalseCondition( + condition.NetworkAttachmentsReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.NetworkAttachmentsReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } + } + + serviceAnnotations, err := nad.CreateNetworksAnnotation(instance.Namespace, instance.Spec.NetworkAttachments) + if err != nil { + return ctrl.Result{}, fmt.Errorf("failed create network annotation from %s: %w", + instance.Spec.NetworkAttachments, err) + } + // Handle service init - ctrlResult, err := r.reconcileInit(ctx, instance, helper, serviceLabels) + ctrlResult, err := r.reconcileInit(ctx, instance, helper, serviceLabels, serviceAnnotations) if err != nil { return ctrlResult, err } else if (ctrlResult != ctrl.Result{}) { @@ -566,11 +605,7 @@ func (r *KeystoneAPIReconciler) reconcileNormal(ctx context.Context, instance *k // // Define a new Deployment object - deplDef, err := keystone.Deployment(instance, inputHash, serviceLabels) - if err != nil { - return ctrl.Result{}, err - } - + deplDef := keystone.Deployment(instance, inputHash, serviceLabels, serviceAnnotations) depl := deployment.NewDeployment( deplDef, time.Duration(5)*time.Second, @@ -597,7 +632,28 @@ func (r *KeystoneAPIReconciler) reconcileNormal(ctx context.Context, instance *k if instance.Status.ReadyCount > 0 { instance.Status.Conditions.MarkTrue(condition.DeploymentReadyCondition, condition.DeploymentReadyMessage) } - instance.Status.Networks = instance.Spec.NetworkAttachmentDefinitions + + // verify if network attachment matches expectations + networkReady, networkAttachmentStatus, err := nad.VerifyNetworkStatusFromAnnotation(ctx, helper, instance.Spec.NetworkAttachments, serviceLabels, instance.Status.ReadyCount) + if err != nil { + return ctrl.Result{}, err + } + + instance.Status.NetworkAttachments = networkAttachmentStatus + if len(instance.Spec.NetworkAttachments) == 0 || networkReady { + instance.Status.Conditions.MarkTrue(condition.NetworkAttachmentsReadyCondition, condition.NetworkAttachmentsReadyMessage) + } else { + err := fmt.Errorf("not all pods have interfaces with ips as configured in NetworkAttachments: %s", instance.Spec.NetworkAttachments) + instance.Status.Conditions.Set(condition.FalseCondition( + condition.NetworkAttachmentsReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.NetworkAttachmentsReadyErrorMessage, + err.Error())) + + return ctrlResult, nil + } + // create Deployment - end // diff --git a/go.mod b/go.mod index fc9124a0a..94620dd39 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,8 @@ require ( sigs.k8s.io/controller-runtime v0.14.2 ) +require github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.4.0 + require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect @@ -82,3 +84,5 @@ replace github.com/openstack-k8s-operators/keystone-operator/api => ./api // Without this, the following error occurs: // ../go/pkg/mod/k8s.io/apimachinery@v0.24.3/pkg/util/managedfields/gvkparser.go:62:39: cannot use smdschema.Schema{…} (value of type "sigs.k8s.io/structured-merge-diff/v4/schema".Schema) as type *"sigs.k8s.io/structured-merge-diff/v4/schema".Schema in struct literal replace sigs.k8s.io/structured-merge-diff/v4 v4.2.2 => sigs.k8s.io/structured-merge-diff/v4 v4.2.1 + +replace github.com/openstack-k8s-operators/lib-common/modules/common => github.com/stuggi/lib-common/modules/common v0.0.0-20230213111010-7458e283a386 diff --git a/go.sum b/go.sum index 44c31cbd9..3d3cdb4e5 100644 --- a/go.sum +++ b/go.sum @@ -191,6 +191,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.4.0 h1:VzM3TYHDgqPkettiP6I6q2jOeQFL4nrJM+UcAc4f6Fs= +github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.4.0/go.mod h1:nqCI7aelBJU61wiBeeZWJ6oi4bJy5nrjkM6lWIMA4j0= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -228,8 +230,6 @@ github.com/openshift/api v3.9.0+incompatible h1:fJ/KsefYuZAjmrr3+5U9yZIZbTOpVkDD github.com/openshift/api v3.9.0+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY= github.com/openstack-k8s-operators/infra-operator/apis v0.0.0-20230126151500-66ff44f847f6 h1:ATYFo2rcUY1Q8DHd81JEfXis3ROlNdmGKAZk0wbFg2U= github.com/openstack-k8s-operators/infra-operator/apis v0.0.0-20230126151500-66ff44f847f6/go.mod h1:1eXDVJYo3+NPrAyvrDo9BTcc2W/v+b6Jw/cL7O0aAno= -github.com/openstack-k8s-operators/lib-common/modules/common v0.0.0-20230208113903-f7b52e2a2ccb h1:GL2gr48Uj07HAR4m4iShujzCrHwy/vH78FIKKjgtIR0= -github.com/openstack-k8s-operators/lib-common/modules/common v0.0.0-20230208113903-f7b52e2a2ccb/go.mod h1:qV9OlokZRpqbHI3lmeN5EOmIKynWphw6GPl3zP9KOGM= github.com/openstack-k8s-operators/lib-common/modules/database v0.0.0-20230208113903-f7b52e2a2ccb h1:FfymdsWWPiHkJcM/9TG0yU2t8hbCigMp02Z53fZXca4= github.com/openstack-k8s-operators/lib-common/modules/database v0.0.0-20230208113903-f7b52e2a2ccb/go.mod h1:rONM/XgvFs6putDIxRHNv9/CTGh2afAvJM5wRP2OywY= github.com/openstack-k8s-operators/lib-common/modules/openstack v0.0.0-20230208113903-f7b52e2a2ccb h1:J4/Q3K0zkdUwtTRcXaxvoMK+ZgggxVtNjzEvqBu/siQ= @@ -290,6 +290,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stuggi/lib-common/modules/common v0.0.0-20230213111010-7458e283a386 h1:ETecHuZuuw8JcV8ovdnygpi+RrW9UX7o2fymH9pUi4w= +github.com/stuggi/lib-common/modules/common v0.0.0-20230213111010-7458e283a386/go.mod h1:+EDQmWZRA8ruHnWPcw9s/el3UMi6u4EZkcSe7dCQ50k= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= diff --git a/main.go b/main.go index e26ddec51..9900d001e 100644 --- a/main.go +++ b/main.go @@ -34,6 +34,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" + networkv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" @@ -51,6 +52,7 @@ func init() { utilruntime.Must(keystonev1.AddToScheme(scheme)) utilruntime.Must(mariadbv1.AddToScheme(scheme)) utilruntime.Must(routev1.AddToScheme(scheme)) + utilruntime.Must(networkv1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } diff --git a/pkg/keystone/bootstrap.go b/pkg/keystone/bootstrap.go index ceac86b14..9d056f267 100644 --- a/pkg/keystone/bootstrap.go +++ b/pkg/keystone/bootstrap.go @@ -16,14 +16,10 @@ limitations under the License. package keystone import ( - "fmt" - keystonev1beta1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" common "github.com/openstack-k8s-operators/lib-common/modules/common" - "github.com/openstack-k8s-operators/lib-common/modules/common/annotations" "github.com/openstack-k8s-operators/lib-common/modules/common/env" - "github.com/openstack-k8s-operators/lib-common/modules/common/util" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -38,8 +34,9 @@ const ( func BootstrapJob( instance *keystonev1beta1.KeystoneAPI, labels map[string]string, + annotations map[string]string, endpoints map[string]string, -) (*batchv1.Job, error) { +) *batchv1.Job { runAsUser := int64(0) args := []string{"-c"} @@ -77,6 +74,9 @@ func BootstrapJob( }, Spec: batchv1.JobSpec{ Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: annotations, + }, Spec: corev1.PodSpec{ RestartPolicy: "OnFailure", ServiceAccountName: ServiceAccount, @@ -114,14 +114,6 @@ func BootstrapJob( job.Spec.Template.Spec.Containers[0].Env = env.MergeEnvs(job.Spec.Template.Spec.Containers[0].Env, envVars) job.Spec.Template.Spec.Volumes = getVolumes(instance.Name) - // networks to attach to - nwAnnotation, err := annotations.GetNADAnnotation(instance.Namespace, instance.Spec.NetworkAttachments) - if err != nil { - return nil, fmt.Errorf("failed create network annotation from %s: %w", - instance.Spec.NetworkAttachments, err) - } - job.Spec.Template.Annotations = util.MergeStringMaps(job.Spec.Template.Annotations, nwAnnotation) - initContainerDetails := APIDetails{ ContainerImage: instance.Spec.ContainerImage, DatabaseHost: instance.Status.DatabaseHostname, @@ -134,5 +126,5 @@ func BootstrapJob( } job.Spec.Template.Spec.InitContainers = initContainer(initContainerDetails) - return job, nil + return job } diff --git a/pkg/keystone/dbsync.go b/pkg/keystone/dbsync.go index bd4f4224c..a3f5a71b3 100644 --- a/pkg/keystone/dbsync.go +++ b/pkg/keystone/dbsync.go @@ -16,14 +16,10 @@ limitations under the License. package keystone import ( - "fmt" - keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" common "github.com/openstack-k8s-operators/lib-common/modules/common" - "github.com/openstack-k8s-operators/lib-common/modules/common/annotations" "github.com/openstack-k8s-operators/lib-common/modules/common/env" - "github.com/openstack-k8s-operators/lib-common/modules/common/util" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -38,7 +34,8 @@ const ( func DbSyncJob( instance *keystonev1.KeystoneAPI, labels map[string]string, -) (*batchv1.Job, error) { + annotations map[string]string, +) *batchv1.Job { runAsUser := int64(0) args := []string{"-c"} @@ -61,6 +58,9 @@ func DbSyncJob( }, Spec: batchv1.JobSpec{ Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: annotations, + }, Spec: corev1.PodSpec{ RestartPolicy: "OnFailure", ServiceAccountName: ServiceAccount, @@ -85,15 +85,6 @@ func DbSyncJob( } job.Spec.Template.Spec.Volumes = getVolumes(ServiceName) - - // networks to attach to - nwAnnotation, err := annotations.GetNADAnnotation(instance.Namespace, instance.Spec.NetworkAttachments) - if err != nil { - return nil, fmt.Errorf("failed create network annotation from %s: %w", - instance.Spec.NetworkAttachments, err) - } - job.Spec.Template.Annotations = util.MergeStringMaps(job.Spec.Template.Annotations, nwAnnotation) - initContainerDetails := APIDetails{ ContainerImage: instance.Spec.ContainerImage, DatabaseHost: instance.Status.DatabaseHostname, @@ -106,5 +97,5 @@ func DbSyncJob( } job.Spec.Template.Spec.InitContainers = initContainer(initContainerDetails) - return job, nil + return job } diff --git a/pkg/keystone/deployment.go b/pkg/keystone/deployment.go index 0cbe9498c..4db512a0d 100644 --- a/pkg/keystone/deployment.go +++ b/pkg/keystone/deployment.go @@ -16,14 +16,10 @@ limitations under the License. package keystone import ( - "fmt" - keystonev1beta1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" common "github.com/openstack-k8s-operators/lib-common/modules/common" "github.com/openstack-k8s-operators/lib-common/modules/common/affinity" - "github.com/openstack-k8s-operators/lib-common/modules/common/annotations" "github.com/openstack-k8s-operators/lib-common/modules/common/env" - "github.com/openstack-k8s-operators/lib-common/modules/common/util" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -41,7 +37,8 @@ func Deployment( instance *keystonev1beta1.KeystoneAPI, configHash string, labels map[string]string, -) (*appsv1.Deployment, error) { + annotations map[string]string, +) *appsv1.Deployment { runAsUser := int64(0) livenessProbe := &corev1.Probe{ @@ -104,7 +101,8 @@ func Deployment( Replicas: &instance.Spec.Replicas, Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: labels, + Annotations: annotations, + Labels: labels, }, Spec: corev1.PodSpec{ ServiceAccountName: ServiceAccount, @@ -145,14 +143,6 @@ func Deployment( deployment.Spec.Template.Spec.NodeSelector = instance.Spec.NodeSelector } - // networks to attach to - nwAnnotation, err := annotations.GetNADAnnotation(instance.Namespace, instance.Spec.NetworkAttachments) - if err != nil { - return nil, fmt.Errorf("failed create network annotation from %s: %w", - instance.Spec.NetworkAttachments, err) - } - deployment.Spec.Template.Annotations = util.MergeStringMaps(deployment.Spec.Template.Annotations, nwAnnotation) - initContainerDetails := APIDetails{ ContainerImage: instance.Spec.ContainerImage, DatabaseHost: instance.Status.DatabaseHostname, @@ -165,5 +155,5 @@ func Deployment( } deployment.Spec.Template.Spec.InitContainers = initContainer(initContainerDetails) - return deployment, nil + return deployment }