Skip to content

Commit

Permalink
Merge branch 'master' into issue#858
Browse files Browse the repository at this point in the history
  • Loading branch information
WilliamMortlMicrosoft authored Apr 13, 2020
2 parents c0fdecb + 8ce7e09 commit b8ffe66
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 77 deletions.
64 changes: 8 additions & 56 deletions docs/postgresql/postgresql.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,65 +8,21 @@ The Postgre SQL operator suite consists of the following operators.
2. Postgre SQL database - Deploys a database under the given `Azure Database for PostgreSQL server`
3. Postgre SQL firewall rule - Deploys a firewall rule to allow access to the `Azure Database for PostgreSQL server` from the specified IP range

## Deploying PostgreSQL Resources

Follow the steps [here](/docs/development.md) or [here](/docs/deploy.md) to either run the operator locally or in a real Kubernetes cluster.

Use the YAML files in the `config/samples` folder as a guide for creating new resources.

### PostgreSQL server

For instance, this is the sample YAML for the PostgreSQL server.

[PostgreSQL server YAML](/config/samples/azure_v1alpha1_postgresqlserver.yaml)
Here is a [sample YAML](/config/samples/azure_v1alpha1_postgresqlserver.yaml) for the PostgreSQL server.

The value for kind, `PostgreSQLServer` is the Custom Resource Definition (CRD) name.
`postgresqlserver-sample` is the name of the PostgreSQL server resource that will be created.

The values under `spec` provide the values for the location where you want to create the PostgreSQL server at and the Resource group in which you want to create it under. It also contains other values that are required to create the server like the `serverVersion`, `sslEnforcement` and the `sku` information.

