From 3fb6584d470122c882fc6a2c52602dd0c93d241b Mon Sep 17 00:00:00 2001 From: Balazs Gibizer Date: Tue, 20 Feb 2024 17:07:09 +0100 Subject: [PATCH] [CRD]Add DB purge API to NovaCell We will have one CronJob per cell to do db archiving and purging per cell. Pointer types are needed for nested struct field defaulting. Operator-lint update is needed to handle the pointer types properly in the omitempty check and to handle an edge case with generic types. Implements: OSPRH-104 --- Makefile | 2 +- api/bases/nova.openstack.org_nova.yaml | 22 +++++++++++++ api/bases/nova.openstack.org_novacells.yaml | 22 +++++++++++++ api/v1beta1/novacell_types.go | 32 +++++++++++++++++++ api/v1beta1/zz_generated.deepcopy.go | 32 +++++++++++++++++++ config/crd/bases/nova.openstack.org_nova.yaml | 22 +++++++++++++ .../bases/nova.openstack.org_novacells.yaml | 22 +++++++++++++ test/functional/nova_controller_test.go | 12 +++++++ test/functional/novacell_controller_test.go | 7 ++++ 9 files changed, 172 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 80b27c14d..82ca41338 100644 --- a/Makefile +++ b/Makefile @@ -351,7 +351,7 @@ golint: get-ci-tools .PHONY: operator-lint operator-lint: $(LOCALBIN) gowork ## Runs operator-lint - GOBIN=$(LOCALBIN) go install github.com/gibizer/operator-lint@v0.3.0 + GOBIN=$(LOCALBIN) go install github.com/gibizer/operator-lint@v0.5.0 go vet -vettool=$(LOCALBIN)/operator-lint ./... ./api/... .PHONY: gowork diff --git a/api/bases/nova.openstack.org_nova.yaml b/api/bases/nova.openstack.org_nova.yaml index c710a8d76..17a4be354 100644 --- a/api/bases/nova.openstack.org_nova.yaml +++ b/api/bases/nova.openstack.org_nova.yaml @@ -465,6 +465,28 @@ spec: type: object type: object type: object + dbPurge: + description: DBPurge defines the parameters for the DB archiving + and purging cron job + properties: + archiveAge: + default: 30 + description: ArchiveAge defines the minimuma age of the + records in days that can be moved to the shadow tables. + minimum: 1 + type: integer + purgeAge: + default: 90 + description: PurgeAge defines the minimum age of the records + in days that can be deleted from the shadow tables + minimum: 1 + type: integer + schedule: + default: 0 0 * * * + description: Schedule defines when to run the DB maintenance + job in a cron format. By default it runs every midnight. + type: string + type: object hasAPIAccess: description: HasAPIAccess defines if this Cell is configured to have access to the API DB and message bus. diff --git a/api/bases/nova.openstack.org_novacells.yaml b/api/bases/nova.openstack.org_novacells.yaml index 8b2738959..63ab4a142 100644 --- a/api/bases/nova.openstack.org_novacells.yaml +++ b/api/bases/nova.openstack.org_novacells.yaml @@ -147,6 +147,28 @@ spec: type: object type: object type: object + dbPurge: + description: DBPurge defines the parameters for the DB archiving and + purging cron job + properties: + archiveAge: + default: 30 + description: ArchiveAge defines the minimuma age of the records + in days that can be moved to the shadow tables. + minimum: 1 + type: integer + purgeAge: + default: 90 + description: PurgeAge defines the minimum age of the records in + days that can be deleted from the shadow tables + minimum: 1 + type: integer + schedule: + default: 0 0 * * * + description: Schedule defines when to run the DB maintenance job + in a cron format. By default it runs every midnight. + type: string + type: object keystoneAuthURL: description: KeystoneAuthURL - the URL that the service in the cell can use to talk to keystone diff --git a/api/v1beta1/novacell_types.go b/api/v1beta1/novacell_types.go index 7d1ad1474..afdee0e71 100644 --- a/api/v1beta1/novacell_types.go +++ b/api/v1beta1/novacell_types.go @@ -90,6 +90,10 @@ type NovaCellTemplate struct { // PasswordSelectors - Selectors to identify the DB passwords from the // Secret PasswordSelectors CellPasswordSelector `json:"passwordSelectors"` + + // +kubebuilder:validation:Optional + // DBPurge defines the parameters for the DB archiving and purging cron job + DBPurge NovaCellDBPurge `json:"dbPurge"` } // NovaCellSpec defines the desired state of NovaCell @@ -179,6 +183,34 @@ type NovaCellSpec struct { // +operator-sdk:csv:customresourcedefinitions:type=spec // TLS - Parameters related to the TLS TLS tls.Ca `json:"tls,omitempty"` + + // +kubebuilder:validation:Optional + // DBPurge defines the parameters for the DB archiving and purging cron job + DBPurge NovaCellDBPurge `json:"dbPurge"` +} + +// NovaCellDBPurge defines the parameters for the DB archiving and purging +// cron job +type NovaCellDBPurge struct { + // +kubebuilder:validation:Optional + // +kubebuilder:default="0 0 * * *" + // Schedule defines when to run the DB maintenance job in a cron format. + // By default it runs every midnight. + Schedule *string `json:"schedule"` + + // +kubebuilder:validation:Optional + // +kubebuilder:default=30 + // +kubebuilder:validation:Minimum=1 + // ArchiveAge defines the minimuma age of the records in days that can be + // moved to the shadow tables. + ArchiveAge *int `json:"archiveAge"` + + // +kubebuilder:validation:Optional + // +kubebuilder:default=90 + // +kubebuilder:validation:Minimum=1 + // PurgeAge defines the minimum age of the records in days that can be + // deleted from the shadow tables + PurgeAge *int `json:"purgeAge"` } // NovaCellStatus defines the observed state of NovaCell diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index b15ab9b76..6d646e508 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -330,6 +330,36 @@ func (in *NovaCell) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NovaCellDBPurge) DeepCopyInto(out *NovaCellDBPurge) { + *out = *in + if in.Schedule != nil { + in, out := &in.Schedule, &out.Schedule + *out = new(string) + **out = **in + } + if in.ArchiveAge != nil { + in, out := &in.ArchiveAge, &out.ArchiveAge + *out = new(int) + **out = **in + } + if in.PurgeAge != nil { + in, out := &in.PurgeAge, &out.PurgeAge + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NovaCellDBPurge. +func (in *NovaCellDBPurge) DeepCopy() *NovaCellDBPurge { + if in == nil { + return nil + } + out := new(NovaCellDBPurge) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NovaCellDefaults) DeepCopyInto(out *NovaCellDefaults) { *out = *in @@ -398,6 +428,7 @@ func (in *NovaCellSpec) DeepCopyInto(out *NovaCellSpec) { } } out.TLS = in.TLS + in.DBPurge.DeepCopyInto(&out.DBPurge) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NovaCellSpec. @@ -467,6 +498,7 @@ func (in *NovaCellTemplate) DeepCopyInto(out *NovaCellTemplate) { } } out.PasswordSelectors = in.PasswordSelectors + in.DBPurge.DeepCopyInto(&out.DBPurge) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NovaCellTemplate. diff --git a/config/crd/bases/nova.openstack.org_nova.yaml b/config/crd/bases/nova.openstack.org_nova.yaml index c710a8d76..17a4be354 100644 --- a/config/crd/bases/nova.openstack.org_nova.yaml +++ b/config/crd/bases/nova.openstack.org_nova.yaml @@ -465,6 +465,28 @@ spec: type: object type: object type: object + dbPurge: + description: DBPurge defines the parameters for the DB archiving + and purging cron job + properties: + archiveAge: + default: 30 + description: ArchiveAge defines the minimuma age of the + records in days that can be moved to the shadow tables. + minimum: 1 + type: integer + purgeAge: + default: 90 + description: PurgeAge defines the minimum age of the records + in days that can be deleted from the shadow tables + minimum: 1 + type: integer + schedule: + default: 0 0 * * * + description: Schedule defines when to run the DB maintenance + job in a cron format. By default it runs every midnight. + type: string + type: object hasAPIAccess: description: HasAPIAccess defines if this Cell is configured to have access to the API DB and message bus. diff --git a/config/crd/bases/nova.openstack.org_novacells.yaml b/config/crd/bases/nova.openstack.org_novacells.yaml index 8b2738959..63ab4a142 100644 --- a/config/crd/bases/nova.openstack.org_novacells.yaml +++ b/config/crd/bases/nova.openstack.org_novacells.yaml @@ -147,6 +147,28 @@ spec: type: object type: object type: object + dbPurge: + description: DBPurge defines the parameters for the DB archiving and + purging cron job + properties: + archiveAge: + default: 30 + description: ArchiveAge defines the minimuma age of the records + in days that can be moved to the shadow tables. + minimum: 1 + type: integer + purgeAge: + default: 90 + description: PurgeAge defines the minimum age of the records in + days that can be deleted from the shadow tables + minimum: 1 + type: integer + schedule: + default: 0 0 * * * + description: Schedule defines when to run the DB maintenance job + in a cron format. By default it runs every midnight. + type: string + type: object keystoneAuthURL: description: KeystoneAuthURL - the URL that the service in the cell can use to talk to keystone diff --git a/test/functional/nova_controller_test.go b/test/functional/nova_controller_test.go index f45832caf..deec50b34 100644 --- a/test/functional/nova_controller_test.go +++ b/test/functional/nova_controller_test.go @@ -23,6 +23,7 @@ import ( . "github.com/openstack-k8s-operators/lib-common/modules/common/test/helpers" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" "github.com/openstack-k8s-operators/lib-common/modules/common/util" @@ -135,6 +136,14 @@ var _ = Describe("Nova controller", func() { Expect(instance.Status.RegisteredCells).To(BeEmpty()) }) + It("defaults Spec fields", func() { + nova := GetNova(novaNames.NovaName) + cell0Template := nova.Spec.CellTemplates["cell0"] + Expect(cell0Template.DBPurge.Schedule).To(Equal(ptr.To("0 0 * * *"))) + Expect(cell0Template.DBPurge.ArchiveAge).To(Equal(ptr.To(30))) + Expect(cell0Template.DBPurge.PurgeAge).To(Equal(ptr.To(90))) + }) + It("registers nova service to keystone", func() { // assert that the KeystoneService for nova is created keystone.GetKeystoneService(novaNames.KeystoneServiceName) @@ -223,6 +232,9 @@ var _ = Describe("Nova controller", func() { cell := GetNovaCell(cell0.CellCRName) Expect(cell.Spec.ServiceUser).To(Equal("nova")) Expect(cell.Spec.ServiceAccount).To(Equal(novaNames.ServiceAccountName.Name)) + Expect(cell.Spec.DBPurge.Schedule).To(Equal(ptr.To("0 0 * * *"))) + Expect(cell.Spec.DBPurge.ArchiveAge).To(Equal(ptr.To(30))) + Expect(cell.Spec.DBPurge.PurgeAge).To(Equal(ptr.To(90))) conductor := GetNovaConductor(cell0.ConductorName) Expect(conductor.Spec.ServiceUser).To(Equal("nova")) diff --git a/test/functional/novacell_controller_test.go b/test/functional/novacell_controller_test.go index 8dfaf503d..0ae02690a 100644 --- a/test/functional/novacell_controller_test.go +++ b/test/functional/novacell_controller_test.go @@ -50,6 +50,13 @@ var _ = Describe("NovaCell controller", func() { ) }) + It("defaults Spec fields", func() { + cell0 := GetNovaCell(cell0.CellCRName) + Expect(cell0.Spec.DBPurge.Schedule).To(Equal(ptr.To("0 0 * * *"))) + Expect(cell0.Spec.DBPurge.ArchiveAge).To(Equal(ptr.To(30))) + Expect(cell0.Spec.DBPurge.PurgeAge).To(Equal(ptr.To(90))) + }) + It("is not Ready", func() { th.ExpectCondition( cell0.CellCRName,