Skip to content

Commit 1743058

Browse files
authored
Merge pull request #10 from manekinekko/azd-support
feat: add support for azd 🎉
2 parents cac8d14 + af2f6bf commit 1743058

11 files changed

+550
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
.azure

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ A real study case application how to apply Node.Js with:
99
* **Vue.Js**
1010
* **Azure Functions**
1111
* **Azure Static Web Apps**
12+
* **Azure Dev CLI**
1213

1314
## 🚀 Resources Used
1415

@@ -123,6 +124,43 @@ Unless you have changed the database name, login and password in the Dockerfile
123124

124125
If you want to test Azure SQL database, to make sure everything will work perfectly even when deployed on Azure, you need to create an Azure SQL database before.
125126

127+
***Using the Azure Dev CLI***
128+
129+
The following prerequisites are required to use this application. Please ensure that you have them all installed locally.
130+
131+
- [Azure Developer CLI](https://aka.ms/azure-dev/install)
132+
- Windows:
133+
```powershell
134+
powershell -ex AllSigned -c "Invoke-RestMethod 'https://aka.ms/install-azd.ps1' | Invoke-Expression"
135+
```
136+
- Linux/MacOS:
137+
```
138+
curl -fsSL https://aka.ms/install-azd.sh | bash
139+
```
140+
- [Azure CLI (2.38.0+)](https://docs.microsoft.com/cli/azure/install-azure-cli)
141+
142+
To create the necessary infrastructure on Azure:
143+
144+
1. Open a terminal, change directory to the root of this project.
145+
1. Run the following command to initialize the project, provision Azure resources.
146+
147+
```bash
148+
azd provision
149+
```
150+
For more details, [read the Azure Dev CLI documentation](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/).
151+
152+
Once the infrastructure has been created, create a `.env` file in the `api` folder and copy/paste content from `.azure/azure-sql-prisma-vue/.env`. We only care about the `DATABASE_URL` and `SHADOW_DATABASE_URL` variables:
153+
154+
```bash
155+
# Database connection string
156+
DATABASE_URL="sqlserver://DB_SERVER_NAME.database.windows.net:1433;database=DB_NAME;user=DB_USER@DB_SERVER_NAME;password={PASSWORD};encrypt=true"
157+
158+
# Shadow database connection string for development
159+
SHADOW_DATABASE_URL="sqlserver://DB_SERVER_NAME.database.windows.net:1433;database=DB_NAME;user=DB_USER@DB_SERVER_NAME;password={PASSWORD};encrypt=true"
160+
```
161+
162+
***Using the Azure Portal***
163+
126164
The are different ways you can create an Azure SQL Database. Using the Portal, using AZ CLI or Powershell. The easiest is using the Portal, and you can have see complete walk-through in this recording: **[Demo: Deploy Azure SQL Database | Azure SQL for beginners (Ep. 14)](https://www.youtube.com/watch?v=wiBC4OxFX60&list=PLlrxD0HtieHi5c9-i_Dnxw9vxBY-TqaeN&index=21)**. If you prefer reading instead of watching, here a complete quickstart guide available, with detailed steps for each option: **[Quickstart: Create an Azure SQL Database single database](https://docs.microsoft.com/en-us/azure/azure-sql/database/single-database-create-quickstart?view=azuresql&tabs=azure-portal)**. If you want something more concise and direct, you can to follow the simple 6-steps guide available here: **[Create and connect to an Azure SQL DB](https://dev.to/azure/create-and-connect-to-an-azure-sql-db-9k0)**.
127165

128166
Make sure you create *two* Azure SQL databases:

azure.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json
2+
3+
name: azure-sql-prisma-vue
4+
5+
infra:
6+
provider: bicep
7+
path: main
8+
9+
services:
10+
web:
11+
project: ./client
12+
dist: dist
13+
language: js
14+
host: staticwebapp

infra/main.bicep

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
targetScope = 'subscription'
2+
3+
@minLength(1)
4+
@maxLength(64)
5+
@description('Name of the the environment which is used to generate a short unique hash used in all resources.')
6+
param name string
7+
8+
@minLength(1)
9+
@description('Primary location for all resources')
10+
param location string
11+
12+
@description('Id of the user or app to assign app roles')
13+
param principalId string = ''
14+
15+
var resourceToken = toLower(uniqueString(subscription().id, name, location))
16+
var tags = { 'azd-env-name': name }
17+
18+
resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
19+
name: 'rg-${name}'
20+
location: location
21+
tags: tags
22+
}
23+
24+
// TODO: make KeyVault optional
25+
var deployKeyVault = false
26+
27+
// Note: Application Insights is required for "azd monitor"
28+
var deployAppInsights = true
29+
30+
module keyVaultResources 'resources/key-vault.bicep' = if (deployKeyVault) {
31+
name: 'key-vault-resources'
32+
scope: resourceGroup
33+
params: {
34+
enableSoftDelete: false
35+
keyVaultName: 'kv-${resourceToken}'
36+
location: location
37+
roleAssignments: [
38+
{
39+
// https://docs.microsoft.com/en-us/azure/key-vault/general/rbac-guide?tabs=azure-cli#azure-built-in-roles-for-key-vault-data-plane-operations
40+
roleDefinitionId: '4633458b-17de-408a-b874-0445c86b69e6'
41+
principalType: 'ServicePrincipal'
42+
principalId: principalId
43+
}
44+
]
45+
tags: tags
46+
}
47+
}
48+
49+
module swaResources 'resources/static-sites.bicep' = {
50+
name: 'static-sites-resources'
51+
scope: resourceGroup
52+
params: {
53+
appSettings: {
54+
APPINSIGHTS_INSTRUMENTATIONKEY: deployAppInsights ? applicationInsightsResources.outputs.connectionString : null
55+
STORAGE_CONNECTION_STRING: storageResources.outputs.connectionString
56+
DATABASE_URL: databaseResources.outputs.url
57+
SHADOW_DATABASE_URL: databaseResources.outputs.urlShadow
58+
AzureWebJobsStorage: storageResources.outputs.connectionString
59+
FUNCTIONS_EXTENSION_VERSION: '~4'
60+
FUNCTIONS_WORKER_RUNTIME: 'node'
61+
SCM_DO_BUILD_DURING_DEPLOYMENT: 'true'
62+
}
63+
buildProperties: {
64+
skipGithubActionWorkflowGeneration: true
65+
}
66+
location: location
67+
staticSiteName: 'stapp-${resourceToken}'
68+
tags: tags
69+
}
70+
}
71+
72+
module storageResources 'resources/storage.bicep' = {
73+
name: 'storage-resources'
74+
scope: resourceGroup
75+
params: {
76+
location: location
77+
storageName: 'st${resourceToken}'
78+
tags: tags
79+
}
80+
}
81+
82+
module logAnalyticsResources 'resources/log-analytics.bicep' = {
83+
name: 'log-analytics-resources'
84+
scope: resourceGroup
85+
params: {
86+
logAnalyticsName: 'log-${resourceToken}'
87+
location: location
88+
tags: tags
89+
}
90+
}
91+
92+
module applicationInsightsResources 'resources/applicationinsights.bicep' = if (deployAppInsights) {
93+
name: 'applicationinsights-resources'
94+
scope: resourceGroup
95+
params: {
96+
applicationInsightsName: resourceToken
97+
location: location
98+
workspaceId: logAnalyticsResources.outputs.workspaceId
99+
tags: tags
100+
}
101+
}
102+
103+
module databaseResources 'resources/sql-server.bicep' = {
104+
name: 'database-resources'
105+
scope: resourceGroup
106+
params: {
107+
sqlServerName: 'sql-${resourceToken}'
108+
databaseName: 'sqldb-${resourceToken}'
109+
administratorLogin: 'prisma-azure'
110+
location: location
111+
tags: tags
112+
}
113+
}
114+
115+
output DATABASE_URL string = databaseResources.outputs.url
116+
output SHADOW_DATABASE_URL string = databaseResources.outputs.urlShadow
117+
output AZURE_LOCATION string = location
118+
output AZURE_TENANT_ID string = tenant().tenantId

infra/main.parameters.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
3+
"contentVersion": "1.0.0.0",
4+
"parameters": {
5+
"name": {
6+
"value": "${AZURE_ENV_NAME}"
7+
},
8+
"location": {
9+
"value": "${AZURE_LOCATION}"
10+
},
11+
"principalId": {
12+
"value": "${AZURE_PRINCIPAL_ID}"
13+
}
14+
}
15+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
param applicationInsightsName string
2+
param location string
3+
param tags object
4+
param workspaceId string
5+
6+
resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
7+
name: 'appi-${applicationInsightsName}'
8+
location: location
9+
tags: tags
10+
kind: 'web'
11+
properties: {
12+
Application_Type: 'web'
13+
WorkspaceResourceId: workspaceId
14+
}
15+
}
16+
17+
output connectionString string = applicationInsights.properties.ConnectionString

infra/resources/key-vault.bicep

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
@description('Resource tags.')
2+
param tags object
3+
4+
@description('Resource location.')
5+
param location string
6+
7+
@description('The name of the key vault. e.g. kv-swa-sso')
8+
param keyVaultName string
9+
10+
@description('The name of the SKU for the key vault.')
11+
param sku string = 'Standard'
12+
13+
@description('Tenant id for the subscription.')
14+
param tenant string = subscription().tenantId
15+
16+
@description('Enables soft delete.')
17+
param enableSoftDelete bool = true
18+
19+
@description('Soft delete retention period.')
20+
param softDeleteRetentionInDays int = 7
21+
22+
@description('An array of role assignment objects. Format: [{ roleDefinitionId: xxx, principalType: xxx, principalId: xxx }]')
23+
param roleAssignments array
24+
// E.g.
25+
// [
26+
// {
27+
// roleDefinitionId: 'replace'
28+
// principalType: 'replace'
29+
// principalId: 'replace'
30+
// }
31+
// ]
32+
33+
resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' = {
34+
name: keyVaultName
35+
location: location
36+
tags: tags
37+
properties: {
38+
sku: {
39+
name: sku
40+
family: 'A'
41+
}
42+
tenantId: tenant
43+
enabledForTemplateDeployment: true
44+
enableRbacAuthorization: true
45+
enableSoftDelete: enableSoftDelete
46+
softDeleteRetentionInDays: softDeleteRetentionInDays
47+
networkAcls: {
48+
bypass: 'AzureServices'
49+
defaultAction: 'Allow'
50+
}
51+
}
52+
}
53+
54+
resource keyVaultRoleAssignments 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = [for role in roleAssignments: {
55+
name: guid(keyVault.name, role.roleDefinitionId, role.principalId)
56+
scope: keyVault
57+
properties: {
58+
principalType: role.principalType
59+
roleDefinitionId: resourceId('microsoft.authorization/roleDefinitions', role.roleDefinitionId)
60+
principalId: role.principalId
61+
}
62+
}]
63+
64+
output keyVaultName string = keyVault.name
65+
output keyVaultResourceId string = keyVault.id
66+
output keyVaultEndpoint string = keyVault.properties.vaultUri

infra/resources/log-analytics.bicep

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
@description('Resource tags.')
2+
param tags object
3+
4+
@description('Resource location.')
5+
param location string
6+
7+
@description('The name of the log Analytics workspace. e.g. log-demo')
8+
param logAnalyticsName string
9+
10+
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = {
11+
name: logAnalyticsName
12+
location: location
13+
tags: tags
14+
properties: any({
15+
retentionInDays: 30
16+
features: {
17+
searchVersion: 1
18+
}
19+
sku: {
20+
name: 'PerGB2018'
21+
}
22+
})
23+
}
24+
25+
output workspaceId string = logAnalyticsWorkspace.id

0 commit comments

Comments
 (0)