Once you've updated the YAML with the settings you need, and you have the operator running, you can create a Custom PostgreSQL server resource using the command.
If `sslEnforcement` is enabled, applications can connect to the PostgreSQL server using SSL. If you would like to connect using the full SSL verification enabled (sslmode=verify-full) that validates the server certificate, you would need the root certificate installed on your client. [This link](https://docs.microsoft.com/en-us/azure/postgresql/concepts-ssl-connection-security) documents the root certificate to use.

```shell
kubectl apply -f config/samples/azure_v1alpha1_postgresqlserver.yaml
```
**Note** The root certificate documented in the above link (`https://www.digicert.com/CACerts/BaltimoreCyberTrustRoot.crt.pem`) only applies to instances on Azure Public Cloud. If you are deploying Azure Database for PostgreSQL instances on Azure China Cloud, you should use this one - `https://dl.cacerts.digicert.com/DigiCertGlobalRootCA.crt.pem`

Along with creating the PostgreSQL server, this operator also generates the admin username and password for the PostgreSQL server and stores it in a kube secret or keyvault (based on what is specified) with the same name as the PostgreSQL server.

You can retrieve this secret using the following command for the sample YAML

```shell
kubectl get secret postgresqlserver-sample -o yaml
```

This would show you the details of the secret. `username` and `password` in the `data` section are the base64 encoded admin credentials to the PostgreSQL server.

```shell
apiVersion: v1alpha1
data:
fullyqualifiedservername: c3Fsc2VydmVyLXNhbXBsZS04ODguZGF0YWJhc2Uud2luZG93cy5uZXQ=
fullyqualifiedusername: aGFzMTUzMnVAc3Fsc2VydmVyLXNhbXBsZS04ODg=
password: XTdpMmQqNsd7YlpFdEApMw==
postgresqlservername: c3Fsc2VyfmVyLXNhbXBsZS04ODg=
username: aGFzMTFzMnU=
kind: Secret
metadata:
creationTimestamp: "2019-10-09T21:02:02Z"
name: sqlserver-sample-888
namespace: default
ownerReferences:
- apiVersion: azure.microsoft.com/v1
blockOwnerDeletion: true
controller: true
kind: PostgreSqlServer
name: sqlserver-sample-888
uid: 08fdbf42-ead8-11e9-91e0-025000000001
resourceVersion: "131163"
selfLink: /api/v1/namespaces/default/secrets/postgresqlserver-sample
uid: 0aeb2429-ead8-11e9-91e0-025000000001
type: Opaque
```

This secret contains the following fields.

- `fullyqualifiedservername` : Fully qualified name of the PostgreSQL server such as postgresqlservername.postgres.database.azure.com
Expand All @@ -79,23 +35,19 @@ For more information on where and how secrets are stored, look [here](/docs/secr

### PostgreSQL Database

Here is the sample YAML for PostgreSQL database

[PostgreSQL database YAML](/config/samples/azure_v1alpha1_postgresqldatabase.yaml)
Here is a [sample YAML](/config/samples/azure_v1alpha1_postgresqldatabase.yaml) for PostgreSQL database

Update the `resourcegroup` to where you want to provision the PostgreSQL database. `server` is the name of the PostgreSQL server where you want to create the database in.

### PostgreSQL firewall

The PostgreSQL firewall operator allows you to add a firewall rule to the PostgreSQL server.
### PostgreSQL firewall rule

Here is the sample YAML for PostgreSQL firewall rule
The PostgreSQL firewall rule operator allows you to add a firewall rule to the PostgreSQL server.

[PostgreSQL firewall rule YAML](/config/samples/azure_v1alpha1_postgresqlfirewallrule.yaml)
Here is a [sample YAML](/config/samples/azure_v1alpha1_postgresqlfirewallrule.yaml) for PostgreSQL firewall rule

The `server` indicates the PostgreSQL server on which you want to configure the new PostgreSQL firewall rule on and `resourceGroup` is the resource group of the PostgreSQL server. The `startIpAddress` and `endIpAddress` indicate the IP range of sources to allow access to the SQL server.

*Note*: When the `startIpAddress` and `endIpAddress` are 0.0.0.0, it is a special case that adds a firewall rule to allow all Azure services to access the SQL server.
*Note*: When the `startIpAddress` and `endIpAddress` are 0.0.0.0, it denotes a special case that adds a firewall rule to allow all Azure services to access the SQL server.

## Deploy, view and delete resources

Expand Down
5 changes: 5 additions & 0 deletions pkg/resourcemanager/apim/apimgmt/apimgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ func (m *Manager) Ensure(ctx context.Context, obj runtime.Object, opts ...resour
if err != nil {
instance.Status.Message = err.Error()
// If there is no parent APIM service, we cannot proceed
instance.Status.Provisioning = false
return false, nil
}

Expand Down Expand Up @@ -160,10 +161,14 @@ func (m *Manager) Ensure(ctx context.Context, obj runtime.Object, opts ...resour
}

if contract.StatusCode == 200 {
instance.Status.Provisioning = false
instance.Status.Provisioned = true
instance.Status.FailedProvisioning = false
instance.Status.Message = resourcemanager.SuccessMsg
} else {
instance.Status.Provisioning = false
instance.Status.Provisioned = false
instance.Status.FailedProvisioning = true
}

return true, nil
Expand Down
32 changes: 11 additions & 21 deletions pkg/resourcemanager/apim/apimservice/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ func (g *AzureAPIMgmtServiceManager) Ensure(ctx context.Context, obj runtime.Obj
errhelp.InvalidParameters,
}

instance.Status.Provisioned = false
instance.Status.Provisioning = true

// STEP 1:
// does it already exist? if not, then provision
exists, activated, resourceID, _ := g.APIMgmtSvcStatus(ctx, resourceGroupName, resourceName)
Expand All @@ -70,17 +73,14 @@ func (g *AzureAPIMgmtServiceManager) Ensure(ctx context.Context, obj runtime.Obj

// if available, create the service
if available {
g.Telemetry.LogTrace("APIM reconcile", "Step 1: creating APIM service")
location := instance.Spec.Location
publisherName := instance.Spec.PublisherName
publisherEmail := instance.Spec.PublisherEmail
_, err := g.CreateAPIMgmtSvc(ctx, tier, location, resourceGroupName, resourceName, publisherName, publisherEmail)
instance.Status.Provisioned = false
instance.Status.Provisioning = true
if err != nil {
instance.Status.Provisioning = false
azerr := errhelp.NewAzureErrorAzureError(err)
if helpers.ContainsString(catch, azerr.Type) {
g.Telemetry.LogError("API Mgmt Svc creation error, requeueing", err)
instance.Status.Message = "API Mgmt Svc encountered a caught error, requeueing..."
return false, nil
}
Expand All @@ -92,20 +92,17 @@ func (g *AzureAPIMgmtServiceManager) Ensure(ctx context.Context, obj runtime.Obj
}

// name wasnt available, log error and stop reconciling
g.Telemetry.LogError("could not create API Mgmt Service due to bad resource name", fmt.Errorf("bad API Mgmt Service name"))
instance.Status.Message = "API Mgmt Svc is ending reconciliation due to bad name"
instance.Status.Provisioned = false
instance.Status.Provisioning = false
instance.Status.FailedProvisioning = true
return true, nil
}

// STEP 2:
// still in the proccess of provisioning
if !activated {
g.Telemetry.LogTrace("APIM reconcile", "Step 2: waiting on activation of APIM service")
instance.Status.Message = "API Mgmt Svc is waiting for activation / updating to complete, requeueing..."
instance.Status.Provisioned = false
instance.Status.Provisioning = true
return false, nil
}

Expand All @@ -114,27 +111,23 @@ func (g *AzureAPIMgmtServiceManager) Ensure(ctx context.Context, obj runtime.Obj
appInsightsResourceGroup := instance.Spec.AppInsightsResourceGroup
appInsightsName := instance.Spec.AppInsightsName
if appInsightsResourceGroup != "" && appInsightsName != "" {
g.Telemetry.LogTrace("APIM reconcile", "Step 3: assigning App Insights for APIM service")
err = g.SetAppInsightsForAPIMgmtSvc(
ctx,
resourceGroupName,
resourceName,
appInsightsResourceGroup,
appInsightsName,
)
instance.Status.Provisioned = false
instance.Status.Provisioning = true
if err != nil {
azerr := errhelp.NewAzureErrorAzureError(err)
if helpers.ContainsString(catch, azerr.Type) {
g.Telemetry.LogError("App Insights error, requeueing", err)
instance.Status.Message = "API Mgmt Svc encountered a caught error, requeueing..."
return false, nil
} else if helpers.ContainsString(fatalErr, azerr.Type) {
g.Telemetry.LogError("Fatal error assigning App Insights", err)
instance.Status.Message = "API Mgmt Svc encountered a trapped error, ending reconciliation"
instance.Status.Message = fmt.Sprintf("API Mgmt Svc encountered a trapped error, ending reconciliation: %s", err.Error())
instance.Status.Provisioned = false
instance.Status.Provisioning = false
instance.Status.FailedProvisioning = true
return true, nil
}
instance.Status.Message = "API Mgmt Svc encountered an unknown error, requeueing..."
Expand All @@ -145,7 +138,6 @@ func (g *AzureAPIMgmtServiceManager) Ensure(ctx context.Context, obj runtime.Obj
// STEP 4:
// need to update with a vnet?
if vnetType != "" && !strings.EqualFold(vnetType, "none") {
g.Telemetry.LogTrace("APIM reconcile", "Step 4: assignning VNet for APIM service")
vnetResourceGroup := instance.Spec.VnetResourceGroup
vnetName := instance.Spec.VnetName
subnetName := instance.Spec.VnetSubnetName
Expand All @@ -158,19 +150,16 @@ func (g *AzureAPIMgmtServiceManager) Ensure(ctx context.Context, obj runtime.Obj
vnetName,
subnetName,
)
instance.Status.Provisioned = false
instance.Status.Provisioning = true
if err != nil {
azerr := errhelp.NewAzureErrorAzureError(err)
if !helpers.ContainsString(catch, azerr.Type) {
g.Telemetry.LogError("VNet update error, requeueing", err)
instance.Status.Message = "API Mgmt Svc encountered a caught error, requeueing..."
return false, nil
} else if helpers.ContainsString(fatalErr, azerr.Type) {
g.Telemetry.LogError("Fatal error occured with assigning a VNet", err)
instance.Status.Message = "API Mgmt Svc encountered a trapped error, ending reconciliation"
instance.Status.Message = fmt.Sprintf("API Mgmt Svc encountered a trapped error, ending reconciliation: %s", err.Error())
instance.Status.Provisioned = false
instance.Status.Provisioning = false
instance.Status.FailedProvisioning = true
return true, nil
}
instance.Status.Message = "API Mgmt Svc encountered an unknown error, requeueing..."
Expand All @@ -184,10 +173,10 @@ func (g *AzureAPIMgmtServiceManager) Ensure(ctx context.Context, obj runtime.Obj

// STEP 5:
// everything is now completed!
g.Telemetry.LogTrace("APIM reconcile", "Step 5: completed reconcilliation successfully")
instance.Status.Message = resourcemanager.SuccessMsg
instance.Status.Provisioned = true
instance.Status.Provisioning = false
instance.Status.FailedProvisioning = false
instance.Status.ResourceId = *resourceID
return true, nil
}
Expand Down Expand Up @@ -253,6 +242,7 @@ func (g *AzureAPIMgmtServiceManager) convert(obj runtime.Object) (*azurev1alpha1
return local, nil
}

// GetStatus retrieves the status object
func (g *AzureAPIMgmtServiceManager) GetStatus(obj runtime.Object) (*v1alpha1.ASOStatus, error) {
instance, err := g.convert(obj)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/resourcemanager/keyvaults/keyvault.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ func (k *azureKeyVaultManager) Ensure(ctx context.Context, obj runtime.Object, o
labels := helpers.LabelsToTags(instance.GetLabels())

instance.Status.Provisioning = true
instance.Status.FailedProvisioning = false

// Check if this KeyVault already exists and its state if it does.

Expand Down

0 comments on commit b8ffe66

Please sign in to comment.