Add state.sqlserver conformance test against Azure SQL (#1182)

* Add Azure SQL to setup-azure-conf-test.sh

* Add state.sqlserver conformance test on Azure SQL

Co-authored-by: Dapr Bot <56698301+dapr-bot@users.noreply.github.com>
This commit is contained in:
Simon Leet 2021-10-06 12:33:50 -07:00 committed by GitHub
parent e457b307b6
commit 9f77037de2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 119 additions and 1 deletions

View File

@ -0,0 +1,25 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation and Dapr Contributors.
// Licensed under the MIT License.
// ------------------------------------------------------------
param sqlServerName string
param rgLocation string = resourceGroup().location
param confTestTags object = {}
param sqlServerAdminPassword string
var sqlServerAdminName = '${sqlServerName}-admin'
resource sqlServer 'Microsoft.Sql/servers@2021-02-01-preview' = {
name: sqlServerName
location: rgLocation
tags: confTestTags
properties: {
administratorLogin: sqlServerAdminName
administratorLoginPassword: sqlServerAdminPassword
minimalTlsVersion: '1.2'
publicNetworkAccess: 'Enabled'
}
}
output sqlServerAdminName string = sqlServer.properties.administratorLogin

View File

@ -33,6 +33,10 @@ param sdkAuthSpId string
@description('Provide the objectId of the Service Principal using cert auth with get and list access to all assets in Azure Key Vault.') @description('Provide the objectId of the Service Principal using cert auth with get and list access to all assets in Azure Key Vault.')
param certAuthSpId string param certAuthSpId string
@minLength(16)
@description('Provide the SQL server admin password of at least 16 characters.')
param sqlServerAdminPassword string
var confTestRgName = '${toLower(namePrefix)}-conf-test-rg' var confTestRgName = '${toLower(namePrefix)}-conf-test-rg'
var cosmosDbName = '${toLower(namePrefix)}-conf-test-db' var cosmosDbName = '${toLower(namePrefix)}-conf-test-db'
var eventGridTopicName = '${toLower(namePrefix)}-conf-test-eventgrid-topic' var eventGridTopicName = '${toLower(namePrefix)}-conf-test-eventgrid-topic'
@ -40,6 +44,7 @@ var eventHubsNamespaceName = '${toLower(namePrefix)}-conf-test-eventhubs'
var iotHubName = '${toLower(namePrefix)}-conf-test-iothub' var iotHubName = '${toLower(namePrefix)}-conf-test-iothub'
var keyVaultName = '${toLower(namePrefix)}-conf-test-kv' var keyVaultName = '${toLower(namePrefix)}-conf-test-kv'
var serviceBusName = '${toLower(namePrefix)}-conf-test-servicebus' var serviceBusName = '${toLower(namePrefix)}-conf-test-servicebus'
var sqlServerName = '${toLower(namePrefix)}-conf-test-sql'
var storageName = '${toLower(namePrefix)}ctstorage' var storageName = '${toLower(namePrefix)}ctstorage'
resource confTestRg 'Microsoft.Resources/resourceGroups@2021-04-01' = { resource confTestRg 'Microsoft.Resources/resourceGroups@2021-04-01' = {
@ -105,6 +110,16 @@ module serviceBus 'conf-test-azure-servicebus.bicep' = {
} }
} }
module sqlServer 'conf-test-azure-sqlserver.bicep' = {
name: sqlServerName
scope: resourceGroup(confTestRg.name)
params: {
confTestTags: confTestTags
sqlServerName: sqlServerName
sqlServerAdminPassword: sqlServerAdminPassword
}
}
module storage 'conf-test-azure-storage.bicep' = { module storage 'conf-test-azure-storage.bicep' = {
name: storageName name: storageName
scope: resourceGroup(confTestRg.name) scope: resourceGroup(confTestRg.name)
@ -131,4 +146,6 @@ output iotHubBindingsConsumerGroupName string = iotHub.outputs.iotHubBindingsCon
output iotHubPubsubConsumerGroupName string = iotHub.outputs.iotHubPubsubConsumerGroupName output iotHubPubsubConsumerGroupName string = iotHub.outputs.iotHubPubsubConsumerGroupName
output keyVaultName string = keyVault.name output keyVaultName string = keyVault.name
output serviceBusName string = serviceBus.name output serviceBusName string = serviceBus.name
output sqlServerName string = sqlServer.name
output sqlServerAdminName string = sqlServer.outputs.sqlServerAdminName
output storageName string = storage.name output storageName string = storage.name

View File

@ -184,8 +184,13 @@ KEYVAULT_CLIENT_ID_VAR_NAME="AzureKeyVaultSecretStoreClientId"
KEYVAULT_TENANT_ID_VAR_NAME="AzureKeyVaultSecretStoreTenantId" KEYVAULT_TENANT_ID_VAR_NAME="AzureKeyVaultSecretStoreTenantId"
KEYVAULT_NAME_VAR_NAME="AzureKeyVaultName" KEYVAULT_NAME_VAR_NAME="AzureKeyVaultName"
RESOURCE_GROUP_NAME_VAR_NAME="AzureResourceGroupName"
SERVICE_BUS_CONNECTION_STRING_VAR_NAME="AzureServiceBusConnectionString" SERVICE_BUS_CONNECTION_STRING_VAR_NAME="AzureServiceBusConnectionString"
SQL_SERVER_NAME_VAR_NAME="AzureSqlServerName"
SQL_SERVER_CONNECTION_STRING_VAR_NAME="AzureSqlServerConnectionString"
STORAGE_ACCESS_KEY_VAR_NAME="AzureBlobStorageAccessKey" STORAGE_ACCESS_KEY_VAR_NAME="AzureBlobStorageAccessKey"
STORAGE_ACCOUNT_VAR_NAME="AzureBlobStorageAccount" STORAGE_ACCOUNT_VAR_NAME="AzureBlobStorageAccount"
STORAGE_CONTAINER_VAR_NAME="AzureBlobStorageContainer" STORAGE_CONTAINER_VAR_NAME="AzureBlobStorageContainer"
@ -231,6 +236,9 @@ else
echo "${SDK_AUTH_SP_INFO}" > "${AZURE_CREDENTIALS_FILENAME}" echo "${SDK_AUTH_SP_INFO}" > "${AZURE_CREDENTIALS_FILENAME}"
fi fi
# Generate new password for SQL Server admin
SQL_SERVER_ADMIN_PASSWORD=$(openssl rand -base64 32)
# Build the bicep template and deploy to Azure # Build the bicep template and deploy to Azure
az bicep install az bicep install
ARM_TEMPLATE_FILE="${OUTPUT_PATH}/${PREFIX}-azure-conf-test.json" ARM_TEMPLATE_FILE="${OUTPUT_PATH}/${PREFIX}-azure-conf-test.json"
@ -238,7 +246,7 @@ echo "Building conf-test-azure.bicep to ${ARM_TEMPLATE_FILE} ..."
az bicep build --file conf-test-azure.bicep --outfile "${ARM_TEMPLATE_FILE}" az bicep build --file conf-test-azure.bicep --outfile "${ARM_TEMPLATE_FILE}"
echo "Creating azure deployment ${DEPLOY_NAME} in ${DEPLOY_LOCATION} and resource prefix ${PREFIX}-* ..." echo "Creating azure deployment ${DEPLOY_NAME} in ${DEPLOY_LOCATION} and resource prefix ${PREFIX}-* ..."
az deployment sub create --name "${DEPLOY_NAME}" --location "${DEPLOY_LOCATION}" --template-file "${ARM_TEMPLATE_FILE}" -p namePrefix="${PREFIX}" -p adminId="${ADMIN_ID}" -p certAuthSpId="${CERT_AUTH_SP_ID}" -p sdkAuthSpId="${SDK_AUTH_SP_ID}" -p rgLocation="${DEPLOY_LOCATION}" az deployment sub create --name "${DEPLOY_NAME}" --location "${DEPLOY_LOCATION}" --template-file "${ARM_TEMPLATE_FILE}" -p namePrefix="${PREFIX}" -p adminId="${ADMIN_ID}" -p certAuthSpId="${CERT_AUTH_SP_ID}" -p sdkAuthSpId="${SDK_AUTH_SP_ID}" -p rgLocation="${DEPLOY_LOCATION}" -p sqlServerAdminPassword="${SQL_SERVER_ADMIN_PASSWORD}"
echo "Sleeping for 5s to allow created ARM deployment info to propagate to query endpoints ..." echo "Sleeping for 5s to allow created ARM deployment info to propagate to query endpoints ..."
sleep 5s sleep 5s
@ -281,6 +289,10 @@ IOT_HUB_BINDINGS_CONSUMER_GROUP_FULLNAME="$(az deployment sub show --name "${DEP
echo "INFO: IOT_HUB_BINDINGS_CONSUMER_GROUP_FULLNAME=${IOT_HUB_BINDINGS_CONSUMER_GROUP_FULLNAME}" echo "INFO: IOT_HUB_BINDINGS_CONSUMER_GROUP_FULLNAME=${IOT_HUB_BINDINGS_CONSUMER_GROUP_FULLNAME}"
IOT_HUB_PUBSUB_CONSUMER_GROUP_FULLNAME="$(az deployment sub show --name "${DEPLOY_NAME}" --query "properties.outputs.iotHubPubsubConsumerGroupName.value" | sed -E 's/[[:space:]]|\"//g')" IOT_HUB_PUBSUB_CONSUMER_GROUP_FULLNAME="$(az deployment sub show --name "${DEPLOY_NAME}" --query "properties.outputs.iotHubPubsubConsumerGroupName.value" | sed -E 's/[[:space:]]|\"//g')"
echo "INFO: IOT_HUB_PUBSUB_CONSUMER_GROUP_FULLNAME=${IOT_HUB_PUBSUB_CONSUMER_GROUP_FULLNAME}" echo "INFO: IOT_HUB_PUBSUB_CONSUMER_GROUP_FULLNAME=${IOT_HUB_PUBSUB_CONSUMER_GROUP_FULLNAME}"
SQL_SERVER_NAME="$(az deployment sub show --name "${DEPLOY_NAME}" --query "properties.outputs.sqlServerName.value" | sed -E 's/[[:space:]]|\"//g')"
echo "INFO: SQL_SERVER_NAME=${SQL_SERVER_NAME}"
SQL_SERVER_ADMIN_NAME="$(az deployment sub show --name "${DEPLOY_NAME}" --query "properties.outputs.sqlServerAdminName.value" | sed -E 's/[[:space:]]|\"//g')"
echo "INFO: SQL_SERVER_ADMIN_NAME=${SQL_SERVER_ADMIN_NAME}"
# Update service principal credentials and roles for created resources # Update service principal credentials and roles for created resources
echo "Creating ${CERT_AUTH_SP_NAME} certificate ..." echo "Creating ${CERT_AUTH_SP_NAME} certificate ..."
@ -297,6 +309,11 @@ IOT_HUB_SCOPE="/subscriptions/${SUB_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/pr
echo "Assigning \"Contributor\" role to ${SDK_AUTH_SP_NAME} in scope \"${IOT_HUB_SCOPE}\"..." echo "Assigning \"Contributor\" role to ${SDK_AUTH_SP_NAME} in scope \"${IOT_HUB_SCOPE}\"..."
MSYS_NO_PATHCONV=1 az role assignment create --assignee "${SDK_AUTH_SP_ID}" --role "Contributor" --scope "${IOT_HUB_SCOPE}" MSYS_NO_PATHCONV=1 az role assignment create --assignee "${SDK_AUTH_SP_ID}" --role "Contributor" --scope "${IOT_HUB_SCOPE}"
# Add SQL Server Contributor role to the SDK auth Service Principal so it can update firewall rules to run sqlserver state conformance tests.
SQL_SERVER_SCOPE="/subscriptions/${SUB_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/providers/Microsoft.Sql/servers/${SQL_SERVER_NAME}"
echo "Assigning \"Contributor\" role to ${SDK_AUTH_SP_NAME} in scope \"${SQL_SERVER_SCOPE}\"..."
MSYS_NO_PATHCONV=1 az role assignment create --assignee "${SDK_AUTH_SP_ID}" --role "Contributor" --scope "${SQL_SERVER_SCOPE}"
##============================================================================== ##==============================================================================
## ##
## Create output files for environment config and teardown of conformance tests ## Create output files for environment config and teardown of conformance tests
@ -466,6 +483,23 @@ SERVICE_BUS_CONNECTION_STRING="$(az servicebus namespace authorization-rule keys
echo export ${SERVICE_BUS_CONNECTION_STRING_VAR_NAME}=\"${SERVICE_BUS_CONNECTION_STRING}\" >> "${ENV_CONFIG_FILENAME}" echo export ${SERVICE_BUS_CONNECTION_STRING_VAR_NAME}=\"${SERVICE_BUS_CONNECTION_STRING}\" >> "${ENV_CONFIG_FILENAME}"
az keyvault secret set --name "${SERVICE_BUS_CONNECTION_STRING_VAR_NAME}" --vault-name "${KEYVAULT_NAME}" --value "${SERVICE_BUS_CONNECTION_STRING}" az keyvault secret set --name "${SERVICE_BUS_CONNECTION_STRING_VAR_NAME}" --vault-name "${KEYVAULT_NAME}" --value "${SERVICE_BUS_CONNECTION_STRING}"
# ----------------------------------
# Populate SQL Server test settings
# ----------------------------------
echo "Configuring SQL Server test settings ..."
# Not specific to SQL server, but this is currently only consumed by setting SQL server firewall rules
echo export ${RESOURCE_GROUP_NAME_VAR_NAME}=\"${RESOURCE_GROUP_NAME}\" >> "${ENV_CONFIG_FILENAME}"
az keyvault secret set --name "${RESOURCE_GROUP_NAME_VAR_NAME}" --vault-name "${KEYVAULT_NAME}" --value "${RESOURCE_GROUP_NAME}"
echo export ${SQL_SERVER_NAME_VAR_NAME}=\"${SQL_SERVER_NAME}\" >> "${ENV_CONFIG_FILENAME}"
az keyvault secret set --name "${SQL_SERVER_NAME_VAR_NAME}" --vault-name "${KEYVAULT_NAME}" --value "${SQL_SERVER_NAME}"
# Note that `az sql db show-connection-string` does not currently support a `go` --client type, so we construct our own here.
SQL_SERVER_CONNECTION_STRING="Server=${SQL_SERVER_NAME}.database.windows.net;port=1433;User ID=${SQL_SERVER_ADMIN_NAME};Password=${SQL_SERVER_ADMIN_PASSWORD};Encrypt=true;"
echo export ${SQL_SERVER_CONNECTION_STRING_VAR_NAME}=\"${SQL_SERVER_CONNECTION_STRING}\" >> "${ENV_CONFIG_FILENAME}"
az keyvault secret set --name "${SQL_SERVER_CONNECTION_STRING_VAR_NAME}" --vault-name "${KEYVAULT_NAME}" --value "${SQL_SERVER_CONNECTION_STRING}"
# ---------------------------------- # ----------------------------------
# Populate Event Hubs test settings # Populate Event Hubs test settings
# ---------------------------------- # ----------------------------------

View File

@ -93,6 +93,8 @@ jobs:
CRON_COMPONENTS=$(yq -I0 --tojson eval - << EOF CRON_COMPONENTS=$(yq -I0 --tojson eval - << EOF
- component: state.azure.cosmosdb - component: state.azure.cosmosdb
required-secrets: AzureCosmosDBMasterKey,AzureCosmosDBUrl,AzureCosmosDB,AzureCosmosDBCollection required-secrets: AzureCosmosDBMasterKey,AzureCosmosDBUrl,AzureCosmosDB,AzureCosmosDBCollection
- component: state.azure.sql
required-secrets: AzureResourceGroupName, AzureSqlServerName, AzureSqlServerConnectionString
- component: state.azure.tablestorage - component: state.azure.tablestorage
required-secrets: AzureBlobStorageAccessKey,AzureBlobStorageAccount required-secrets: AzureBlobStorageAccessKey,AzureBlobStorageAccount
- component: pubsub.azure.eventhubs - component: pubsub.azure.eventhubs
@ -269,6 +271,18 @@ jobs:
go mod download go mod download
go install gotest.tools/gotestsum@latest go install gotest.tools/gotestsum@latest
- name: Configure Azure SQL Firewall
run: |
set +e
TEST_OUTPUT="$(go test -v -tags=conftests -count=1 -timeout=1m ./tests/conformance -run=TestStateConformance/azure.sql)"
echo "Trial run result:\n\"$TEST_OUTPUT\""
PUBLIC_IP=$(echo "$TEST_OUTPUT" | grep -Po "Client with IP address '\K[^']*")
if [[ -n ${PUBLIC_IP} ]]; then
echo "Setting Azure SQL firewall-rule AllowTestRunnerIP to allow $PUBLIC_IP..."
az sql server firewall-rule create --resource-group ${{ env.AzureResourceGroupName }} --server ${{ env.AzureSqlServerName }} -n "AllowTestRunnerIP" --start-ip-address "$PUBLIC_IP" --end-ip-address "$PUBLIC_IP"
fi
if: contains(matrix.component, 'azure.sql')
- name: Run tests - name: Run tests
continue-on-error: true continue-on-error: true
run: | run: |
@ -307,6 +321,13 @@ jobs:
continue-on-error: true continue-on-error: true
run: pkill ngrok; cat /tmp/ngrok.log run: pkill ngrok; cat /tmp/ngrok.log
- name: Cleanup Azure SQL Firewall and test DB instance
if: contains(matrix.component, 'azure.sql')
continue-on-error: true
run: |
az sql server firewall-rule delete --resource-group ${{ env.AzureResourceGroupName }} --server ${{ env.AzureSqlServerName }} -n "AllowTestRunnerIP"
az sql db delete --resource-group ${{ env.AzureResourceGroupName }} --server ${{ env.AzureSqlServerName }} -n dapr --yes
# Download the required certificates into files, and set env var pointing to their names # Download the required certificates into files, and set env var pointing to their names
- name: Clean up certs - name: Clean up certs
if: matrix.required-certs != '' if: matrix.required-certs != ''

View File

@ -0,0 +1,17 @@
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
spec:
type: state.sqlserver
metadata:
- name: connectionString
value: ${{AzureSqlServerConnectionString}}
- name: tableName
value: dapr_conf_test
- name: keyType
value: string
- name: keyLength
value: 120
- name: schema
value: proto

View File

@ -7,6 +7,8 @@ components:
allOperations: true allOperations: true
- component: azure.cosmosdb - component: azure.cosmosdb
allOperations: true allOperations: true
- component: azure.sql
allOperations: true
- component: sqlserver - component: sqlserver
allOperations: true allOperations: true
- component: mysql - component: mysql

View File

@ -374,6 +374,8 @@ func loadStateStore(tc TestComponent) state.Store {
store = s_cosmosdb.NewCosmosDBStateStore(testLogger) store = s_cosmosdb.NewCosmosDBStateStore(testLogger)
case "mongodb": case "mongodb":
store = s_mongodb.NewMongoDB(testLogger) store = s_mongodb.NewMongoDB(testLogger)
case "azure.sql":
fallthrough
case "sqlserver": case "sqlserver":
store = s_sqlserver.NewSQLServerStateStore(testLogger) store = s_sqlserver.NewSQLServerStateStore(testLogger)
case "mysql": case "mysql":