Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Azure Databases for MySQL Server #855

Merged
merged 17 commits into from
Apr 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,12 @@ resources:
- group: azure
version: v1alpha1
kind: AzureSQLVNetRule
- group: azure
version: v1alpha1
kind: MySQLServer
- group: azure
version: v1alpha1
kind: MySQLDatabase
- group: azure
version: v1alpha1
kind: MySQLFirewallRule
42 changes: 42 additions & 0 deletions api/v1alpha1/mysqldatabase_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

package v1alpha1

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.

// MySQLDatabaseSpec defines the desired state of MySQLDatabase
type MySQLDatabaseSpec struct {
ResourceGroup string `json:"resourceGroup,omitempty"`
Server string `json:"server,omitempty"`
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// MySQLDatabase is the Schema for the mysqldatabases API
type MySQLDatabase struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec MySQLDatabaseSpec `json:"spec,omitempty"`
Status ASOStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// MySQLDatabaseList contains a list of MySQLDatabase
type MySQLDatabaseList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []MySQLDatabase `json:"items"`
}

func init() {
SchemeBuilder.Register(&MySQLDatabase{}, &MySQLDatabaseList{})
}
44 changes: 44 additions & 0 deletions api/v1alpha1/mysqlfirewallrule_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

package v1alpha1

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.

// MySQLFirewallRuleSpec defines the desired state of MySQLFirewallRule
type MySQLFirewallRuleSpec struct {
ResourceGroup string `json:"resourceGroup"`
Server string `json:"server"`
StartIPAddress string `json:"startIpAddress"`
EndIPAddress string `json:"endIpAddress"`
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// MySQLFirewallRule is the Schema for the mysqlfirewallrules API
type MySQLFirewallRule struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec MySQLFirewallRuleSpec `json:"spec,omitempty"`
Status ASOStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// MySQLFirewallRuleList contains a list of MySQLFirewallRule
type MySQLFirewallRuleList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []MySQLFirewallRule `json:"items"`
}

func init() {
SchemeBuilder.Register(&MySQLFirewallRule{}, &MySQLFirewallRuleList{})
}
68 changes: 68 additions & 0 deletions api/v1alpha1/mysqlserver_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

package v1alpha1

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.

// 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"`
KeyVaultToStoreSecrets string `json:"keyVaultToStoreSecrets,omitempty"`
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// MySQLServer is the Schema for the mysqlservers API
type MySQLServer struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec MySQLServerSpec `json:"spec,omitempty"`
Status ASOStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// MySQLServerList contains a list of MySQLServer
type MySQLServerList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []MySQLServer `json:"items"`
}

func init() {
SchemeBuilder.Register(&MySQLServer{}, &MySQLServerList{})
}

