diff --git a/examples/azure/README.md b/examples/azure/README.md index 8dbca3ec8..5ad3f4e26 100644 --- a/examples/azure/README.md +++ b/examples/azure/README.md @@ -22,7 +22,7 @@ Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/master/g ```go require ( ... - github.com/Azure/azure-sdk-for-go v46.1.0+incompatible + github.com/Azure/azure-sdk-for-go v57.1.0+incompatible ... ) ``` diff --git a/examples/azure/terraform-azure-mysqldb-flexible-example/README.md b/examples/azure/terraform-azure-mysqldb-flexible-example/README.md new file mode 100644 index 000000000..c7b1576ed --- /dev/null +++ b/examples/azure/terraform-azure-mysqldb-flexible-example/README.md @@ -0,0 +1,31 @@ +# Terraform Azure Database for MySQL - Flexible Server Example + +This folder contains a Terraform module that deploys resources in [Azure](https://azure.microsoft.com/) to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code. +This module deploy a [Azure Database for MySQL - Flexible Server](https://learn.microsoft.com/en-gb/azure/mysql/flexible-server/overview) with default values defined in [variables.tf](variables.tf). + +Check out [test/azure/terraform_azure_mysqldb_flexible_example_test.go](./../../../test/azure/terraform_azure_mysqldb_flexible_example_test.go) to see how you can write automated tests for this module and validate the configuration of the parameters and options. + +**WARNING**: This module and the automated tests for it deploy real resources into your Azure account which can cost you money. The resources are all part of the [Azure Free Tier](https://azure.microsoft.com/en-us/pricing/free-services/), so if you haven't used that up, +it should be free, but you are completely responsible for all Azure charges. + +## Running this module manually +1. Sign up for [Azure](https://azure.microsoft.com/). +1. Configure your Azure credentials using one of the [supported methods for Azure CLI + tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest) +1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`. +1. Ensure [environment variables](../README.md#review-environment-variables) are available +1. Run `terraform init` +1. Run `terraform apply` +1. When you're done, run `terraform destroy`. + + +## Running automated tests against this module +1. Sign up for [Azure](https://azure.microsoft.com/) +1. Configure your Azure credentials using one of the [supported methods for Azure CLI + tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest) +1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH` +1. Configure your Terratest [Go test environment](../README.md) +1. `cd test/azure` +1. `go build terraform_azure_mysqldb_flexible_example_test.go` +1. `go test -v -timeout 60m -tags azure -run TestTerraformAzureMySqlFlexibleServerDBExample` + diff --git a/examples/azure/terraform-azure-mysqldb-flexible-example/main.tf b/examples/azure/terraform-azure-mysqldb-flexible-example/main.tf new file mode 100644 index 000000000..3bd4f99d7 --- /dev/null +++ b/examples/azure/terraform-azure-mysqldb-flexible-example/main.tf @@ -0,0 +1,96 @@ +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY AN AZURE Database For MySQL - Flexible Server +# This is an example of how to deploy an Azure Database Mysql - Flexible Server . +# See test/terraform_azure_mysqldb_flexible_example_test.go for how to write automated tests for this code. +# --------------------------------------------------------------------------------------------------------------------- + +# --------------------------------------------------------------------------------------------------------------------- +# PIN TERRAFORM VERSION TO >= 0.12 +# The examples have been upgraded to 0.12 syntax +# --------------------------------------------------------------------------------------------------------------------- + +terraform { + # This module is now only being tested with Terraform 0.13.x. However, to make upgrading easier, we are setting + # 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it + # forwards compatible with 0.13.x code. + required_version = ">= 0.12.26" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.41.0" + } + + random = { + source = "hashicorp/random" + version = "~> 3.4.3" + } + } +} + +# --------------------------------------------------------------------------------------------------------------------- +# CONFIGURE OUR AZURE CONNECTION +# --------------------------------------------------------------------------------------------------------------------- + +provider "azurerm" { + features {} +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY A RESOURCE GROUP +# --------------------------------------------------------------------------------------------------------------------- + +resource "azurerm_resource_group" "example" { + location = var.location + name = "rg-flexible-${var.postfix}" +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY AZURE MySQL FLEXIBLE SERVER +# --------------------------------------------------------------------------------------------------------------------- + +# Random password is used as an example to simplify the deployment and improve the security of the database. +# This is not as a production recommendation as the password is stored in the Terraform state file. +resource "random_password" "password" { + length = 16 + override_special = "_%@" + min_upper = "1" + min_lower = "1" + min_numeric = "1" + min_special = "1" +} + +resource "azurerm_mysql_flexible_server" "example" { + name = "mysql-flexible-${var.postfix}" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + administrator_login = var.mysql_flexible_server_administrator_login + administrator_password = random_password.password.result + + backup_retention_days = var.mysql_flexible_server_backup_retention_days + sku_name = var.mysql_flexible_server_sku_name + version = var.mysql_version + # Azure automatically deploy the instance in an Availability Zone. + # By providing this, when updating your configuration, you avoid error: + # Error: `zone` cannot be changed independently. + zone = var.mysql_flexible_server_zone + + storage { + auto_grow_enabled = false + size_gb = var.mysql_flexible_server_storage_size_gb + } +} + +# --------------------------------------------------------------------------------------------------------------------- +# DEPLOY AZURE MySQL DATABASE +# --------------------------------------------------------------------------------------------------------------------- + +resource "azurerm_mysql_flexible_database" "example" { + name = "mysqldb-flexible-${var.postfix}" + resource_group_name = azurerm_resource_group.example.name + server_name = azurerm_mysql_flexible_server.example.name + + charset = var.mysql_flexible_server_db_charset + collation = var.mysql_flexible_server_db_collation +} \ No newline at end of file diff --git a/examples/azure/terraform-azure-mysqldb-flexible-example/outputs.tf b/examples/azure/terraform-azure-mysqldb-flexible-example/outputs.tf new file mode 100644 index 000000000..cc722066d --- /dev/null +++ b/examples/azure/terraform-azure-mysqldb-flexible-example/outputs.tf @@ -0,0 +1,24 @@ +output "resource_group_name" { + value = azurerm_resource_group.example.name +} + +output "mysql_flexible_server_name" { + value = azurerm_mysql_flexible_server.example.name +} + +output "mysql_flexible_server_full_domain_name" { + value = azurerm_mysql_flexible_server.example.fqdn +} + +output "mysql_flexible_server_admin_login" { + value = azurerm_mysql_flexible_server.example.administrator_login +} + +output "mysql_flexible_server_admin_login_pass" { + value = azurerm_mysql_flexible_server.example.administrator_password + sensitive = true +} + +output "mysql_flexible_server_db_name" { + value = azurerm_mysql_flexible_database.example.name +} \ No newline at end of file diff --git a/examples/azure/terraform-azure-mysqldb-flexible-example/variables.tf b/examples/azure/terraform-azure-mysqldb-flexible-example/variables.tf new file mode 100644 index 000000000..6f61cc50d --- /dev/null +++ b/examples/azure/terraform-azure-mysqldb-flexible-example/variables.tf @@ -0,0 +1,99 @@ +# --------------------------------------------------------------------------------------------------------------------- +# ENVIRONMENT VARIABLES +# Define these secrets as environment variables +# --------------------------------------------------------------------------------------------------------------------- + +# ARM_CLIENT_ID +# ARM_CLIENT_SECRET +# ARM_SUBSCRIPTION_ID +# ARM_TENANT_ID + +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED PARAMETERS +# You must provide a value for each of these parameters. +# --------------------------------------------------------------------------------------------------------------------- + +# --------------------------------------------------------------------------------------------------------------------- +# OPTIONAL PARAMETERS +# These parameters have reasonable defaults. +# --------------------------------------------------------------------------------------------------------------------- + +variable "postfix" { + description = "A postfix string to centrally mitigate resource name collisions." + type = string + default = "example" +} + +variable "location" { + description = "The Azure Region where the MySQL Flexible Server should exist." + type = string + default = "West Europe" +} + +variable "mysql_flexible_server_administrator_login" { + description = "The Administrator login for the MySQL Flexible Server." + type = string + default = "mysqladmin" +} + +variable "mysql_flexible_server_backup_retention_days" { + description = "The backup retention days for the MySQL Flexible Server." + type = number + default = 7 + + validation { + condition = var.mysql_flexible_server_backup_retention_days >= 1 && var.mysql_flexible_server_backup_retention_days <= 35 + error_message = "MySQL Flexible Server retention days should be between 1 and 35." + } +} + +variable "mysql_flexible_server_sku_name" { + description = "The SKU Name for the MySQL Flexible Server." + type = string + default = "B_Standard_B1ms" +} + +variable "mysql_flexible_server_storage_size_gb" { + description = "The max storage allowed for the MySQL Flexible Server." + type = number + default = 32 + + validation { + condition = var.mysql_flexible_server_storage_size_gb >= 20 && var.mysql_flexible_server_storage_size_gb <= 16384 + error_message = "MySQL Flexible Server storage size (GB) should be a value between 20 and 16384." + } +} + +variable "mysql_flexible_server_zone" { + description = "Specifies the Availability Zone in which this MySQL Flexible Server should be located." + type = number + default = 1 + + validation { + condition = var.mysql_flexible_server_zone == 1 || var.mysql_flexible_server_zone == 2 || var.mysql_flexible_server_zone == 3 + error_message = "MySQL Flexible Server possible Availability Zone are 1, 2 or 3." + } +} + +variable "mysql_version" { + description = "The version of the MySQL Flexible Server to use." + type = string + default = "5.7" + + validation { + condition = var.mysql_version == "5.7" || var.mysql_version == "8.0.21" + error_message = "MySQL version for Flexbile Server instance should be 5.7 or 8.0.21." + } +} + +variable "mysql_flexible_server_db_charset" { + description = "Specifies the Charset for the MySQL Database, which needs to be a valid MySQL Charset." + type = string + default = "utf8" +} + +variable "mysql_flexible_server_db_collation" { + description = "Specifies the Collation for the MySQL Database, which needs to be a valid MySQL Collation." + type = string + default = "utf8_unicode_ci" +} \ No newline at end of file diff --git a/go.mod b/go.mod index ccbfbc7a5..c84e0191c 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( cloud.google.com/go v0.105.0 // indirect cloud.google.com/go/storage v1.27.0 - github.com/Azure/azure-sdk-for-go v51.0.0+incompatible + github.com/Azure/azure-sdk-for-go v57.1.0+incompatible github.com/Azure/go-autorest/autorest v0.11.20 github.com/Azure/go-autorest/autorest/azure/auth v0.5.8 github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect @@ -109,7 +109,6 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/satori/go.uuid v1.2.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/ulikunitz/xz v0.5.10 // indirect go.opencensus.io v0.24.0 // indirect diff --git a/go.sum b/go.sum index c819d1ca5..339118704 100644 --- a/go.sum +++ b/go.sum @@ -191,8 +191,8 @@ cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1V cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v51.0.0+incompatible h1:p7blnyJSjJqf5jflHbSGhIhEpXIgIFmYZNg5uwqweso= -github.com/Azure/azure-sdk-for-go v51.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v57.1.0+incompatible h1:TKQ3ieyB0vVKkF6t9dsWbMjq56O1xU3eh3Ec09v6ajM= +github.com/Azure/azure-sdk-for-go v57.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -525,6 +525,8 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -923,7 +925,6 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= diff --git a/modules/azure/client_factory.go b/modules/azure/client_factory.go index dbfc3201c..30516f8d9 100644 --- a/modules/azure/client_factory.go +++ b/modules/azure/client_factory.go @@ -16,6 +16,7 @@ import ( "github.com/Azure/azure-sdk-for-go/profiles/latest/frontdoor/mgmt/frontdoor" "github.com/Azure/azure-sdk-for-go/profiles/latest/mysql/mgmt/mysql" + "github.com/Azure/azure-sdk-for-go/profiles/latest/mysql/mgmt/mysqlflexibleservers" "github.com/Azure/azure-sdk-for-go/profiles/latest/resources/mgmt/resources" "github.com/Azure/azure-sdk-for-go/profiles/latest/sql/mgmt/sql" "github.com/Azure/azure-sdk-for-go/profiles/preview/cosmos-db/mgmt/documentdb" @@ -438,6 +439,64 @@ func CreateMySQLServerClientE(subscriptionID string) (*mysql.ServersClient, erro return &mysqlClient, nil } +// CreateMySqlFlexibleServerClientE is a helper function that will setup a mysql flexible server client. +func CreateMySqlFlexibleServerClientE(subscriptionID string) (*mysqlflexibleservers.ServersClient, error) { + // Validate Azure subscription ID + subscriptionID, err := getTargetAzureSubscription(subscriptionID) + if err != nil { + return nil, err + } + + // Lookup environment URI + baseURI, err := getBaseURI() + if err != nil { + return nil, err + } + + // Create a mysql server client + flexibleMySqlClient := mysqlflexibleservers.NewServersClientWithBaseURI(baseURI, subscriptionID) + + // Create an authorizer + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err + } + + // Attach authorizer to the client + flexibleMySqlClient.Authorizer = *authorizer + + return &flexibleMySqlClient, nil +} + +// CreateMySqlFlexibleServerDBClientE is a helper function that will setup a mysql db flexible server client. +func CreateMySqlFlexibleServerDBClientE(subscriptionID string) (*mysqlflexibleservers.DatabasesClient, error) { + // Validate Azure subscription ID + subscriptionID, err := getTargetAzureSubscription(subscriptionID) + if err != nil { + return nil, err + } + + // Lookup environment URI + baseURI, err := getBaseURI() + if err != nil { + return nil, err + } + + // Create a mysql server client + flexibleMySqlDBClient := mysqlflexibleservers.NewDatabasesClientWithBaseURI(baseURI, subscriptionID) + + // Create an authorizer + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err + } + + // Attach authorizer to the client + flexibleMySqlDBClient.Authorizer = *authorizer + + return &flexibleMySqlDBClient, nil +} + // CreateDisksClientE returns a new Disks client in the specified Azure Subscription func CreateDisksClientE(subscriptionID string) (*compute.DisksClient, error) { // Validate Azure subscription ID diff --git a/modules/azure/client_factory_test.go b/modules/azure/client_factory_test.go index b58e127fb..da8cf19ad 100644 --- a/modules/azure/client_factory_test.go +++ b/modules/azure/client_factory_test.go @@ -357,3 +357,71 @@ func TestFrontDoorFrontendEndpointClientBaseURISetCorrectly(t *testing.T) { }) } } + +func TestMySQLFlexibleServerEndpointClientBaseURISetCorrectly(t *testing.T) { + var cases = []struct { + CaseName string + EnvironmentName string + ExpectedBaseURI string + }{ + {"GovCloud/MySQLFlexibleServer", govCloudEnvName, autorest.USGovernmentCloud.ResourceManagerEndpoint}, + {"PublicCloud/MySQLFlexibleServer", publicCloudEnvName, autorest.PublicCloud.ResourceManagerEndpoint}, + {"ChinaCloud/MySQLFlexibleServer", chinaCloudEnvName, autorest.ChinaCloud.ResourceManagerEndpoint}, + {"GermanCloud/MySQLFlexibleServer", germanyCloudEnvName, autorest.GermanCloud.ResourceManagerEndpoint}, + } + + // save any current env value and restore on exit + currentEnv := os.Getenv(AzureEnvironmentEnvName) + defer os.Setenv(AzureEnvironmentEnvName, currentEnv) + + for _, tt := range cases { + // The following is necessary to make sure testCase's values don't + // get updated due to concurrency within the scope of t.Run(..) below + tt := tt + t.Run(tt.CaseName, func(t *testing.T) { + // Override env setting + os.Setenv(AzureEnvironmentEnvName, tt.EnvironmentName) + + // Get a Database for MySQL Flexible Server endpoint client + client, err := CreateMySqlFlexibleServerClientE("") + require.NoError(t, err) + + // Check for correct ARM URI + assert.Equal(t, tt.ExpectedBaseURI, client.BaseURI) + }) + } +} + +func TestMySQLFlexibleServerDBEndpointClientBaseURISetCorrectly(t *testing.T) { + var cases = []struct { + CaseName string + EnvironmentName string + ExpectedBaseURI string + }{ + {"GovCloud/MySQLFlexibleServerDB", govCloudEnvName, autorest.USGovernmentCloud.ResourceManagerEndpoint}, + {"PublicCloud/MySQLFlexibleServerDB", publicCloudEnvName, autorest.PublicCloud.ResourceManagerEndpoint}, + {"ChinaCloud/MySQLFlexibleServerDB", chinaCloudEnvName, autorest.ChinaCloud.ResourceManagerEndpoint}, + {"GermanCloud/MySQLFlexibleServerDB", germanyCloudEnvName, autorest.GermanCloud.ResourceManagerEndpoint}, + } + + // save any current env value and restore on exit + currentEnv := os.Getenv(AzureEnvironmentEnvName) + defer os.Setenv(AzureEnvironmentEnvName, currentEnv) + + for _, tt := range cases { + // The following is necessary to make sure testCase's values don't + // get updated due to concurrency within the scope of t.Run(..) below + tt := tt + t.Run(tt.CaseName, func(t *testing.T) { + // Override env setting + os.Setenv(AzureEnvironmentEnvName, tt.EnvironmentName) + + // Get a Database for MySQL Flexible Server endpoint client + client, err := CreateMySqlFlexibleServerDBClientE("") + require.NoError(t, err) + + // Check for correct ARM URI + assert.Equal(t, tt.ExpectedBaseURI, client.BaseURI) + }) + } +} diff --git a/modules/azure/mysqlflexible.go b/modules/azure/mysqlflexible.go new file mode 100644 index 000000000..6a3d8294a --- /dev/null +++ b/modules/azure/mysqlflexible.go @@ -0,0 +1,112 @@ +package azure + +import ( + "context" + + "github.com/Azure/azure-sdk-for-go/profiles/latest/mysql/mgmt/mysqlflexibleservers" + "github.com/gruntwork-io/terratest/modules/testing" + "github.com/stretchr/testify/require" +) + +// GetMySqlFlexibleServer is a helper function that gets the server. +// This function would fail the test if there is an error. +func GetMySqlFlexibleServer(t testing.TestingT, resGroupName string, serverName string, subscriptionID string) *mysqlflexibleservers.Server { + mysqlServer, err := GetMySqlFlexibleServerE(t, subscriptionID, resGroupName, serverName) + require.NoError(t, err) + + return mysqlServer +} + +// GetMySqlFlexibleServerE is a helper function that gets the server. +func GetMySqlFlexibleServerE(t testing.TestingT, subscriptionID string, resGroupName string, serverName string) (*mysqlflexibleservers.Server, error) { + // Create a MySql Server client + flexibleMySqlClient, err := CreateMySqlFlexibleServerClientE(subscriptionID) + if err != nil { + return nil, err + } + + // Get the corresponding flexible server client + flexibleMySqlServer, err := flexibleMySqlClient.Get(context.Background(), resGroupName, serverName) + if err != nil { + return nil, err + } + + //Return flexible server + return &flexibleMySqlServer, nil +} + +// GetMySqlFlexibleDBClientE is a helper function that will setup a MySql flexible DB client. +func GetMySqlFlexibleServerDBClientE(subscriptionID string) (*mysqlflexibleservers.DatabasesClient, error) { + // Validate Azure subscription ID + subscriptionID, err := getTargetAzureSubscription(subscriptionID) + if err != nil { + return nil, err + } + + // Create a mysql db client + mysqlFlexibleDBClient := mysqlflexibleservers.NewDatabasesClient(subscriptionID) + + // Create an authorizer + authorizer, err := NewAuthorizer() + if err != nil { + return nil, err + } + + // Attach authorizer to the client + mysqlFlexibleDBClient.Authorizer = *authorizer + + return &mysqlFlexibleDBClient, nil +} + +// GetMySqlFlexibleServerDB is a helper function that gets the database. +// This function would fail the test if there is an error. +func GetMySqlFlexibleServerDB(t testing.TestingT, resGroupName string, serverName string, dbName string, subscriptionID string) *mysqlflexibleservers.Database { + database, err := GetMySqlFlexibleServerDBE(t, subscriptionID, resGroupName, serverName, dbName) + require.NoError(t, err) + + return database +} + +// GetMySqlFlexibleServerDBE is a helper function that gets the database. +func GetMySqlFlexibleServerDBE(t testing.TestingT, subscriptionID string, resGroupName string, serverName string, dbName string) (*mysqlflexibleservers.Database, error) { + // Create a MySql Flexible Server DB client + mysqlFlexibleServerDBClient, err := CreateMySqlFlexibleServerDBClientE(subscriptionID) + if err != nil { + return nil, err + } + + // Get the corresponding MySql Flexible Server DB client + mysqlFlexibleServerDB, err := mysqlFlexibleServerDBClient.Get(context.Background(), resGroupName, serverName, dbName) + if err != nil { + return nil, err + } + + //Return MySql Flexible Server DB + return &mysqlFlexibleServerDB, nil +} + +// ListMySqlFlexibleServerDB is a helper function that gets all databases per server. +func ListMySqlFlexibleServerDB(t testing.TestingT, resGroupName string, serverName string, subscriptionID string) []mysqlflexibleservers.Database { + mysqlFlexibleServerDBList, err := ListMySqlFlexibleServerDBE(t, subscriptionID, resGroupName, serverName) + require.NoError(t, err) + + return mysqlFlexibleServerDBList +} + +// ListMySqlFlexibleServerDBE is a helper function that gets all databases per server. +func ListMySqlFlexibleServerDBE(t testing.TestingT, subscriptionID string, resGroupName string, serverName string) ([]mysqlflexibleservers.Database, error) { + // Create a MySql Flexible Server DB client + mysqlFlexibleServerDBClient, err := CreateMySqlFlexibleServerDBClientE(subscriptionID) + if err != nil { + return nil, err + } + + // Get the corresponding MySql Flexible Server DB client + mysqlFlexibleServerDBs, err := mysqlFlexibleServerDBClient.ListByServer(context.Background(), resGroupName, serverName) + if err != nil { + return nil, err + } + + //Return MySql Flexible Server DB list + return mysqlFlexibleServerDBs.Values(), nil +} diff --git a/modules/azure/mysqlflexible_test.go b/modules/azure/mysqlflexible_test.go new file mode 100644 index 000000000..b3e3ddad6 --- /dev/null +++ b/modules/azure/mysqlflexible_test.go @@ -0,0 +1,40 @@ +//go:build azure +// +build azure + +// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for +// CircleCI. + +package azure + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +/* +The below tests are currently stubbed out, with the expectation that they will throw errors. +If/when CRUD methods are introduced for Azure MySQL server and database, these tests can be extended +*/ +func TestGetMySqlFlexibleServerE(t *testing.T) { + t.Parallel() + + resGroupName := "" + serverName := "" + subscriptionID := "" + + _, err := GetMySqlFlexibleServerE(t, subscriptionID, resGroupName, serverName) + require.Error(t, err) +} + +func TestGetMySqlFlexibleServerDBE(t *testing.T) { + t.Parallel() + + resGroupName := "" + serverName := "" + subscriptionID := "" + dbName := "" + + _, err := GetMySqlFlexibleServerDBE(t, subscriptionID, resGroupName, serverName, dbName) + require.Error(t, err) +} diff --git a/test/azure/terraform_azure_mysqldb_flexible_example_test.go b/test/azure/terraform_azure_mysqldb_flexible_example_test.go new file mode 100644 index 000000000..65b8ebf46 --- /dev/null +++ b/test/azure/terraform_azure_mysqldb_flexible_example_test.go @@ -0,0 +1,70 @@ +//go:build azure +// +build azure + +// NOTE: We use build tags to differentiate azure testing because we currently do not have azure access setup for +// CircleCI. + +package test + +import ( + "fmt" + "strings" + "testing" + + "github.com/Azure/azure-sdk-for-go/profiles/latest/mysql/mgmt/mysqlflexibleservers" + "github.com/gruntwork-io/terratest/modules/azure" + "github.com/gruntwork-io/terratest/modules/random" + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/assert" +) + +func TestTerraformAzureMySqlFlexibleServerDBExample(t *testing.T) { + t.Parallel() + + uniquePostfix := strings.ToLower(random.UniqueId()) + expectedFlexibleServerSkuName := "Standard_B1ms" + expectedFlexibleServerStorageGb := "32" + expectedFlexibleServerDatabaseCharSet := "utf8" + expectedFlexibleServerDatabaseCollation := "utf8_unicode_ci" + + // website::tag::1:: Configure Terraform setting up a path to Terraform code. + terraformOptions := &terraform.Options{ + // The path to where our Terraform code is located + TerraformDir: "../../examples/azure/terraform-azure-mysqldb-flexible-example", + Vars: map[string]interface{}{ + "postfix": uniquePostfix, + // SKU name returned by Azure is different from + // the SKU name that terraform use to create the resource. + // Appending the SKU Family as workaround. + "mysql_flexible_server_sku_name": "B_" + expectedFlexibleServerSkuName, + "mysql_flexible_server_storage_size_gb": expectedFlexibleServerStorageGb, + "mysql_flexible_server_db_charset": expectedFlexibleServerDatabaseCharSet, + }, + } + + // website::tag::4:: At the end of the test, run `terraform destroy` to clean up any resources that were created + defer terraform.Destroy(t, terraformOptions) + + // website::tag::2:: Run `terraform init` and `terraform apply`. Fail the test if there are any errors. + terraform.InitAndApply(t, terraformOptions) + + // website::tag::3:: Run `terraform output` to get the values of output variables + expectedResourceGroupName := terraform.Output(t, terraformOptions, "resource_group_name") + expectedMySqlFlexibleServerName := terraform.Output(t, terraformOptions, "mysql_flexible_server_name") + + expectedMySqlFlexibleServerDBName := terraform.Output(t, terraformOptions, "mysql_flexible_server_db_name") + + // website::tag::4:: Get mySql server details and assert them against the terraform output + actualMySqlFlexibleServer := azure.GetMySqlFlexibleServer(t, expectedResourceGroupName, expectedMySqlFlexibleServerName, "") + + assert.Equal(t, expectedFlexibleServerSkuName, *actualMySqlFlexibleServer.Sku.Name) + assert.Equal(t, expectedFlexibleServerStorageGb, fmt.Sprint(*actualMySqlFlexibleServer.ServerProperties.Storage.StorageSizeGB)) + + assert.Equal(t, mysqlflexibleservers.ServerStateReady, actualMySqlFlexibleServer.ServerProperties.State) + + // website::tag::5:: Get mySql server DB details and assert them against the terraform output + actualMySqlServerFlexibleServerDatabase := azure.GetMySqlFlexibleServerDB(t, expectedResourceGroupName, expectedMySqlFlexibleServerName, expectedMySqlFlexibleServerDBName, "") + + assert.Equal(t, expectedFlexibleServerDatabaseCharSet, *actualMySqlServerFlexibleServerDatabase.DatabaseProperties.Charset) + assert.Equal(t, expectedFlexibleServerDatabaseCollation, *actualMySqlServerFlexibleServerDatabase.DatabaseProperties.Collation) +}