diff --git a/docs/postgresql/postgresql.md b/docs/postgresql/postgresql.md index 661f923cd07..5990445c729 100644 --- a/docs/postgresql/postgresql.md +++ b/docs/postgresql/postgresql.md @@ -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 @@ -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 diff --git a/pkg/resourcemanager/apim/apimgmt/apimgmt.go b/pkg/resourcemanager/apim/apimgmt/apimgmt.go index 20d617307d7..24743af44e5 100644 --- a/pkg/resourcemanager/apim/apimgmt/apimgmt.go +++ b/pkg/resourcemanager/apim/apimgmt/apimgmt.go @@ -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 } @@ -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 diff --git a/pkg/resourcemanager/apim/apimservice/reconcile.go b/pkg/resourcemanager/apim/apimservice/reconcile.go index d6820242826..8f226c7bd70 100644 --- a/pkg/resourcemanager/apim/apimservice/reconcile.go +++ b/pkg/resourcemanager/apim/apimservice/reconcile.go @@ -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) @@ -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 } @@ -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 } @@ -114,7 +111,6 @@ 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, @@ -122,19 +118,16 @@ func (g *AzureAPIMgmtServiceManager) Ensure(ctx context.Context, obj runtime.Obj 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..." @@ -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 @@ -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..." @@ -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 } @@ -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 { diff --git a/pkg/resourcemanager/keyvaults/keyvault.go b/pkg/resourcemanager/keyvaults/keyvault.go index 25cdbcdfeca..2522fe0f3af 100644 --- a/pkg/resourcemanager/keyvaults/keyvault.go +++ b/pkg/resourcemanager/keyvaults/keyvault.go @@ -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.