func NewDefaultMySQLServer(name, resourceGroup, location string) *MySQLServer {
return &MySQLServer{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: "default",
},
Spec: MySQLServerSpec{
Location: location,
ResourceGroup: resourceGroup,
Sku: AzureDBsSQLSku{
Name: "B_Gen5_2",
Tier: SkuTier("Basic"),
Family: "Gen5",
Size: "51200",
Capacity: 2,
},
ServerVersion: ServerVersion("8.0"),
SSLEnforcement: SslEnforcementEnumEnabled,
},
}
}
4 changes: 2 additions & 2 deletions api/v1alpha1/postgresqlserver_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import (
type PostgreSQLServerSpec struct {
Location string `json:"location"`
ResourceGroup string `json:"resourceGroup,omitempty"`
Sku PSQLSku `json:"sku,omitempty"`
Sku AzureDBsSQLSku `json:"sku,omitempty"`
ServerVersion ServerVersion `json:"serverVersion,omitempty"`
SSLEnforcement SslEnforcementEnum `json:"sslEnforcement,omitempty"`
KeyVaultToStoreSecrets string `json:"keyVaultToStoreSecrets,omitempty"`
}

type PSQLSku struct {
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'
Expand Down
9 changes: 9 additions & 0 deletions config/crd/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ resources:

- bases/azure.microsoft.com_keyvaultkeys.yaml
- bases/azure.microsoft.com_azuresqlvnetrules.yaml
- bases/azure.microsoft.com_mysqlservers.yaml
- bases/azure.microsoft.com_mysqldatabases.yaml
- bases/azure.microsoft.com_mysqlfirewallrules.yaml
# +kubebuilder:scaffold:crdkustomizeresource

#patches:
Expand All @@ -54,6 +57,9 @@ resources:
#- patches/webhook_in_virtualnetworks.yaml
#- patches/webhook_in_keyvaultkeys.yaml
#- patches/webhook_in_azuresqlvnetrules.yaml
#- patches/webhook_in_mysqlservers.yaml
#- patches/webhook_in_mysqldatabases.yaml
#- patches/webhook_in_mysqlfirewallrules.yaml
# +kubebuilder:scaffold:crdkustomizewebhookpatch

# [CAINJECTION] patches here are for enabling the CA injection for each CRD
Expand All @@ -79,6 +85,9 @@ resources:
#- patches/cainjection_in_virtualnetworks.yaml
#- patches/cainjection_in_keyvaultkeys.yaml
#- patches/cainjection_in_azuresqlvnetrules.yaml
#- patches/cainjection_in_mysqlservers.yaml
#- patches/cainjection_in_mysqldatabases.yaml
#- patches/cainjection_in_mysqlfirewallrules.yaml
# +kubebuilder:scaffold:crdkustomizecainjectionpatch

# the following config is for teaching kustomize how to do kustomization for CRDs.
Expand Down
8 changes: 8 additions & 0 deletions config/crd/patches/cainjection_in_mysqldatabases.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# The following patch adds a directive for certmanager to inject CA into the CRD
# CRD conversion requires k8s 1.13 or later.
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
certmanager.k8s.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
name: mysqldatabases.azure.microsoft.com
8 changes: 8 additions & 0 deletions config/crd/patches/cainjection_in_mysqlfirewallrules.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# The following patch adds a directive for certmanager to inject CA into the CRD
# CRD conversion requires k8s 1.13 or later.
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
certmanager.k8s.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
name: mysqlfirewallrules.azure.microsoft.com
8 changes: 8 additions & 0 deletions config/crd/patches/cainjection_in_mysqlservers.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# The following patch adds a directive for certmanager to inject CA into the CRD
# CRD conversion requires k8s 1.13 or later.
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
certmanager.k8s.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
name: mysqlservers.azure.microsoft.com
17 changes: 17 additions & 0 deletions config/crd/patches/webhook_in_mysqldatabases.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# The following patch enables conversion webhook for CRD
# CRD conversion requires k8s 1.13 or later.
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: mysqldatabases.azure.microsoft.com
spec:
conversion:
strategy: Webhook
webhookClientConfig:
# this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank,
# but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager)
caBundle: Cg==
service:
namespace: system
name: webhook-service
path: /convert
17 changes: 17 additions & 0 deletions config/crd/patches/webhook_in_mysqlfirewallrules.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# The following patch enables conversion webhook for CRD
# CRD conversion requires k8s 1.13 or later.
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: mysqlfirewallrules.azure.microsoft.com
spec:
conversion:
strategy: Webhook
webhookClientConfig:
# this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank,
# but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager)
caBundle: Cg==
service:
namespace: system
name: webhook-service
path: /convert
17 changes: 17 additions & 0 deletions config/crd/patches/webhook_in_mysqlservers.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# The following patch enables conversion webhook for CRD
# CRD conversion requires k8s 1.13 or later.
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: mysqlservers.azure.microsoft.com
spec:
conversion:
strategy: Webhook
webhookClientConfig:
# this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank,
# but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager)
caBundle: Cg==
service:
namespace: system
name: webhook-service
path: /convert
7 changes: 7 additions & 0 deletions config/samples/azure_v1alpha1_mysqldatabase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: azure.microsoft.com/v1alpha1
kind: MySQLDatabase
metadata:
name: mysqldatabase-sample
spec:
resourceGroup: resourcegroup-azure-operators
server: mysqlserver-sample
9 changes: 9 additions & 0 deletions config/samples/azure_v1alpha1_mysqlfirewallrule.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: azure.microsoft.com/v1alpha1
kind: MySQLFirewallRule
metadata:
name: mysqlfirewallrule-sample
spec:
resourceGroup: resourcegroup-azure-operators
server: mysqlserver-sample
startIpAddress: 0.0.0.0
endIpAddress: 0.0.0.0
15 changes: 15 additions & 0 deletions config/samples/azure_v1alpha1_mysqlserver.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: azure.microsoft.com/v1alpha1
kind: MySQLServer
metadata:
name: mysqlserver-sample
spec:
location: eastus2
resourceGroup: resourcegroup-azure-operators
serverVersion: "8.0"
sslEnforcement: Enabled
sku:
name: B_Gen5_2
tier: Basic
family: Gen5
size: "51200"
capacity: 2
31 changes: 31 additions & 0 deletions controllers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/Azure/azure-service-operator/pkg/secrets"
"github.com/go-logr/logr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
apierrors "k8s.io/apimachinery/pkg/api/errors"
apierrs "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
Expand Down Expand Up @@ -256,6 +257,36 @@ func EnsureDelete(ctx context.Context, t *testing.T, tc TestContext, instance ru

}

func RequireInstance(ctx context.Context, t *testing.T, tc TestContext, instance runtime.Object) {
RequireInstanceWithResult(ctx, t, tc, instance, successMsg, true)
}

func RequireInstanceWithResult(ctx context.Context, t *testing.T, tc TestContext, instance runtime.Object, message string, provisioned bool) {
require := require.New(t)
typeOf := fmt.Sprintf("%T", instance)

err := tc.k8sClient.Create(ctx, instance)
require.Equal(nil, err, fmt.Sprintf("create %s in k8s", typeOf))

res, err := meta.Accessor(instance)
require.Equal(nil, err, "not a metav1 object")

names := types.NamespacedName{Name: res.GetName(), Namespace: res.GetNamespace()}

// Wait for first sql server to resolve
require.Eventually(func() bool {
_ = tc.k8sClient.Get(ctx, names, instance)
return HasFinalizer(res, finalizerName)
}, tc.timeoutFast, tc.retry, "error waiting for %s to have finalizer", typeOf)

require.Eventually(func() bool {
_ = tc.k8sClient.Get(ctx, names, instance)
statused := ConvertToStatus(instance)
return strings.Contains(statused.Status.Message, message) && statused.Status.Provisioned == provisioned
}, tc.timeout, tc.retry, "wait for %s to provision", typeOf)

}

// ConvertToStatus takes a runtime.Object and attempts to convert it to an object with an ASOStatus field
func ConvertToStatus(instance runtime.Object) *v1alpha1.StatusedObject {
target := &v1alpha1.StatusedObject{}
Expand Down
Loading