From e18cbc7334435a4da1ddd78779142c692b412dda Mon Sep 17 00:00:00 2001 From: Erin Corson Date: Thu, 14 May 2020 20:34:53 -0600 Subject: [PATCH] add backup retention and geo redundant backup configurability (#1051) add backup retention and georedundancy for psql and mysql --- api/v1alpha1/mysqlserver_conversion.go | 2 +- api/v1alpha1/postgresqlserver_conversion.go | 70 ++++++++ api/v1alpha1/postgresqlserver_webhook.go | 20 +++ api/v1alpha2/mysqlserver_types.go | 92 ++-------- api/v1alpha2/postgresqlserver_conversion.go | 6 + api/v1alpha2/postgresqlserver_types.go | 52 ++++++ api/v1alpha2/sharedazuredbs_types.go | 86 ++++++++++ config/crd/kustomization.yaml | 8 +- .../patches/cainjection_in_mysqlservers.yaml | 2 +- .../crd/patches/webhook_in_mysqlservers.yaml | 1 + .../webhook_in_postgresqldatabases.yaml | 1 + .../patches/webhook_in_postgresqlservers.yaml | 1 + config/default/manager_image_patch.yaml | 2 +- .../samples/azure_v1alpha1_mysqlserver.yaml | 2 - .../samples/azure_v1alpha2_mysqlserver.yaml | 16 +- .../azure_v1alpha2_postgresqlserver.yaml | 26 +++ controllers/mysql_combined_test.go | 1 + controllers/mysqlserver_controller_test.go | 6 +- .../postgresql_combined_controller_test.go | 22 ++- controllers/postgresqlserver_controller.go | 7 +- .../postgresqlserver_controller_test.go | 18 +- main.go | 4 + pkg/resourcemanager/mysql/server/client.go | 28 +-- pkg/resourcemanager/mysql/server/reconcile.go | 7 +- .../psql/database/database_test.go | 159 ----------------- .../psql/firewallrule/firewallrule_test.go | 160 ------------------ .../psql/firewallrule/suite_test.go | 93 ---------- pkg/resourcemanager/psql/server/server.go | 88 +++++----- .../psql/server/server_manager.go | 14 +- .../psql/server/server_reconcile.go | 15 +- .../psql/server/server_test.go | 115 ------------- pkg/resourcemanager/psql/server/suite_test.go | 89 ---------- 32 files changed, 400 insertions(+), 813 deletions(-) create mode 100644 api/v1alpha1/postgresqlserver_conversion.go create mode 100644 api/v1alpha1/postgresqlserver_webhook.go create mode 100644 api/v1alpha2/postgresqlserver_conversion.go create mode 100644 api/v1alpha2/postgresqlserver_types.go create mode 100644 api/v1alpha2/sharedazuredbs_types.go create mode 100644 config/samples/azure_v1alpha2_postgresqlserver.yaml delete mode 100644 pkg/resourcemanager/psql/database/database_test.go delete mode 100644 pkg/resourcemanager/psql/firewallrule/firewallrule_test.go delete mode 100644 pkg/resourcemanager/psql/firewallrule/suite_test.go delete mode 100644 pkg/resourcemanager/psql/server/server_test.go delete mode 100644 pkg/resourcemanager/psql/server/suite_test.go diff --git a/api/v1alpha1/mysqlserver_conversion.go b/api/v1alpha1/mysqlserver_conversion.go index 623dc6f2795..2496e333bf3 100644 --- a/api/v1alpha1/mysqlserver_conversion.go +++ b/api/v1alpha1/mysqlserver_conversion.go @@ -32,7 +32,7 @@ func (src *MySQLServer) ConvertTo(dstRaw conversion.Hub) error { dst.Spec.KeyVaultToStoreSecrets = src.Spec.KeyVaultToStoreSecrets // New Spec - //dst.Spec.StorageProfile = nil + dst.Spec.StorageProfile = nil // Status dst.Status = v1alpha2.ASOStatus(src.Status) diff --git a/api/v1alpha1/postgresqlserver_conversion.go b/api/v1alpha1/postgresqlserver_conversion.go new file mode 100644 index 00000000000..be3af9f916d --- /dev/null +++ b/api/v1alpha1/postgresqlserver_conversion.go @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package v1alpha1 + +import ( + "github.com/Azure/azure-service-operator/api/v1alpha2" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +func (src *PostgreSQLServer) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1alpha2.PostgreSQLServer) + + // ObjectMeta + dst.ObjectMeta = src.ObjectMeta + + // Spec + dst.Spec.ResourceGroup = src.Spec.ResourceGroup + dst.Spec.Location = src.Spec.Location + dst.Spec.Sku = v1alpha2.AzureDBsSQLSku{ + Name: src.Spec.Sku.Name, + Tier: v1alpha2.SkuTier(src.Spec.Sku.Tier), + Capacity: src.Spec.Sku.Capacity, + Size: src.Spec.Sku.Size, + Family: src.Spec.Sku.Family, + } + + dst.Spec.ServerVersion = v1alpha2.ServerVersion(src.Spec.ServerVersion) + dst.Spec.SSLEnforcement = v1alpha2.SslEnforcementEnum(src.Spec.SSLEnforcement) + dst.Spec.CreateMode = src.Spec.CreateMode + dst.Spec.ReplicaProperties = v1alpha2.ReplicaProperties(src.Spec.ReplicaProperties) + dst.Spec.KeyVaultToStoreSecrets = src.Spec.KeyVaultToStoreSecrets + + // New Spec + dst.Spec.StorageProfile = nil + + // Status + dst.Status = v1alpha2.ASOStatus(src.Status) + + return nil +} + +func (dst *PostgreSQLServer) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1alpha2.PostgreSQLServer) + + // ObjectMeta + dst.ObjectMeta = src.ObjectMeta + + // Spec + dst.Spec.ResourceGroup = src.Spec.ResourceGroup + dst.Spec.Location = src.Spec.Location + dst.Spec.Sku = AzureDBsSQLSku{ + Name: src.Spec.Sku.Name, + Tier: SkuTier(src.Spec.Sku.Tier), + Capacity: src.Spec.Sku.Capacity, + Size: src.Spec.Sku.Size, + Family: src.Spec.Sku.Family, + } + dst.Spec.ServerVersion = ServerVersion(src.Spec.ServerVersion) + dst.Spec.SSLEnforcement = SslEnforcementEnum(src.Spec.SSLEnforcement) + dst.Spec.CreateMode = src.Spec.CreateMode + dst.Spec.ReplicaProperties = ReplicaProperties(src.Spec.ReplicaProperties) + dst.Spec.KeyVaultToStoreSecrets = src.Spec.KeyVaultToStoreSecrets + + // Status + dst.Status = ASOStatus(src.Status) + + return nil + +} diff --git a/api/v1alpha1/postgresqlserver_webhook.go b/api/v1alpha1/postgresqlserver_webhook.go new file mode 100644 index 00000000000..1643b209af1 --- /dev/null +++ b/api/v1alpha1/postgresqlserver_webhook.go @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package v1alpha1 + +import ( + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" +) + +// log is for logging in this package. +var postgresqlserverlog = logf.Log.WithName("postgresqlserver-resource") + +func (r *PostgreSQLServer) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! diff --git a/api/v1alpha2/mysqlserver_types.go b/api/v1alpha2/mysqlserver_types.go index 0a05465a285..56dc56949a7 100644 --- a/api/v1alpha2/mysqlserver_types.go +++ b/api/v1alpha2/mysqlserver_types.go @@ -4,90 +4,24 @@ package v1alpha2 import ( - "github.com/Azure/azure-sdk-for-go/services/mysql/mgmt/2017-12-01/mysql" + "github.com/Azure/go-autorest/autorest/to" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. -type AzureDBsSQLSku struct { - // Name - The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. - Name string `json:"name,omitempty"` - // Tier - The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', 'GeneralPurpose', 'MemoryOptimized' - Tier SkuTier `json:"tier,omitempty"` - // Capacity - The scale up/out capacity, representing server's compute units. - Capacity int32 `json:"capacity,omitempty"` - // Size - The size code, to be interpreted by resource as appropriate. - Size string `json:"size,omitempty"` - // Family - The family of hardware. - Family string `json:"family,omitempty"` -} - -// ServerVersion enumerates the values for server version. -type ServerVersion string - -const ( - // NineFullStopFive ... - NineFullStopFive ServerVersion = "9.5" - // NineFullStopSix ... - NineFullStopSix ServerVersion = "9.6" - // OneOne ... - OneOne ServerVersion = "11" - // OneZero ... - OneZero ServerVersion = "10" - // OneZeroFullStopTwo ... - OneZeroFullStopTwo ServerVersion = "10.2" - // OneZeroFullStopZero ... - OneZeroFullStopZero ServerVersion = "10.0" -) - -type SkuTier string - -const ( - // Basic ... - PSQLBasic SkuTier = "Basic" - // GeneralPurpose ... - PSQLGeneralPurpose SkuTier = "GeneralPurpose" - // MemoryOptimized ... - PSQLMemoryOptimized SkuTier = "MemoryOptimized" -) - -type SslEnforcementEnum string - -const ( - // SslEnforcementEnumDisabled ... - SslEnforcementEnumDisabled SslEnforcementEnum = "Disabled" - // SslEnforcementEnumEnabled ... - SslEnforcementEnumEnabled SslEnforcementEnum = "Enabled" -) - -type StorageProfile struct { - // BackupRetentionDays - Backup retention days for the server. - BackupRetentionDays *int32 `json:"backupRetentionDays,omitempty"` - // GeoRedundantBackup - Enable Geo-redundant or not for server backup. Possible values include: 'Enabled', 'Disabled' - GeoRedundantBackup mysql.GeoRedundantBackup `json:"geoRedundantBackup,omitempty"` - // StorageMB - Max storage allowed for a server. - StorageMB *int32 `json:"storageMB,omitempty"` - // StorageAutogrow - Enable Storage Auto Grow. Possible values include: 'StorageAutogrowEnabled', 'StorageAutogrowDisabled' - StorageAutogrow mysql.StorageAutogrow `json:"storageAutogrow,omitempty"` -} - -type ReplicaProperties struct { - SourceServerId string `json:"sourceServerId,omitempty"` -} - // MySQLServerSpec defines the desired state of MySQLServer type MySQLServerSpec struct { - Location string `json:"location"` - ResourceGroup string `json:"resourceGroup,omitempty"` - Sku AzureDBsSQLSku `json:"sku,omitempty"` - ServerVersion ServerVersion `json:"serverVersion,omitempty"` - SSLEnforcement SslEnforcementEnum `json:"sslEnforcement,omitempty"` - CreateMode string `json:"createMode,omitempty"` - ReplicaProperties ReplicaProperties `json:"replicaProperties,omitempty"` - StorageProfile *StorageProfile `json:"storageProfile,omitempty"` - KeyVaultToStoreSecrets string `json:"keyVaultToStoreSecrets,omitempty"` + Location string `json:"location"` + ResourceGroup string `json:"resourceGroup,omitempty"` + Sku AzureDBsSQLSku `json:"sku,omitempty"` + ServerVersion ServerVersion `json:"serverVersion,omitempty"` + SSLEnforcement SslEnforcementEnum `json:"sslEnforcement,omitempty"` + CreateMode string `json:"createMode,omitempty"` + ReplicaProperties ReplicaProperties `json:"replicaProperties,omitempty"` + StorageProfile *MySQLStorageProfile `json:"storageProfile,omitempty"` + KeyVaultToStoreSecrets string `json:"keyVaultToStoreSecrets,omitempty"` } // +kubebuilder:object:root=true @@ -137,6 +71,12 @@ func NewDefaultMySQLServer(name, resourceGroup, location string) *MySQLServer { ServerVersion: ServerVersion("8.0"), SSLEnforcement: SslEnforcementEnumEnabled, CreateMode: "Default", + StorageProfile: &MySQLStorageProfile{ + BackupRetentionDays: to.Int32Ptr(10), + GeoRedundantBackup: "Disabled", + StorageMB: to.Int32Ptr(5120), + StorageAutogrow: "Disabled", + }, }, } } diff --git a/api/v1alpha2/postgresqlserver_conversion.go b/api/v1alpha2/postgresqlserver_conversion.go new file mode 100644 index 00000000000..0cc4042ab2c --- /dev/null +++ b/api/v1alpha2/postgresqlserver_conversion.go @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package v1alpha2 + +func (*PostgreSQLServer) Hub() {} diff --git a/api/v1alpha2/postgresqlserver_types.go b/api/v1alpha2/postgresqlserver_types.go new file mode 100644 index 00000000000..e9b0fab6e2a --- /dev/null +++ b/api/v1alpha2/postgresqlserver_types.go @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// PostgreSQLServerSpec defines the desired state of PostgreSQLServer +type PostgreSQLServerSpec struct { + Location string `json:"location"` + ResourceGroup string `json:"resourceGroup,omitempty"` + Sku AzureDBsSQLSku `json:"sku,omitempty"` + ServerVersion ServerVersion `json:"serverVersion,omitempty"` + SSLEnforcement SslEnforcementEnum `json:"sslEnforcement,omitempty"` + KeyVaultToStoreSecrets string `json:"keyVaultToStoreSecrets,omitempty"` + CreateMode string `json:"createMode,omitempty"` + StorageProfile *PSQLStorageProfile `json:"storageProfile,omitempty"` + ReplicaProperties ReplicaProperties `json:"replicaProperties,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:storageversion + +// PostgreSQLServer is the Schema for the postgresqlservers API +// +kubebuilder:printcolumn:name="Provisioned",type="string",JSONPath=".status.provisioned" +// +kubebuilder:printcolumn:name="Message",type="string",JSONPath=".status.message" +type PostgreSQLServer struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec PostgreSQLServerSpec `json:"spec,omitempty"` + Status ASOStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// PostgreSQLServerList contains a list of PostgreSQLServer +type PostgreSQLServerList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []PostgreSQLServer `json:"items"` +} + +func init() { + SchemeBuilder.Register(&PostgreSQLServer{}, &PostgreSQLServerList{}) +} diff --git a/api/v1alpha2/sharedazuredbs_types.go b/api/v1alpha2/sharedazuredbs_types.go new file mode 100644 index 00000000000..391765e9919 --- /dev/null +++ b/api/v1alpha2/sharedazuredbs_types.go @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package v1alpha2 + +import ( + "github.com/Azure/azure-sdk-for-go/services/mysql/mgmt/2017-12-01/mysql" + psql "github.com/Azure/azure-sdk-for-go/services/postgresql/mgmt/2017-12-01/postgresql" +) + +type AzureDBsSQLSku struct { + // Name - The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. + Name string `json:"name,omitempty"` + // Tier - The tier of the particular SKU, e.g. Basic. Possible values include: 'Basic', 'GeneralPurpose', 'MemoryOptimized' + Tier SkuTier `json:"tier,omitempty"` + // Capacity - The scale up/out capacity, representing server's compute units. + Capacity int32 `json:"capacity,omitempty"` + // Size - The size code, to be interpreted by resource as appropriate. + Size string `json:"size,omitempty"` + // Family - The family of hardware. + Family string `json:"family,omitempty"` +} + +// ServerVersion enumerates the values for server version. +type ServerVersion string + +const ( + // NineFullStopFive ... + NineFullStopFive ServerVersion = "9.5" + // NineFullStopSix ... + NineFullStopSix ServerVersion = "9.6" + // OneOne ... + OneOne ServerVersion = "11" + // OneZero ... + OneZero ServerVersion = "10" + // OneZeroFullStopTwo ... + OneZeroFullStopTwo ServerVersion = "10.2" + // OneZeroFullStopZero ... + OneZeroFullStopZero ServerVersion = "10.0" +) + +type SkuTier string + +const ( + // Basic ... + PSQLBasic SkuTier = "Basic" + // GeneralPurpose ... + PSQLGeneralPurpose SkuTier = "GeneralPurpose" + // MemoryOptimized ... + PSQLMemoryOptimized SkuTier = "MemoryOptimized" +) + +type SslEnforcementEnum string + +const ( + // SslEnforcementEnumDisabled ... + SslEnforcementEnumDisabled SslEnforcementEnum = "Disabled" + // SslEnforcementEnumEnabled ... + SslEnforcementEnumEnabled SslEnforcementEnum = "Enabled" +) + +type MySQLStorageProfile struct { + // BackupRetentionDays - Backup retention days for the server. + BackupRetentionDays *int32 `json:"backupRetentionDays,omitempty"` + // GeoRedundantBackup - Enable Geo-redundant or not for server backup. Possible values include: 'Enabled', 'Disabled' + GeoRedundantBackup mysql.GeoRedundantBackup `json:"geoRedundantBackup,omitempty"` + // StorageMB - Max storage allowed for a server. + StorageMB *int32 `json:"storageMB,omitempty"` + // StorageAutogrow - Enable Storage Auto Grow. Possible values include: 'StorageAutogrowEnabled', 'StorageAutogrowDisabled' + StorageAutogrow mysql.StorageAutogrow `json:"storageAutogrow,omitempty"` +} + +type PSQLStorageProfile struct { + // BackupRetentionDays - Backup retention days for the server. + BackupRetentionDays *int32 `json:"backupRetentionDays,omitempty"` + // GeoRedundantBackup - Enable Geo-redundant or not for server backup. Possible values include: 'Enabled', 'Disabled' + GeoRedundantBackup psql.GeoRedundantBackup `json:"geoRedundantBackup,omitempty"` + // StorageMB - Max storage allowed for a server. + StorageMB *int32 `json:"storageMB,omitempty"` + // StorageAutogrow - Enable Storage Auto Grow. Possible values include: 'StorageAutogrowEnabled', 'StorageAutogrowDisabled' + StorageAutogrow psql.StorageAutogrow `json:"storageAutogrow,omitempty"` +} + +type ReplicaProperties struct { + SourceServerId string `json:"sourceServerId,omitempty"` +} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index ed5b82d2f5b..99feaa910e7 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -55,7 +55,7 @@ patches: - patches/webhook_in_azuresqlfailovergroups.yaml - patches/webhook_in_blobcontainers.yaml #- patches/webhook_in_appinsights.yaml -#- patches/webhook_in_postgresqlservers.yaml +- patches/webhook_in_postgresqlservers.yaml #- patches/webhook_in_postgresqldatabases.yaml #- patches/webhook_in_postgresqlfirewallrules.yaml #- patches/webhook_in_postgresqlvnetrules.yaml @@ -64,7 +64,7 @@ patches: #- patches/webhook_in_virtualnetworks.yaml #- patches/webhook_in_keyvaultkeys.yaml #- patches/webhook_in_azuresqlvnetrules.yaml -#- patches/webhook_in_mysqlservers.yaml +- patches/webhook_in_mysqlservers.yaml #- patches/webhook_in_mysqldatabases.yaml #- patches/webhook_in_mysqlfirewallrules.yaml #- patches/webhook_in_storageaccounts.yaml @@ -91,7 +91,7 @@ patches: - patches/cainjection_in_azuresqlfailovergroups.yaml - patches/cainjection_in_blobcontainers.yaml #- patches/cainjection_in_appinsights.yaml -#- patches/cainjection_in_postgresqlservers.yaml +- patches/cainjection_in_postgresqlservers.yaml #- patches/cainjection_in_postgresqldatabases.yaml #- patches/cainjection_in_postgresqlfirewallrules.yaml #- patches/cainjection_in_postgresqlvnetrules.yaml @@ -100,7 +100,7 @@ patches: #- patches/cainjection_in_virtualnetworks.yaml #- patches/cainjection_in_keyvaultkeys.yaml #- patches/cainjection_in_azuresqlvnetrules.yaml -#- patches/cainjection_in_mysqlservers.yaml +- patches/cainjection_in_mysqlservers.yaml #- patches/cainjection_in_mysqldatabases.yaml #- patches/cainjection_in_mysqlfirewallrules.yaml #- patches/cainjection_in_storageaccounts.yaml diff --git a/config/crd/patches/cainjection_in_mysqlservers.yaml b/config/crd/patches/cainjection_in_mysqlservers.yaml index eb156449204..09ab69332b9 100644 --- a/config/crd/patches/cainjection_in_mysqlservers.yaml +++ b/config/crd/patches/cainjection_in_mysqlservers.yaml @@ -4,5 +4,5 @@ apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: annotations: - certmanager.k8s.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) name: mysqlservers.azure.microsoft.com diff --git a/config/crd/patches/webhook_in_mysqlservers.yaml b/config/crd/patches/webhook_in_mysqlservers.yaml index 0e5a1fddb11..931c1ca3b04 100644 --- a/config/crd/patches/webhook_in_mysqlservers.yaml +++ b/config/crd/patches/webhook_in_mysqlservers.yaml @@ -5,6 +5,7 @@ kind: CustomResourceDefinition metadata: name: mysqlservers.azure.microsoft.com spec: + preserveUnknownFields: false conversion: strategy: Webhook webhookClientConfig: diff --git a/config/crd/patches/webhook_in_postgresqldatabases.yaml b/config/crd/patches/webhook_in_postgresqldatabases.yaml index 24fe80d4bbb..b664b01795c 100644 --- a/config/crd/patches/webhook_in_postgresqldatabases.yaml +++ b/config/crd/patches/webhook_in_postgresqldatabases.yaml @@ -5,6 +5,7 @@ kind: CustomResourceDefinition metadata: name: postgresqldatabases.azure.microsoft.com spec: + preserveUnknownFields: false conversion: strategy: Webhook webhookClientConfig: diff --git a/config/crd/patches/webhook_in_postgresqlservers.yaml b/config/crd/patches/webhook_in_postgresqlservers.yaml index 94970f10763..d47eeb4e7ab 100644 --- a/config/crd/patches/webhook_in_postgresqlservers.yaml +++ b/config/crd/patches/webhook_in_postgresqlservers.yaml @@ -5,6 +5,7 @@ kind: CustomResourceDefinition metadata: name: postgresqlservers.azure.microsoft.com spec: + preserveUnknownFields: false conversion: strategy: Webhook webhookClientConfig: diff --git a/config/default/manager_image_patch.yaml b/config/default/manager_image_patch.yaml index 4a3ddd7410b..9816777d797 100644 --- a/config/default/manager_image_patch.yaml +++ b/config/default/manager_image_patch.yaml @@ -8,7 +8,7 @@ spec: spec: containers: # Change the value of image field below to your controller image URL - - image: controller:latest + - image: docker.io/frodopwns/op6:26 name: manager env: - name: AZURE_CLIENT_ID diff --git a/config/samples/azure_v1alpha1_mysqlserver.yaml b/config/samples/azure_v1alpha1_mysqlserver.yaml index 05d543e51f2..7d0ed854e02 100644 --- a/config/samples/azure_v1alpha1_mysqlserver.yaml +++ b/config/samples/azure_v1alpha1_mysqlserver.yaml @@ -7,8 +7,6 @@ spec: resourceGroup: resourcegroup-azure-operators serverVersion: "8.0" sslEnforcement: Enabled - minimalTLSVersion: TLS10 # Possible values include: 'TLS10', 'TLS11', 'TLS12', 'Disabled' - infrastructureEncryption: Enabled # Possible values include: Enabled, Disabled createMode: Default # Possible values include: Default, Replica, PointInTimeRestore (not implemented), GeoRestore (not implemented) sku: name: GP_Gen5_4 # tier + family + cores eg. - B_Gen4_1, GP_Gen5_4 diff --git a/config/samples/azure_v1alpha2_mysqlserver.yaml b/config/samples/azure_v1alpha2_mysqlserver.yaml index f96ed87e9d1..676cbde19da 100644 --- a/config/samples/azure_v1alpha2_mysqlserver.yaml +++ b/config/samples/azure_v1alpha2_mysqlserver.yaml @@ -1,14 +1,12 @@ apiVersion: azure.microsoft.com/v1alpha2 kind: MySQLServer metadata: - name: mysqlserver-verztest2 + name: mysqlserver-sample spec: location: eastus2 - resourceGroup: resourcegroup-mysqlverz + resourceGroup: resourcegroup-azure-operators serverVersion: "8.0" sslEnforcement: Enabled - minimalTLSVersion: TLS10 # Possible values include: 'TLS10', 'TLS11', 'TLS12', 'Disabled' - infrastructureEncryption: Enabled # Possible values include: Enabled, Disabled createMode: Default # Possible values include: Default, Replica, PointInTimeRestore (not implemented), GeoRestore (not implemented) sku: name: GP_Gen5_4 # tier + family + cores eg. - B_Gen4_1, GP_Gen5_4 @@ -17,9 +15,9 @@ spec: size: "51200" capacity: 4 # Optional Backup Retention Config - storageProfile: - backupRetentionDays: 10 - geoRedundantBackup: Disabled # or Enabled - storageMB: 200 # max storage - storageAutogrow: Disabled # or Enabled + # storageProfile: + # backupRetentionDays: 10 + # geoRedundantBackup: Enabled # Disabled or Enabled + # storageMB: 5120 # max storage - minimum of 5120 MB and additional increments of 1024 MB up to maximum of 16777216 MB + # storageAutogrow: Enabled # Disabled or Enabled \ No newline at end of file diff --git a/config/samples/azure_v1alpha2_postgresqlserver.yaml b/config/samples/azure_v1alpha2_postgresqlserver.yaml new file mode 100644 index 00000000000..a0c4a3d3a0d --- /dev/null +++ b/config/samples/azure_v1alpha2_postgresqlserver.yaml @@ -0,0 +1,26 @@ +apiVersion: azure.microsoft.com/v1alpha2 +kind: PostgreSQLServer +metadata: + name: postgresqlserver-sample +spec: + location: eastus + resourceGroup: resourcegroup-azure-operators + serverVersion: "10" + sslEnforcement: Enabled + createMode: Default # Possible values include: Default, Replica, PointInTimeRestore (not implemented), GeoRestore (not implemented) + sku: + name: GP_Gen5_4 # Name - The name of the sku, typically, tier + family + cores, e.g. B_Gen4_1, GP_Gen5_8. + tier: GeneralPurpose # possible values - 'Basic', 'GeneralPurpose', 'MemoryOptimized' + family: Gen5 + size: "51200" + capacity: 4 + # Use the field below to optionally specify a different keyvault + # to store the server admin credential secrets in + #keyVaultToStoreSecrets: asoSecretKeyVault + # Optional Backup Retention Config + # storageProfile: + # backupRetentionDays: 10 + # geoRedundantBackup: Enabled # Disabled or Enabled + # storageMB: 5120 # max storage - minimum of 5120 MB and additional increments of 1024 MB up to maximum of 16777216 MB + # storageAutogrow: Enabled # Disabled or Enabled + \ No newline at end of file diff --git a/controllers/mysql_combined_test.go b/controllers/mysql_combined_test.go index 1b118d19489..4d5623e3a18 100644 --- a/controllers/mysql_combined_test.go +++ b/controllers/mysql_combined_test.go @@ -33,6 +33,7 @@ func TestMySQLHappyPath(t *testing.T) { // Create a mySQL replica mySQLReplicaInstance := v1alpha2.NewReplicaMySQLServer(mySQLReplicaName, rgName, rgLocation, mySQLServerInstance.Status.ResourceId) + mySQLReplicaInstance.Spec.StorageProfile = nil EnsureInstance(ctx, t, tc, mySQLReplicaInstance) diff --git a/controllers/mysqlserver_controller_test.go b/controllers/mysqlserver_controller_test.go index 41786957192..3bb036c7aaf 100644 --- a/controllers/mysqlserver_controller_test.go +++ b/controllers/mysqlserver_controller_test.go @@ -9,7 +9,7 @@ import ( "context" "testing" - azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" + "github.com/Azure/azure-service-operator/api/v1alpha2" "github.com/Azure/azure-service-operator/pkg/errhelp" ) @@ -24,7 +24,7 @@ func TestMySQLServerControllerNoResourceGroup(t *testing.T) { mySQLServerName := GenerateTestResourceNameWithRandom("mysql-srv", 10) // Create the mySQLServer object and expect the Reconcile to be created - mySQLServerInstance := azurev1alpha1.NewDefaultMySQLServer(mySQLServerName, rgName, rgLocation) + mySQLServerInstance := v1alpha2.NewDefaultMySQLServer(mySQLServerName, rgName, rgLocation) EnsureInstanceWithResult(ctx, t, tc, mySQLServerInstance, errhelp.ResourceGroupNotFoundErrorCode, false) EnsureDelete(ctx, t, tc, mySQLServerInstance) @@ -41,7 +41,7 @@ func TestMySQLServerControllerBadLocation(t *testing.T) { mySQLServerName := GenerateTestResourceNameWithRandom("mysql-srv", 10) // Create the mySQLServer object and expect the Reconcile to be created - mySQLServerInstance := azurev1alpha1.NewDefaultMySQLServer(mySQLServerName, rgName, rgLocation) + mySQLServerInstance := v1alpha2.NewDefaultMySQLServer(mySQLServerName, rgName, rgLocation) EnsureInstanceWithResult(ctx, t, tc, mySQLServerInstance, errhelp.InvalidResourceLocation, false) EnsureDelete(ctx, t, tc, mySQLServerInstance) diff --git a/controllers/postgresql_combined_controller_test.go b/controllers/postgresql_combined_controller_test.go index 5ee9509d6e9..d4700ba5c07 100644 --- a/controllers/postgresql_combined_controller_test.go +++ b/controllers/postgresql_combined_controller_test.go @@ -10,6 +10,8 @@ import ( "testing" azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" + "github.com/Azure/azure-service-operator/api/v1alpha2" + "github.com/Azure/go-autorest/autorest/to" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -21,7 +23,7 @@ func TestPSQLDatabaseController(t *testing.T) { var rgName string var rgLocation string var postgreSQLServerName string - var postgreSQLServerInstance *azurev1alpha1.PostgreSQLServer + var postgreSQLServerInstance *v1alpha2.PostgreSQLServer // Add any setup steps that needs to be executed before each test rgName = tc.resourceGroupName @@ -30,24 +32,30 @@ func TestPSQLDatabaseController(t *testing.T) { postgreSQLServerName = GenerateTestResourceNameWithRandom("psql-srv", 10) // Create the PostgreSQLServer object and expect the Reconcile to be created - postgreSQLServerInstance = &azurev1alpha1.PostgreSQLServer{ + postgreSQLServerInstance = &v1alpha2.PostgreSQLServer{ ObjectMeta: metav1.ObjectMeta{ Name: postgreSQLServerName, Namespace: "default", }, - Spec: azurev1alpha1.PostgreSQLServerSpec{ + Spec: v1alpha2.PostgreSQLServerSpec{ Location: rgLocation, ResourceGroup: rgName, CreateMode: "Default", - Sku: azurev1alpha1.AzureDBsSQLSku{ + Sku: v1alpha2.AzureDBsSQLSku{ Name: "GP_Gen5_4", - Tier: azurev1alpha1.SkuTier("GeneralPurpose"), + Tier: v1alpha2.SkuTier("GeneralPurpose"), Family: "Gen5", Size: "51200", Capacity: 4, }, - ServerVersion: azurev1alpha1.ServerVersion("10"), - SSLEnforcement: azurev1alpha1.SslEnforcementEnumEnabled, + ServerVersion: v1alpha2.ServerVersion("10"), + SSLEnforcement: v1alpha2.SslEnforcementEnumEnabled, + StorageProfile: &v1alpha2.PSQLStorageProfile{ + BackupRetentionDays: to.Int32Ptr(10), + GeoRedundantBackup: "Disabled", + StorageMB: to.Int32Ptr(5120), + StorageAutogrow: "Disabled", + }, }, } diff --git a/controllers/postgresqlserver_controller.go b/controllers/postgresqlserver_controller.go index 32479b82257..db00fc06488 100644 --- a/controllers/postgresqlserver_controller.go +++ b/controllers/postgresqlserver_controller.go @@ -4,9 +4,8 @@ package controllers import ( + "github.com/Azure/azure-service-operator/api/v1alpha2" ctrl "sigs.k8s.io/controller-runtime" - - azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" ) // PostgreSQLServerReconciler reconciles a PostgreSQLServer object @@ -18,11 +17,11 @@ type PostgreSQLServerReconciler struct { // +kubebuilder:rbac:groups=azure.microsoft.com,resources=postgresqlservers/status,verbs=get;update;patch func (r *PostgreSQLServerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { - return r.Reconciler.Reconcile(req, &azurev1alpha1.PostgreSQLServer{}) + return r.Reconciler.Reconcile(req, &v1alpha2.PostgreSQLServer{}) } func (r *PostgreSQLServerReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&azurev1alpha1.PostgreSQLServer{}). + For(&v1alpha2.PostgreSQLServer{}). Complete(r) } diff --git a/controllers/postgresqlserver_controller_test.go b/controllers/postgresqlserver_controller_test.go index db123fe98b0..c4a84a501dc 100644 --- a/controllers/postgresqlserver_controller_test.go +++ b/controllers/postgresqlserver_controller_test.go @@ -9,7 +9,7 @@ import ( "context" "testing" - azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" + "github.com/Azure/azure-service-operator/api/v1alpha2" "github.com/Azure/azure-service-operator/pkg/errhelp" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -27,23 +27,23 @@ func TestPSQLServerControllerNoResourceGroup(t *testing.T) { postgreSQLServerName := GenerateTestResourceNameWithRandom("psql-srv", 10) // Create the PostgreSQLServer object and expect the Reconcile to be created - postgreSQLServerInstance := &azurev1alpha1.PostgreSQLServer{ + postgreSQLServerInstance := &v1alpha2.PostgreSQLServer{ ObjectMeta: metav1.ObjectMeta{ Name: postgreSQLServerName, Namespace: "default", }, - Spec: azurev1alpha1.PostgreSQLServerSpec{ + Spec: v1alpha2.PostgreSQLServerSpec{ Location: rgLocation, ResourceGroup: rgName, - Sku: azurev1alpha1.AzureDBsSQLSku{ + Sku: v1alpha2.AzureDBsSQLSku{ Name: "B_Gen5_2", - Tier: azurev1alpha1.SkuTier("Basic"), + Tier: v1alpha2.SkuTier("Basic"), Family: "Gen5", Size: "51200", Capacity: 2, }, - ServerVersion: azurev1alpha1.ServerVersion("10"), - SSLEnforcement: azurev1alpha1.SslEnforcementEnumEnabled, + ServerVersion: v1alpha2.ServerVersion("10"), + SSLEnforcement: v1alpha2.SslEnforcementEnumEnabled, }, } EnsureInstanceWithResult(ctx, t, tc, postgreSQLServerInstance, errhelp.ResourceGroupNotFoundErrorCode, false) @@ -64,12 +64,12 @@ func TestPSQLServerControllerReplicaNoSourceServer(t *testing.T) { // Create the PostgreSQL Replica Server object and expect the Reconcile to be created - postgreSQLServerReplicaInstance := &azurev1alpha1.PostgreSQLServer{ + postgreSQLServerReplicaInstance := &v1alpha2.PostgreSQLServer{ ObjectMeta: metav1.ObjectMeta{ Name: postgreSQLServerReplicaName, Namespace: "default", }, - Spec: azurev1alpha1.PostgreSQLServerSpec{ + Spec: v1alpha2.PostgreSQLServerSpec{ Location: rgLocation, ResourceGroup: rgName, CreateMode: "Replica", diff --git a/main.go b/main.go index 4ee5f851f0a..1027341fc36 100644 --- a/main.go +++ b/main.go @@ -779,6 +779,10 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "MySQLServer") os.Exit(1) } + if err = (&azurev1alpha1.PostgreSQLServer{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "PostgreSQLServer") + os.Exit(1) + } // +kubebuilder:scaffold:builder setupLog.Info("starting manager") diff --git a/pkg/resourcemanager/mysql/server/client.go b/pkg/resourcemanager/mysql/server/client.go index d6fb58241e8..933ac600609 100644 --- a/pkg/resourcemanager/mysql/server/client.go +++ b/pkg/resourcemanager/mysql/server/client.go @@ -8,6 +8,7 @@ import ( "strings" mysql "github.com/Azure/azure-sdk-for-go/services/mysql/mgmt/2017-12-01/mysql" + "github.com/Azure/azure-service-operator/api/v1alpha2" "github.com/Azure/azure-service-operator/pkg/resourcemanager/config" "github.com/Azure/azure-service-operator/pkg/resourcemanager/iam" "github.com/Azure/azure-service-operator/pkg/secrets" @@ -61,12 +62,12 @@ func (m *MySQLServerClient) CheckServerNameAvailability(ctx context.Context, ser } -func (m *MySQLServerClient) CreateServerIfValid(ctx context.Context, servername string, resourcegroup string, location string, tags map[string]*string, serverversion mysql.ServerVersion, sslenforcement mysql.SslEnforcementEnum, skuInfo mysql.Sku, adminlogin string, adminpassword string, createmode string, sourceserver string) (pollingURL string, server mysql.Server, err error) { +func (m *MySQLServerClient) CreateServerIfValid(ctx context.Context, instance v1alpha2.MySQLServer, tags map[string]*string, skuInfo mysql.Sku, adminlogin string, adminpassword string, createmode string) (pollingURL string, server mysql.Server, err error) { client := getMySQLServersClient() // Check if name is valid if this is the first create call - valid, err := m.CheckServerNameAvailability(ctx, servername) + valid, err := m.CheckServerNameAvailability(ctx, instance.Name) if !valid { return "", server, err } @@ -74,32 +75,37 @@ func (m *MySQLServerClient) CreateServerIfValid(ctx context.Context, servername var result mysql.ServersCreateFuture var serverProperties mysql.BasicServerPropertiesForCreate var skuData *mysql.Sku + var storageProfile *mysql.StorageProfile + if instance.Spec.StorageProfile != nil { + obj := mysql.StorageProfile(*instance.Spec.StorageProfile) + storageProfile = &obj + } if strings.EqualFold(createmode, "replica") { serverProperties = &mysql.ServerPropertiesForReplica{ - SourceServerID: to.StringPtr(sourceserver), + SourceServerID: to.StringPtr(instance.Spec.ReplicaProperties.SourceServerId), CreateMode: mysql.CreateModeReplica, + StorageProfile: storageProfile, } } else { serverProperties = &mysql.ServerPropertiesForDefaultCreate{ AdministratorLogin: &adminlogin, AdministratorLoginPassword: &adminpassword, - Version: serverversion, - SslEnforcement: sslenforcement, - //StorageProfile: &mysql.StorageProfile{}, - CreateMode: mysql.CreateModeServerPropertiesForCreate, + Version: mysql.ServerVersion(instance.Spec.ServerVersion), + SslEnforcement: mysql.SslEnforcementEnum(instance.Spec.SSLEnforcement), + CreateMode: mysql.CreateModeServerPropertiesForCreate, + StorageProfile: storageProfile, } skuData = &skuInfo - } result, _ = client.Create( ctx, - resourcegroup, - servername, + instance.Spec.ResourceGroup, + instance.Name, mysql.ServerForCreate{ - Location: &location, + Location: &instance.Spec.Location, Tags: tags, Properties: serverProperties, Sku: skuData, diff --git a/pkg/resourcemanager/mysql/server/reconcile.go b/pkg/resourcemanager/mysql/server/reconcile.go index 789e5ddf825..b3650b375ca 100644 --- a/pkg/resourcemanager/mysql/server/reconcile.go +++ b/pkg/resourcemanager/mysql/server/reconcile.go @@ -133,17 +133,12 @@ func (m *MySQLServerClient) Ensure(ctx context.Context, obj runtime.Object, opts pollURL, server, err := m.CreateServerIfValid( ctx, - instance.Name, - instance.Spec.ResourceGroup, - instance.Spec.Location, + *instance, labels, - mysql.ServerVersion(instance.Spec.ServerVersion), - mysql.SslEnforcementEnum(instance.Spec.SSLEnforcement), skuInfo, adminlogin, adminpassword, createmode, - instance.Spec.ReplicaProperties.SourceServerId, ) if err != nil { // let the user know what happened diff --git a/pkg/resourcemanager/psql/database/database_test.go b/pkg/resourcemanager/psql/database/database_test.go deleted file mode 100644 index 91016ef593e..00000000000 --- a/pkg/resourcemanager/psql/database/database_test.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -package database - -import ( - "fmt" - "time" - - psql "github.com/Azure/azure-sdk-for-go/services/postgresql/mgmt/2017-12-01/postgresql" - "github.com/Azure/azure-service-operator/pkg/errhelp" - helpers "github.com/Azure/azure-service-operator/pkg/helpers" - server "github.com/Azure/azure-service-operator/pkg/resourcemanager/psql/server" - "github.com/Azure/go-autorest/autorest/to" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("PSQL database", func() { - - var rgName string - var location string - var psqlServer string - var PSQLServerManager server.PostgreSQLServerManager - var PSQLDatabaseManager PostgreSQLDatabaseManager - - BeforeEach(func() { - // Add any setup steps that needs to be executed before each test - rgName = tc.ResourceGroupName - location = tc.ResourceGroupLocation - PSQLServerManager = tc.postgreSQLServerManager - PSQLDatabaseManager = tc.postgreSQLDatabaseManager - - // Create PSQL server - psqlServer = "t-dev-psql-srv-" + helpers.RandomString(10) - - pSQLSku := psql.Sku{ - Name: to.StringPtr("B_Gen5_2"), - Tier: psql.SkuTier("Basic"), - Capacity: to.Int32Ptr(2), - Size: to.StringPtr("51200"), - Family: to.StringPtr("Gen5"), - } - tags := map[string]*string{ - "tag1": to.StringPtr("value1"), - "tag2": to.StringPtr("value2"), - } - - // Create PSQL server instance - Eventually(func() bool { - time.Sleep(3 * time.Second) - _, err := PSQLServerManager.GetServer(ctx, rgName, psqlServer) - if err == nil { - return true - } - _, _, err = PSQLServerManager.CreateServerIfValid( - ctx, - psqlServer, - rgName, - location, - tags, - psql.OneZero, - psql.SslEnforcementEnumEnabled, - pSQLSku, - "adm1nus3r", - "m@#terU$3r", - "", - "", - ) - if err != nil { - fmt.Println(err.Error()) - if !errhelp.IsAsynchronousOperationNotComplete(err) { - fmt.Println("error occured") - return false - } - } - return true - }, tc.timeout, tc.retryInterval, - ).Should(BeTrue()) - - }) - - AfterEach(func() { - // Add any teardown steps that needs to be executed after each test - // Delete PSQL server - Eventually(func() bool { - time.Sleep(3 * time.Second) - _, err := PSQLServerManager.GetServer(ctx, rgName, psqlServer) - if err != nil { - return true - } - _, err = PSQLServerManager.DeleteServer(ctx, psqlServer, rgName) - if err != nil { - fmt.Println(err.Error()) - if !errhelp.IsAsynchronousOperationNotComplete(err) { - fmt.Println("error occured") - return false - } - } - return err == nil - }, tc.timeout, tc.retryInterval, - ).Should(BeTrue()) - }) - - // Add Tests for OpenAPI validation (or additonal CRD features) specified in - // your API definition. - // Avoid adding tests for vanilla CRUD operations because they would - // test Kubernetes API server, which isn't the goal here. - - Context("Create and Delete", func() { - It("should create and delete PSQL database in azure", func() { - - defer GinkgoRecover() - - psqlDatabase := "t-dev-psql-db-" + helpers.RandomString(10) - - // Create PSQL database instance - Eventually(func() bool { - time.Sleep(3 * time.Second) - _, err := PSQLDatabaseManager.GetDatabase(ctx, rgName, psqlServer, psqlDatabase) - if err == nil { - return true - } - _, err = PSQLDatabaseManager.CreateDatabaseIfValid(ctx, psqlDatabase, psqlServer, rgName) - if err != nil { - fmt.Println(err.Error()) - if !errhelp.IsAsynchronousOperationNotComplete(err) { - fmt.Println("error occured") - return false - } - } - return true - }, tc.timeout, tc.retryInterval, - ).Should(BeTrue()) - - time.Sleep(5 * time.Minute) - - // Delete PSQL database instance - Eventually(func() bool { - time.Sleep(3 * time.Second) - _, err := PSQLDatabaseManager.GetDatabase(ctx, rgName, psqlServer, psqlDatabase) - if err != nil { - return true - } - _, err = PSQLDatabaseManager.DeleteDatabase(ctx, psqlDatabase, psqlServer, rgName) - if err != nil { - fmt.Println(err.Error()) - if !errhelp.IsAsynchronousOperationNotComplete(err) { - fmt.Println("error occured") - return false - } - } - return err == nil - }, tc.timeout, tc.retryInterval, - ).Should(BeTrue()) - }) - - }) -}) diff --git a/pkg/resourcemanager/psql/firewallrule/firewallrule_test.go b/pkg/resourcemanager/psql/firewallrule/firewallrule_test.go deleted file mode 100644 index a9481a326e0..00000000000 --- a/pkg/resourcemanager/psql/firewallrule/firewallrule_test.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -package server - -import ( - "fmt" - "time" - - psql "github.com/Azure/azure-sdk-for-go/services/postgresql/mgmt/2017-12-01/postgresql" - "github.com/Azure/azure-service-operator/pkg/errhelp" - helpers "github.com/Azure/azure-service-operator/pkg/helpers" - server "github.com/Azure/azure-service-operator/pkg/resourcemanager/psql/server" - "github.com/Azure/go-autorest/autorest/to" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("PSQL server", func() { - - var rgName string - var location string - var psqlServer string - var PSQLServerManager server.PostgreSQLServerManager - var PSQLFirewallRuleManager PostgreSQLFirewallRuleManager - - BeforeEach(func() { - // Add any setup steps that needs to be executed before each test - rgName = tc.ResourceGroupName - location = tc.ResourceGroupLocation - PSQLServerManager = tc.postgreSQLServerManager - PSQLFirewallRuleManager = tc.postgreSQLFirewallRuleManager - - // Create PSQL server - psqlServer = "t-dev-psql-srv-" + helpers.RandomString(10) - - pSQLSku := psql.Sku{ - Name: to.StringPtr("B_Gen5_2"), - Tier: psql.SkuTier("Basic"), - Capacity: to.Int32Ptr(2), - Size: to.StringPtr("51200"), - Family: to.StringPtr("Gen5"), - } - tags := map[string]*string{ - "tag1": to.StringPtr("value1"), - "tag2": to.StringPtr("value2"), - } - - // Create PSQL server instance - Eventually(func() bool { - time.Sleep(3 * time.Second) - _, err := PSQLServerManager.GetServer(ctx, rgName, psqlServer) - if err == nil { - return true - } - _, _, err = PSQLServerManager.CreateServerIfValid( - ctx, - psqlServer, - rgName, - location, - tags, - psql.OneZero, - psql.SslEnforcementEnumEnabled, - pSQLSku, - "adm1nus3r", - "m@#terU$3r", - "", - "", - ) - if err != nil { - fmt.Println(err.Error()) - if !errhelp.IsAsynchronousOperationNotComplete(err) { - fmt.Println("error occured") - return false - } - } - return true - }, tc.timeout, tc.retryInterval, - ).Should(BeTrue()) - - }) - - AfterEach(func() { - // Add any teardown steps that needs to be executed after each test - // Delete PSQL server - Eventually(func() bool { - time.Sleep(3 * time.Second) - _, err := PSQLServerManager.GetServer(ctx, rgName, psqlServer) - if err != nil { - return true - } - _, err = PSQLServerManager.DeleteServer(ctx, psqlServer, rgName) - if err != nil { - fmt.Println(err.Error()) - if !errhelp.IsAsynchronousOperationNotComplete(err) { - fmt.Println("error occured") - return false - } - } - return err == nil - }, tc.timeout, tc.retryInterval, - ).Should(BeTrue()) - }) - - // Add Tests for OpenAPI validation (or additonal CRD features) specified in - // your API definition. - // Avoid adding tests for vanilla CRUD operations because they would - // test Kubernetes API server, which isn't the goal here. - - Context("Create and Delete", func() { - It("should create and delete firewall rule on a PSQL server in azure", func() { - - defer GinkgoRecover() - - psqlFirewallRule := "t-dev-psql-fwrule-" + helpers.RandomString(10) - - // Create PSQL firewall rule - Eventually(func() bool { - time.Sleep(3 * time.Second) - _, err := PSQLFirewallRuleManager.GetFirewallRule(ctx, rgName, psqlServer, psqlFirewallRule) - if err == nil { - return true - } - _, err = PSQLFirewallRuleManager.CreateFirewallRule(ctx, rgName, psqlServer, psqlFirewallRule, "0.0.0.0", "0.0.0.0") - if err != nil { - fmt.Println(err.Error()) - if !errhelp.IsAsynchronousOperationNotComplete(err) { - fmt.Println("error occured") - return false - } - } - return true - }, tc.timeout, tc.retryInterval, - ).Should(BeTrue()) - - time.Sleep(5 * time.Minute) - - // Delete PSQL firewall rule - Eventually(func() bool { - time.Sleep(3 * time.Second) - _, err := PSQLFirewallRuleManager.GetFirewallRule(ctx, rgName, psqlServer, psqlFirewallRule) - if err != nil { - return true - } - _, err = PSQLFirewallRuleManager.DeleteFirewallRule(ctx, rgName, psqlServer, psqlFirewallRule) - if err != nil { - fmt.Println(err.Error()) - if !errhelp.IsAsynchronousOperationNotComplete(err) { - fmt.Println("error occured") - return false - } - } - return err == nil - }, tc.timeout, tc.retryInterval, - ).Should(BeTrue()) - - }) - - }) -}) diff --git a/pkg/resourcemanager/psql/firewallrule/suite_test.go b/pkg/resourcemanager/psql/firewallrule/suite_test.go deleted file mode 100644 index b19fd81155c..00000000000 --- a/pkg/resourcemanager/psql/firewallrule/suite_test.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -package server - -import ( - "testing" - "time" - - "github.com/Azure/azure-service-operator/pkg/errhelp" - resourcemanagerconfig "github.com/Azure/azure-service-operator/pkg/resourcemanager/config" - - resourcegroupsresourcemanager "github.com/Azure/azure-service-operator/pkg/resourcemanager/resourcegroups" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "context" - - "github.com/Azure/azure-service-operator/pkg/helpers" - server "github.com/Azure/azure-service-operator/pkg/resourcemanager/psql/server" - // +kubebuilder:scaffold:imports -) - -// These tests use Ginkgo (BDD-style Go testing framework). Refer to -// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. - -type TestContext struct { - ResourceGroupName string - ResourceGroupLocation string - postgreSQLServerManager server.PostgreSQLServerManager - postgreSQLFirewallRuleManager PostgreSQLFirewallRuleManager - ResourceGroupManager resourcegroupsresourcemanager.ResourceGroupManager - timeout time.Duration - retryInterval time.Duration -} - -var tc TestContext -var ctx context.Context - -func TestAPIs(t *testing.T) { - t.Parallel() - RegisterFailHandler(Fail) - RunSpecs(t, "PSQL Firewall Rule Suite") -} - -var _ = BeforeSuite(func() { - - By("bootstrapping test environment") - - ctx = context.Background() - err := resourcemanagerconfig.ParseEnvironment() - Expect(err).ToNot(HaveOccurred()) - - resourceGroupName := "t-rg-dev-psql-" + helpers.RandomString(10) - resourceGroupLocation := resourcemanagerconfig.DefaultLocation() - resourceGroupManager := resourcegroupsresourcemanager.NewAzureResourceGroupManager() - - //create resourcegroup for this suite - _, err = resourceGroupManager.CreateGroup(ctx, resourceGroupName, resourceGroupLocation) - Expect(err).ToNot(HaveOccurred()) - - tc = TestContext{ - ResourceGroupName: resourceGroupName, - ResourceGroupLocation: resourceGroupLocation, - postgreSQLServerManager: &server.PSQLServerClient{}, - postgreSQLFirewallRuleManager: &PSQLFirewallRuleClient{}, - ResourceGroupManager: resourceGroupManager, - timeout: 20 * time.Minute, - retryInterval: 3 * time.Second, - } -}) - -var _ = AfterSuite(func() { - By("tearing down the test environment") - // delete the resource group and contained resources - _, err := tc.ResourceGroupManager.DeleteGroup(ctx, tc.ResourceGroupName) - if !errhelp.IsAsynchronousOperationNotComplete(err) { - return - } - - for { - time.Sleep(time.Second * 10) - _, err := resourcegroupsresourcemanager.GetGroup(ctx, tc.ResourceGroupName) - if err == nil { - } else { - if errhelp.IsGroupNotFound(err) { - break - } else { - return - } - } - } -}) diff --git a/pkg/resourcemanager/psql/server/server.go b/pkg/resourcemanager/psql/server/server.go index 54a16d4ffee..13c457f5ca2 100644 --- a/pkg/resourcemanager/psql/server/server.go +++ b/pkg/resourcemanager/psql/server/server.go @@ -9,7 +9,7 @@ import ( "strings" psql "github.com/Azure/azure-sdk-for-go/services/postgresql/mgmt/2017-12-01/postgresql" - azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" + "github.com/Azure/azure-service-operator/api/v1alpha2" "github.com/Azure/azure-service-operator/pkg/helpers" "github.com/Azure/azure-service-operator/pkg/resourcemanager/config" "github.com/Azure/azure-service-operator/pkg/resourcemanager/iam" @@ -75,16 +75,11 @@ func (p *PSQLServerClient) CheckServerNameAvailability(ctx context.Context, serv } func (p *PSQLServerClient) CreateServerIfValid(ctx context.Context, - servername string, - resourcegroup string, - location string, + instance v1alpha2.PostgreSQLServer, tags map[string]*string, - serverversion psql.ServerVersion, - sslenforcement psql.SslEnforcementEnum, skuInfo psql.Sku, adminlogin string, adminpassword string, - createmode string, - sourceserver string) (pollingURL string, server psql.Server, err error) { + createmode string) (pollingURL string, server psql.Server, err error) { client, err := getPSQLServersClient() if err != nil { @@ -92,51 +87,54 @@ func (p *PSQLServerClient) CreateServerIfValid(ctx context.Context, } // Check if name is valid if this is the first create call - valid, err := p.CheckServerNameAvailability(ctx, servername) + valid, err := p.CheckServerNameAvailability(ctx, instance.Name) if !valid { return "", psql.Server{}, err } var result psql.ServersCreateFuture + var serverProperties psql.BasicServerPropertiesForCreate + var skuData *psql.Sku + var storageProfile *psql.StorageProfile + if instance.Spec.StorageProfile != nil { + obj := psql.StorageProfile(*instance.Spec.StorageProfile) + storageProfile = &obj + } if strings.EqualFold(createmode, string(psql.CreateModeReplica)) { - result, err = client.Create( - ctx, - resourcegroup, - servername, - psql.ServerForCreate{ - Location: &location, - Tags: tags, - Properties: &psql.ServerPropertiesForReplica{ - SourceServerID: to.StringPtr(sourceserver), - CreateMode: psql.CreateModeReplica, - }, - }, - ) - } else { - result, err = client.Create( - ctx, - resourcegroup, - servername, - psql.ServerForCreate{ - Location: &location, - Tags: tags, - Properties: &psql.ServerPropertiesForDefaultCreate{ - AdministratorLogin: &adminlogin, - AdministratorLoginPassword: &adminpassword, - Version: serverversion, - SslEnforcement: sslenforcement, - CreateMode: psql.CreateModeServerPropertiesForCreate, - }, - Sku: &skuInfo, - }, - ) - - } + serverProperties = &psql.ServerPropertiesForReplica{ + SourceServerID: to.StringPtr(instance.Spec.ReplicaProperties.SourceServerId), + CreateMode: psql.CreateModeReplica, + StorageProfile: storageProfile, + } + } else { + serverProperties = &psql.ServerPropertiesForDefaultCreate{ + AdministratorLogin: &adminlogin, + AdministratorLoginPassword: &adminpassword, + Version: psql.ServerVersion(instance.Spec.ServerVersion), + SslEnforcement: psql.SslEnforcementEnum(instance.Spec.SSLEnforcement), + CreateMode: psql.CreateModeServerPropertiesForCreate, + StorageProfile: storageProfile, + } + skuData = &skuInfo + } + + result, err = client.Create( + ctx, + instance.Spec.ResourceGroup, + instance.Name, + psql.ServerForCreate{ + Location: &instance.Spec.Location, + Tags: tags, + Properties: serverProperties, + Sku: skuData, + }, + ) if err != nil { return "", psql.Server{}, err } + res, err := result.Result(client) return result.PollingURL(), res, err } @@ -168,7 +166,7 @@ func (p *PSQLServerClient) GetServer(ctx context.Context, resourcegroup string, return client.Get(ctx, resourcegroup, servername) } -func (p *PSQLServerClient) AddServerCredsToSecrets(ctx context.Context, secretName string, data map[string][]byte, instance *azurev1alpha1.PostgreSQLServer) error { +func (p *PSQLServerClient) AddServerCredsToSecrets(ctx context.Context, secretName string, data map[string][]byte, instance *v1alpha2.PostgreSQLServer) error { key := types.NamespacedName{ Name: secretName, Namespace: instance.Namespace, @@ -187,7 +185,7 @@ func (p *PSQLServerClient) AddServerCredsToSecrets(ctx context.Context, secretNa return nil } -func (p *PSQLServerClient) UpdateSecretWithFullServerName(ctx context.Context, secretName string, data map[string][]byte, instance *azurev1alpha1.PostgreSQLServer, fullservername string) error { +func (p *PSQLServerClient) UpdateSecretWithFullServerName(ctx context.Context, secretName string, data map[string][]byte, instance *v1alpha2.PostgreSQLServer, fullservername string) error { key := types.NamespacedName{ Name: secretName, Namespace: instance.Namespace, @@ -208,7 +206,7 @@ func (p *PSQLServerClient) UpdateSecretWithFullServerName(ctx context.Context, s return nil } -func (p *PSQLServerClient) GetOrPrepareSecret(ctx context.Context, instance *azurev1alpha1.PostgreSQLServer) (map[string][]byte, error) { +func (p *PSQLServerClient) GetOrPrepareSecret(ctx context.Context, instance *v1alpha2.PostgreSQLServer) (map[string][]byte, error) { name := instance.Name usernameLength := 8 diff --git a/pkg/resourcemanager/psql/server/server_manager.go b/pkg/resourcemanager/psql/server/server_manager.go index 9295242289e..32eb81f7f1a 100644 --- a/pkg/resourcemanager/psql/server/server_manager.go +++ b/pkg/resourcemanager/psql/server/server_manager.go @@ -7,7 +7,7 @@ import ( "context" psql "github.com/Azure/azure-sdk-for-go/services/postgresql/mgmt/2017-12-01/postgresql" - azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" + "github.com/Azure/azure-service-operator/api/v1alpha2" "github.com/Azure/azure-service-operator/pkg/resourcemanager" ) @@ -18,16 +18,12 @@ type PostgreSQLServerManager interface { servername string) (bool, error) CreateServerIfValid(ctx context.Context, - servername string, - resourcegroup string, - location string, + instance v1alpha2.PostgreSQLServer, tags map[string]*string, - serverversion psql.ServerVersion, - sslenforcement psql.SslEnforcementEnum, skuInfo psql.Sku, adminlogin string, adminpassword string, - createmode string, sourceserver string) (string, psql.Server, error) + createmode string) (string, psql.Server, error) DeleteServer(ctx context.Context, resourcegroup string, @@ -40,10 +36,10 @@ type PostgreSQLServerManager interface { AddServerCredsToSecrets(ctx context.Context, secretName string, data map[string][]byte, - instance *azurev1alpha1.PostgreSQLServer) error + instance *v1alpha2.PostgreSQLServer) error GetOrPrepareSecret(ctx context.Context, - instance *azurev1alpha1.PostgreSQLServer) (map[string][]byte, error) + instance *v1alpha2.PostgreSQLServer) (map[string][]byte, error) // also embed async client methods resourcemanager.ARMClient diff --git a/pkg/resourcemanager/psql/server/server_reconcile.go b/pkg/resourcemanager/psql/server/server_reconcile.go index a0ed1f93f73..7b8b7130282 100644 --- a/pkg/resourcemanager/psql/server/server_reconcile.go +++ b/pkg/resourcemanager/psql/server/server_reconcile.go @@ -11,6 +11,7 @@ import ( psql "github.com/Azure/azure-sdk-for-go/services/postgresql/mgmt/2017-12-01/postgresql" "github.com/Azure/azure-service-operator/api/v1alpha1" azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" + "github.com/Azure/azure-service-operator/api/v1alpha2" "github.com/Azure/azure-service-operator/pkg/errhelp" "github.com/Azure/azure-service-operator/pkg/helpers" "github.com/Azure/azure-service-operator/pkg/resourcemanager" @@ -133,17 +134,12 @@ func (p *PSQLServerClient) Ensure(ctx context.Context, obj runtime.Object, opts instance.Status.FailedProvisioning = false pollURL, _, err := p.CreateServerIfValid( ctx, - instance.Name, - instance.Spec.ResourceGroup, - instance.Spec.Location, + *instance, labels, - psql.ServerVersion(instance.Spec.ServerVersion), - psql.SslEnforcementEnum(instance.Spec.SSLEnforcement), skuInfo, adminlogin, adminpassword, createmode, - instance.Spec.ReplicaProperties.SourceServerId, ) if err != nil { instance.Status.Message = errhelp.StripErrorIDs(err) @@ -250,11 +246,12 @@ func (p *PSQLServerClient) GetStatus(obj runtime.Object) (*v1alpha1.ASOStatus, e if err != nil { return nil, err } - return &instance.Status, nil + st := v1alpha1.ASOStatus(instance.Status) + return &st, nil } -func (p *PSQLServerClient) convert(obj runtime.Object) (*v1alpha1.PostgreSQLServer, error) { - local, ok := obj.(*v1alpha1.PostgreSQLServer) +func (p *PSQLServerClient) convert(obj runtime.Object) (*v1alpha2.PostgreSQLServer, error) { + local, ok := obj.(*v1alpha2.PostgreSQLServer) if !ok { return nil, fmt.Errorf("failed type assertion on kind: %s", obj.GetObjectKind().GroupVersionKind().String()) } diff --git a/pkg/resourcemanager/psql/server/server_test.go b/pkg/resourcemanager/psql/server/server_test.go deleted file mode 100644 index a99e178e934..00000000000 --- a/pkg/resourcemanager/psql/server/server_test.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -package server - -import ( - "fmt" - "time" - - psql "github.com/Azure/azure-sdk-for-go/services/postgresql/mgmt/2017-12-01/postgresql" - "github.com/Azure/azure-service-operator/pkg/errhelp" - helpers "github.com/Azure/azure-service-operator/pkg/helpers" - "github.com/Azure/go-autorest/autorest/to" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("PSQL server", func() { - - var rgName string - var location string - var psqlServer string - var PSQLManager PostgreSQLServerManager - - BeforeEach(func() { - // Add any setup steps that needs to be executed before each test - rgName = tc.ResourceGroupName - location = tc.ResourceGroupLocation - PSQLManager = tc.postgreSQLServerManager - }) - - AfterEach(func() { - // Add any teardown steps that needs to be executed after each test - }) - - // Add Tests for OpenAPI validation (or additonal CRD features) specified in - // your API definition. - // Avoid adding tests for vanilla CRUD operations because they would - // test Kubernetes API server, which isn't the goal here. - - Context("Create and Delete", func() { - It("should create and delete PSQL server in azure", func() { - - defer GinkgoRecover() - - psqlServer = "t-dev-psql-srv-" + helpers.RandomString(10) - - pSQLSku := psql.Sku{ - Name: to.StringPtr("B_Gen5_2"), - Tier: psql.SkuTier("Basic"), - Capacity: to.Int32Ptr(2), - Size: to.StringPtr("51200"), - Family: to.StringPtr("Gen5"), - } - tags := map[string]*string{ - "tag1": to.StringPtr("value1"), - "tag2": to.StringPtr("value2"), - } - - // Create PSQL server instance - Eventually(func() bool { - time.Sleep(3 * time.Second) - _, err := PSQLManager.GetServer(ctx, rgName, psqlServer) - if err == nil { - return true - } - _, _, err = PSQLManager.CreateServerIfValid( - ctx, - psqlServer, - rgName, - location, - tags, - psql.OneZero, - psql.SslEnforcementEnumEnabled, - pSQLSku, - "adm1nus3r", - "m@#terU$3r", - "", - "", - ) - if err != nil { - fmt.Println(err.Error()) - if !errhelp.IsAsynchronousOperationNotComplete(err) { - fmt.Println("error occured") - return false - } - } - return true - }, tc.timeout, tc.retryInterval, - ).Should(BeTrue()) - - time.Sleep(5 * time.Minute) - - // Delete PSQL server instance - Eventually(func() bool { - time.Sleep(3 * time.Second) - _, err := PSQLManager.GetServer(ctx, rgName, psqlServer) - if err != nil { - return true - } - _, err = PSQLManager.DeleteServer(ctx, psqlServer, rgName) - if err != nil { - fmt.Println(err.Error()) - if !errhelp.IsAsynchronousOperationNotComplete(err) { - fmt.Println("error occured") - return false - } - } - return err == nil - }, tc.timeout, tc.retryInterval, - ).Should(BeTrue()) - }) - - }) -}) diff --git a/pkg/resourcemanager/psql/server/suite_test.go b/pkg/resourcemanager/psql/server/suite_test.go deleted file mode 100644 index f6892942adb..00000000000 --- a/pkg/resourcemanager/psql/server/suite_test.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -package server - -import ( - "testing" - "time" - - "github.com/Azure/azure-service-operator/pkg/errhelp" - resourcemanagerconfig "github.com/Azure/azure-service-operator/pkg/resourcemanager/config" - - "context" - - resourcegroupsresourcemanager "github.com/Azure/azure-service-operator/pkg/resourcemanager/resourcegroups" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/Azure/azure-service-operator/pkg/helpers" - // +kubebuilder:scaffold:imports -) - -// These tests use Ginkgo (BDD-style Go testing framework). Refer to -// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. - -type TestContext struct { - ResourceGroupName string - ResourceGroupLocation string - postgreSQLServerManager PostgreSQLServerManager - ResourceGroupManager resourcegroupsresourcemanager.ResourceGroupManager - timeout time.Duration - retryInterval time.Duration -} - -var tc TestContext -var ctx context.Context - -func TestAPIs(t *testing.T) { - t.Parallel() - RegisterFailHandler(Fail) - RunSpecs(t, "PSQL server Suite") -} - -var _ = BeforeSuite(func() { - By("bootstrapping test environment") - - ctx = context.Background() - err := resourcemanagerconfig.ParseEnvironment() - Expect(err).ToNot(HaveOccurred()) - - resourceGroupName := "t-rg-dev-psql-" + helpers.RandomString(10) - resourceGroupLocation := resourcemanagerconfig.DefaultLocation() - resourceGroupManager := resourcegroupsresourcemanager.NewAzureResourceGroupManager() - - //create resourcegroup for this suite - _, err = resourceGroupManager.CreateGroup(ctx, resourceGroupName, resourceGroupLocation) - Expect(err).ToNot(HaveOccurred()) - - tc = TestContext{ - ResourceGroupName: resourceGroupName, - ResourceGroupLocation: resourceGroupLocation, - postgreSQLServerManager: &PSQLServerClient{}, - ResourceGroupManager: resourceGroupManager, - timeout: 20 * time.Minute, - retryInterval: 3 * time.Second, - } -}) - -var _ = AfterSuite(func() { - By("tearing down the test environment") - // delete the resource group and contained resources - _, err := tc.ResourceGroupManager.DeleteGroup(ctx, tc.ResourceGroupName) - if !errhelp.IsAsynchronousOperationNotComplete(err) { - return - } - - for { - time.Sleep(time.Second * 10) - _, err := resourcegroupsresourcemanager.GetGroup(ctx, tc.ResourceGroupName) - if err == nil { - } else { - if errhelp.IsGroupNotFound(err) { - break - } else { - return - } - } - } -})