diff --git a/scripts/create-infrastructure.ps1 b/scripts/create-infrastructure.ps1 new file mode 100644 index 0000000..da423aa --- /dev/null +++ b/scripts/create-infrastructure.ps1 @@ -0,0 +1,35 @@ +param ( + [Parameter()] + [ValidateSet('none', 'json')] + [string] + $verbosity = 'none' +) + +$user = az account show --query user.name +if($null -eq $user) { + az login --output $verbosity + $user = az account show --query user.name +} + +write-host "logged in as $user" -ForegroundColor Green +write-host "deploying resources..." -ForegroundColor Yellow + +$location='eastus' +$serviceName='evenire' +$env='dev' + +az deployment sub create --location=$location ` + --template-file ./src/infra/main.bicep ` + --parameters service_name=$serviceName location=$location env=$env + +# the http20ProxyFlag is not yet supported in the bicep template, so we need to set it manually +$subscriptionId = $(az account show --query id --output tsv) +$resourceGroupName = "rg-$serviceName" +$webAppName = "web-$serviceName-$env" +$uri = "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.Web/sites/$webAppName/config/web?api-version=2022-03-01" +az rest ` +--method PUT ` +--uri $uri ` +--body '{\"properties\":{\"http20ProxyFlag\":1}}' + +write-host "deployment complete!" -ForegroundColor Green \ No newline at end of file diff --git a/scripts/deploy-azure.ps1 b/scripts/deploy-azure.ps1 deleted file mode 100644 index d8320a3..0000000 --- a/scripts/deploy-azure.ps1 +++ /dev/null @@ -1,36 +0,0 @@ -param ( - [Parameter()] - [string] - $version, - - [Parameter()] - [string] - $registryName = 'crevenire', - - [Parameter()] - [ValidateSet('none', 'json')] - [string] - $verbosity = 'none' -) - -$user = az account show --query user.name -if($user -eq $null) { - az login --output $verbosity - $user = az account show --query user.name -} - -write-host "logged in as $user" -ForegroundColor Green - -write-host "logging on the container registry ..." -ForegroundColor Yellow -$token = $(az acr login --name $registryName --expose-token --only-show-errors --output tsv --query accessToken) -docker login "$registryName.azurecr.io" --username 00000000-0000-0000-0000-000000000000 --password $token - -write-host "deploying EvenireDB docker image ..." -ForegroundColor Yellow - -docker tag "eveniredb:$version" "$registryName.azurecr.io/eveniredb:$version" -docker tag "eveniredb:latest" "$registryName.azurecr.io/eveniredb:latest" - -docker push "$registryName.azurecr.io/eveniredb:$version" -docker push "$registryName.azurecr.io/eveniredb:latest" - -write-host "deployment complete!" -ForegroundColor Green \ No newline at end of file diff --git a/scripts/init-azure-resources.ps1 b/scripts/init-azure-resources.ps1 deleted file mode 100644 index 04b0ff2..0000000 --- a/scripts/init-azure-resources.ps1 +++ /dev/null @@ -1,49 +0,0 @@ -param ( - [Parameter()] - [string] - $resourceGroupName = 'rg-evenire', - - [Parameter()] - [string] - $registryName = 'crevenire', - - [Parameter()] - [string] - $location = 'eastus', - - [Parameter()] - [string] - $planName = 'plan-evenire', - - [Parameter()] - [string] - $webAppName = 'web-evenire', - - [Parameter()] - [ValidateSet('none', 'json')] - [string] - $verbosity = 'none' -) - -$user = az account show --query user.name -if($user -eq $null) { - az login --output $verbosity - $user = az account show --query user.name -} - -write-host "logged in as $user" -ForegroundColor Green - -write-host "ensuring resource group '$resourceGroupName' ..." -ForegroundColor Yellow -az group create --name $resourceGroupName --location $location --output $verbosity - -write-host "ensuring container registry '$registryName' in resource group '$resourceGroupName' ..." -ForegroundColor Yellow -az acr create --name $registryName --resource-group $resourceGroupName --sku standard --admin-enabled true --output $verbosity -# TODO: grant permissions (acrPush acrDelete) - -write-host "ensuring service plan '$planName' in resource group '$resourceGroupName' ..." -ForegroundColor Yellow -az appservice plan create --name $planName --resource-group $resourceGroupName --is-linux --sku F1 - -write-host "ensuring webapp '$webAppName' in resource group '$resourceGroupName' ..." -ForegroundColor Yellow -az webapp create --resource-group $resourceGroupName --plan $planName --name $webAppName --deployment-container-image-name "$registryName.azurecr.io/eveniredb:latest" - -# TODO: appinsights \ No newline at end of file diff --git a/scripts/publish.ps1 b/scripts/publish.ps1 index eaea155..a32f037 100644 --- a/scripts/publish.ps1 +++ b/scripts/publish.ps1 @@ -8,5 +8,45 @@ param ( $timestamp = $(get-date -UFormat %s) $version = "$env-$timestamp" +function PublishToAzure { + param ( + [Parameter()] + [string] + $version, + + [Parameter()] + [string] + $registryName = 'crevenire', + + [Parameter()] + [ValidateSet('none', 'json')] + [string] + $verbosity = 'none' + ) + + $user = az account show --query user.name + if ($user -eq $null) { + az login --output $verbosity + $user = az account show --query user.name + } + + write-host "logged in as $user" -ForegroundColor Green + + write-host "logging on the container registry ..." -ForegroundColor Yellow + $token = $(az acr login --name $registryName --expose-token --only-show-errors --output tsv --query accessToken) + docker login "$registryName.azurecr.io" --username 00000000-0000-0000-0000-000000000000 --password $token + + write-host "deploying EvenireDB docker image ..." -ForegroundColor Yellow + + docker tag "eveniredb:$version" "$registryName.azurecr.io/eveniredb:$version" + docker tag "eveniredb:latest" "$registryName.azurecr.io/eveniredb:latest" + + docker push "$registryName.azurecr.io/eveniredb:$version" + docker push "$registryName.azurecr.io/eveniredb:latest" + + write-host "deployment complete!" -ForegroundColor Green +} + ./scripts/dockerize.ps1 -version $version -env $env -./scripts/deploy-azure.ps1 -version $version \ No newline at end of file + +PublishToAzure -version $version diff --git a/src/infra/container_registry.bicep b/src/infra/container_registry.bicep new file mode 100644 index 0000000..fc81cd2 --- /dev/null +++ b/src/infra/container_registry.bicep @@ -0,0 +1,17 @@ +param location string +param service_name string + +var container_registry_name = 'cr${service_name}' + +resource container_registry_resource 'Microsoft.ContainerRegistry/registries@2023-08-01-preview' = { + name: container_registry_name + location: location + sku: { + name: 'Basic' + } + properties: { + adminUserEnabled: true + } +} + +output container_registry_name string = container_registry_name diff --git a/src/infra/logs.bicep b/src/infra/logs.bicep new file mode 100644 index 0000000..f0c9cf2 --- /dev/null +++ b/src/infra/logs.bicep @@ -0,0 +1,19 @@ +param location string +param service_name string + +var logs_name = 'logs-${service_name}' + +resource logs_resource 'microsoft.insights/components@2020-02-02' = { + name: logs_name + location: location + kind: 'web' + properties: { + Application_Type: 'web' + Flow_Type: 'Redfield' + Request_Source: 'IbizaAIExtension' + RetentionInDays: 30 + IngestionMode: 'ApplicationInsights' + publicNetworkAccessForIngestion: 'Enabled' + publicNetworkAccessForQuery: 'Enabled' + } +} diff --git a/src/infra/main.bicep b/src/infra/main.bicep new file mode 100644 index 0000000..e6f46cc --- /dev/null +++ b/src/infra/main.bicep @@ -0,0 +1,52 @@ +targetScope = 'subscription' + +param service_name string = 'evenire' +param location string = 'eastus' +param plan_sku string = 'F1' + +@allowed([ + 'dev' + 'prod' +]) +param env string = 'dev' + +var resourceGroupName = 'rg-${service_name}' + +resource resource_group_resource 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: resourceGroupName + location: location +} + +module container_registry './container_registry.bicep' = { + name: 'acr' + scope: resource_group_resource + params: { + location: location + service_name: service_name + } +} + +module logs './logs.bicep' = { + name: 'logs' + scope: resource_group_resource + params: { + location: location + service_name: service_name + } +} + +module webapp './webapp.bicep' = { + name: 'app' + dependsOn: [ + container_registry + logs + ] + scope: resource_group_resource + params: { + location: location + service_name: service_name + plan_sku: plan_sku + container_registry_name: container_registry.outputs.container_registry_name + env: env + } +} diff --git a/src/infra/webapp.bicep b/src/infra/webapp.bicep new file mode 100644 index 0000000..87d56a9 --- /dev/null +++ b/src/infra/webapp.bicep @@ -0,0 +1,102 @@ +param location string +param service_name string +param plan_sku string +param container_registry_name string +param env string + +var web_app_name = 'web-${service_name}-${env}' +var web_plan_name = 'plan-${service_name}-${env}' +var always_on = plan_sku != 'F1' +var image = '${container_registry_name}.azurecr.io/eveniredb:latest' + +var appEnv = env == 'dev' ? 'Development' : 'Production' + +resource acr 'Microsoft.ContainerRegistry/registries@2023-08-01-preview' existing = { + name: container_registry_name +} + +resource web_plan_resource 'Microsoft.Web/serverfarms@2022-09-01' = { + name: web_plan_name + location: location + sku: { + name: plan_sku + size: plan_sku + } + kind: 'linux' + properties: { + targetWorkerSizeId: 0 + targetWorkerCount: 1 + reserved: true + zoneRedundant: false + } +} + +resource web_app_resource 'Microsoft.Web/sites@2022-09-01' = { + name: web_app_name + location: location + kind: 'app,linux,container' + dependsOn:[ + acr + ] + properties: { + serverFarmId: web_plan_resource.id + enabled: true + httpsOnly: true + siteConfig: { + numberOfWorkers: 1 + alwaysOn: always_on + http20Enabled: true + http20ProxyFlag: 1 // this is apparently not yet supported, so have to set it manually using CLI after deployment + linuxFxVersion: 'DOCKER|${image}' + appSettings:[ + { + name: 'DOCKER_ENABLE_CI' + value: 'true' + } + { + name: 'DOCKER_CUSTOM_IMAGE_NAME' + value: image + } + { + name: 'DOCKER_REGISTRY_SERVER_URL' + value: acr.properties.loginServer + } + { + name: 'DOCKER_REGISTRY_SERVER_USERNAME' + value: acr.name + } + { + name: 'DOCKER_REGISTRY_SERVER_PASSWORD' + value: acr.listCredentials().passwords[0].value + } + { + name: 'WEBSITES_ENABLE_APP_SERVICE_STORAGE' + value: 'false' + } + { + name: 'ASPNETCORE_ENVIRONMENT' + value: appEnv + } + ] + } + } +} + +var publishingCredentialsId = resourceId('Microsoft.Web/sites/config', web_app_name, 'publishingCredentials') +var publishingcreds = list(publishingCredentialsId, '2022-03-01') +var scmUri = publishingcreds.properties.scmUri +var hook_name = '${service_name}hook' + +resource hook 'Microsoft.ContainerRegistry/registries/webhooks@2023-08-01-preview' = { + parent: acr + dependsOn:[ web_app_resource ] + location: location + name: hook_name + properties: { + serviceUri: '${scmUri}/docker/hook' + status: 'enabled' + actions: [ + 'push' + ] + } +}