Pamela Fox
commited on
Commit
·
9595e1d
1
Parent(s):
f72f77b
Port to core (appservice/vnet/pg changes made)
Browse files- infra/core/database/cosmos/cosmos-account.bicep +48 -0
- infra/core/database/cosmos/mongo/cosmos-mongo-account.bicep +22 -0
- infra/core/database/cosmos/mongo/cosmos-mongo-db.bicep +46 -0
- infra/core/database/cosmos/sql/cosmos-sql-account.bicep +21 -0
- infra/core/database/cosmos/sql/cosmos-sql-db.bicep +73 -0
- infra/core/database/cosmos/sql/cosmos-sql-role-assign.bicep +18 -0
- infra/core/database/cosmos/sql/cosmos-sql-role-def.bicep +29 -0
- infra/core/database/postgresql/flexibleserver.bicep +51 -0
- infra/core/database/sqlserver/sqlserver.bicep +129 -0
- infra/core/gateway/apim-api-policy.xml +92 -0
- infra/core/gateway/apim.bicep +61 -0
- infra/core/host/appservice.bicep +111 -0
- infra/core/host/appserviceplan.bicep +20 -0
- infra/core/host/container-app.bicep +77 -0
- infra/core/host/container-apps-environment.bicep +26 -0
- infra/core/host/container-apps.bicep +30 -0
- infra/core/host/container-registry.bicep +36 -0
- infra/core/host/functions.bicep +82 -0
- infra/core/host/staticwebapp.bicep +21 -0
- infra/core/monitor/applicationinsights-dashboard.bicep +1235 -0
- infra/core/monitor/applicationinsights.bicep +30 -0
- infra/core/monitor/loganalytics.bicep +21 -0
- infra/core/monitor/monitoring.bicep +31 -0
- infra/core/security/dnszone.bicep +23 -0
- infra/core/security/keyvault-access.bicep +21 -0
- infra/core/security/keyvault-secret.bicep +30 -0
- infra/core/security/keyvault.bicep +25 -0
- infra/core/security/virtualnetwork.bicep +83 -0
- infra/core/storage/storage-account.bicep +38 -0
- infra/main.bicep +88 -5
- infra/resources.bicep +0 -222
infra/core/database/cosmos/cosmos-account.bicep
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param connectionStringKey string = 'AZURE-COSMOS-CONNECTION-STRING'
|
6 |
+
param keyVaultName string
|
7 |
+
|
8 |
+
@allowed([ 'GlobalDocumentDB', 'MongoDB', 'Parse' ])
|
9 |
+
param kind string
|
10 |
+
|
11 |
+
resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' = {
|
12 |
+
name: name
|
13 |
+
kind: kind
|
14 |
+
location: location
|
15 |
+
tags: tags
|
16 |
+
properties: {
|
17 |
+
consistencyPolicy: { defaultConsistencyLevel: 'Session' }
|
18 |
+
locations: [
|
19 |
+
{
|
20 |
+
locationName: location
|
21 |
+
failoverPriority: 0
|
22 |
+
isZoneRedundant: false
|
23 |
+
}
|
24 |
+
]
|
25 |
+
databaseAccountOfferType: 'Standard'
|
26 |
+
enableAutomaticFailover: false
|
27 |
+
enableMultipleWriteLocations: false
|
28 |
+
apiProperties: (kind == 'MongoDB') ? { serverVersion: '4.0' } : {}
|
29 |
+
capabilities: [ { name: 'EnableServerless' } ]
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
resource cosmosConnectionString 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
|
34 |
+
parent: keyVault
|
35 |
+
name: connectionStringKey
|
36 |
+
properties: {
|
37 |
+
value: cosmos.listConnectionStrings().connectionStrings[0].connectionString
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
|
42 |
+
name: keyVaultName
|
43 |
+
}
|
44 |
+
|
45 |
+
output connectionStringKey string = connectionStringKey
|
46 |
+
output endpoint string = cosmos.properties.documentEndpoint
|
47 |
+
output id string = cosmos.id
|
48 |
+
output name string = cosmos.name
|
infra/core/database/cosmos/mongo/cosmos-mongo-account.bicep
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param keyVaultName string
|
6 |
+
param connectionStringKey string = 'AZURE-COSMOS-CONNECTION-STRING'
|
7 |
+
|
8 |
+
module cosmos '../../cosmos/cosmos-account.bicep' = {
|
9 |
+
name: 'cosmos-account'
|
10 |
+
params: {
|
11 |
+
name: name
|
12 |
+
location: location
|
13 |
+
connectionStringKey: connectionStringKey
|
14 |
+
keyVaultName: keyVaultName
|
15 |
+
kind: 'MongoDB'
|
16 |
+
tags: tags
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
output connectionStringKey string = cosmos.outputs.connectionStringKey
|
21 |
+
output endpoint string = cosmos.outputs.endpoint
|
22 |
+
output id string = cosmos.outputs.id
|
infra/core/database/cosmos/mongo/cosmos-mongo-db.bicep
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param accountName string
|
2 |
+
param databaseName string
|
3 |
+
param location string = resourceGroup().location
|
4 |
+
param tags object = {}
|
5 |
+
|
6 |
+
param collections array = []
|
7 |
+
param connectionStringKey string = 'AZURE-COSMOS-CONNECTION-STRING'
|
8 |
+
param keyVaultName string
|
9 |
+
|
10 |
+
module cosmos 'cosmos-mongo-account.bicep' = {
|
11 |
+
name: 'cosmos-mongo-account'
|
12 |
+
params: {
|
13 |
+
name: accountName
|
14 |
+
location: location
|
15 |
+
keyVaultName: keyVaultName
|
16 |
+
tags: tags
|
17 |
+
connectionStringKey: connectionStringKey
|
18 |
+
}
|
19 |
+
}
|
20 |
+
|
21 |
+
resource database 'Microsoft.DocumentDB/databaseAccounts/mongodbDatabases@2022-08-15' = {
|
22 |
+
name: '${accountName}/${databaseName}'
|
23 |
+
tags: tags
|
24 |
+
properties: {
|
25 |
+
resource: { id: databaseName }
|
26 |
+
}
|
27 |
+
|
28 |
+
resource list 'collections' = [for collection in collections: {
|
29 |
+
name: collection.name
|
30 |
+
properties: {
|
31 |
+
resource: {
|
32 |
+
id: collection.id
|
33 |
+
shardKey: { _id: collection.shardKey }
|
34 |
+
indexes: [ { key: { keys: [ collection.indexKey ] } } ]
|
35 |
+
}
|
36 |
+
}
|
37 |
+
}]
|
38 |
+
|
39 |
+
dependsOn: [
|
40 |
+
cosmos
|
41 |
+
]
|
42 |
+
}
|
43 |
+
|
44 |
+
output connectionStringKey string = connectionStringKey
|
45 |
+
output databaseName string = databaseName
|
46 |
+
output endpoint string = cosmos.outputs.endpoint
|
infra/core/database/cosmos/sql/cosmos-sql-account.bicep
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param keyVaultName string
|
6 |
+
|
7 |
+
module cosmos '../../cosmos/cosmos-account.bicep' = {
|
8 |
+
name: 'cosmos-account'
|
9 |
+
params: {
|
10 |
+
name: name
|
11 |
+
location: location
|
12 |
+
tags: tags
|
13 |
+
keyVaultName: keyVaultName
|
14 |
+
kind: 'GlobalDocumentDB'
|
15 |
+
}
|
16 |
+
}
|
17 |
+
|
18 |
+
output connectionStringKey string = cosmos.outputs.connectionStringKey
|
19 |
+
output endpoint string = cosmos.outputs.endpoint
|
20 |
+
output id string = cosmos.outputs.id
|
21 |
+
output name string = cosmos.outputs.name
|
infra/core/database/cosmos/sql/cosmos-sql-db.bicep
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param accountName string
|
2 |
+
param databaseName string
|
3 |
+
param location string = resourceGroup().location
|
4 |
+
param tags object = {}
|
5 |
+
|
6 |
+
param containers array = []
|
7 |
+
param keyVaultName string
|
8 |
+
param principalIds array = []
|
9 |
+
|
10 |
+
module cosmos 'cosmos-sql-account.bicep' = {
|
11 |
+
name: 'cosmos-sql-account'
|
12 |
+
params: {
|
13 |
+
name: accountName
|
14 |
+
location: location
|
15 |
+
tags: tags
|
16 |
+
keyVaultName: keyVaultName
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
resource database 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2022-05-15' = {
|
21 |
+
name: '${accountName}/${databaseName}'
|
22 |
+
properties: {
|
23 |
+
resource: { id: databaseName }
|
24 |
+
}
|
25 |
+
|
26 |
+
resource list 'containers' = [for container in containers: {
|
27 |
+
name: container.name
|
28 |
+
properties: {
|
29 |
+
resource: {
|
30 |
+
id: container.id
|
31 |
+
partitionKey: { paths: [ container.partitionKey ] }
|
32 |
+
}
|
33 |
+
options: {}
|
34 |
+
}
|
35 |
+
}]
|
36 |
+
|
37 |
+
dependsOn: [
|
38 |
+
cosmos
|
39 |
+
]
|
40 |
+
}
|
41 |
+
|
42 |
+
module roleDefintion 'cosmos-sql-role-def.bicep' = {
|
43 |
+
name: 'cosmos-sql-role-definition'
|
44 |
+
params: {
|
45 |
+
accountName: accountName
|
46 |
+
}
|
47 |
+
dependsOn: [
|
48 |
+
cosmos
|
49 |
+
database
|
50 |
+
]
|
51 |
+
}
|
52 |
+
|
53 |
+
// We need batchSize(1) here because sql role assignments have to be done sequentially
|
54 |
+
@batchSize(1)
|
55 |
+
module userRole 'cosmos-sql-role-assign.bicep' = [for principalId in principalIds: if (!empty(principalId)) {
|
56 |
+
name: 'cosmos-sql-user-role-${uniqueString(principalId)}'
|
57 |
+
params: {
|
58 |
+
accountName: accountName
|
59 |
+
roleDefinitionId: roleDefintion.outputs.id
|
60 |
+
principalId: principalId
|
61 |
+
}
|
62 |
+
dependsOn: [
|
63 |
+
cosmos
|
64 |
+
database
|
65 |
+
]
|
66 |
+
}]
|
67 |
+
|
68 |
+
output accountId string = cosmos.outputs.id
|
69 |
+
output accountName string = cosmos.outputs.name
|
70 |
+
output connectionStringKey string = cosmos.outputs.connectionStringKey
|
71 |
+
output databaseName string = databaseName
|
72 |
+
output endpoint string = cosmos.outputs.endpoint
|
73 |
+
output roleDefinitionId string = roleDefintion.outputs.id
|
infra/core/database/cosmos/sql/cosmos-sql-role-assign.bicep
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param accountName string
|
2 |
+
|
3 |
+
param roleDefinitionId string
|
4 |
+
param principalId string = ''
|
5 |
+
|
6 |
+
resource role 'Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments@2022-05-15' = {
|
7 |
+
parent: cosmos
|
8 |
+
name: guid(roleDefinitionId, principalId, cosmos.id)
|
9 |
+
properties: {
|
10 |
+
principalId: principalId
|
11 |
+
roleDefinitionId: roleDefinitionId
|
12 |
+
scope: cosmos.id
|
13 |
+
}
|
14 |
+
}
|
15 |
+
|
16 |
+
resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' existing = {
|
17 |
+
name: accountName
|
18 |
+
}
|
infra/core/database/cosmos/sql/cosmos-sql-role-def.bicep
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param accountName string
|
2 |
+
|
3 |
+
resource roleDefinition 'Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions@2022-08-15' = {
|
4 |
+
parent: cosmos
|
5 |
+
name: guid(cosmos.id, accountName, 'sql-role')
|
6 |
+
properties: {
|
7 |
+
assignableScopes: [
|
8 |
+
cosmos.id
|
9 |
+
]
|
10 |
+
permissions: [
|
11 |
+
{
|
12 |
+
dataActions: [
|
13 |
+
'Microsoft.DocumentDB/databaseAccounts/readMetadata'
|
14 |
+
'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*'
|
15 |
+
'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*'
|
16 |
+
]
|
17 |
+
notDataActions: []
|
18 |
+
}
|
19 |
+
]
|
20 |
+
roleName: 'Reader Writer'
|
21 |
+
type: 'CustomRole'
|
22 |
+
}
|
23 |
+
}
|
24 |
+
|
25 |
+
resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' existing = {
|
26 |
+
name: accountName
|
27 |
+
}
|
28 |
+
|
29 |
+
output id string = roleDefinition.id
|
infra/core/database/postgresql/flexibleserver.bicep
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param sku object
|
6 |
+
param storage object
|
7 |
+
param delegatedSubnetResourceId string = ''
|
8 |
+
param privateDnsZoneArmResourceId string = ''
|
9 |
+
param privateDnsZoneLink object = {}
|
10 |
+
|
11 |
+
param databaseName string
|
12 |
+
param administratorLogin string
|
13 |
+
@secure()
|
14 |
+
param administratorLoginPassword string
|
15 |
+
|
16 |
+
// PostgreSQL version
|
17 |
+
@allowed(['11', '12', '13', '14', '15'])
|
18 |
+
param version string
|
19 |
+
|
20 |
+
resource postgresServer 'Microsoft.DBforPostgreSQL/flexibleServers@2022-01-20-preview' = {
|
21 |
+
location: location
|
22 |
+
tags: tags
|
23 |
+
name: name
|
24 |
+
sku: sku
|
25 |
+
properties: {
|
26 |
+
version: version
|
27 |
+
administratorLogin: administratorLogin
|
28 |
+
administratorLoginPassword: administratorLoginPassword
|
29 |
+
storage: storage
|
30 |
+
network: union(
|
31 |
+
!empty(delegatedSubnetResourceId) ? { delegatedSubnetResourceId: delegatedSubnetResourceId } : {},
|
32 |
+
!empty(privateDnsZoneArmResourceId) ? {privateDnsZoneArmResourceId: privateDnsZoneArmResourceId } : {})
|
33 |
+
highAvailability: {
|
34 |
+
mode: 'Disabled'
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
resource database 'databases' = {
|
39 |
+
name: databaseName
|
40 |
+
}
|
41 |
+
|
42 |
+
resource firewall 'firewallRules' = {
|
43 |
+
name: 'AllowAllWindowsAzureIps'
|
44 |
+
properties: {
|
45 |
+
startIpAddress: '0.0.0.0'
|
46 |
+
endIpAddress: '0.0.0.0'
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
+
dependsOn: empty(privateDnsZoneLink) ? [] : [privateDnsZoneLink]
|
51 |
+
}
|
infra/core/database/sqlserver/sqlserver.bicep
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param appUser string = 'appUser'
|
6 |
+
param databaseName string
|
7 |
+
param keyVaultName string
|
8 |
+
param sqlAdmin string = 'sqlAdmin'
|
9 |
+
param connectionStringKey string = 'AZURE-SQL-CONNECTION-STRING'
|
10 |
+
|
11 |
+
@secure()
|
12 |
+
param sqlAdminPassword string
|
13 |
+
@secure()
|
14 |
+
param appUserPassword string
|
15 |
+
|
16 |
+
resource sqlServer 'Microsoft.Sql/servers@2022-05-01-preview' = {
|
17 |
+
name: name
|
18 |
+
location: location
|
19 |
+
tags: tags
|
20 |
+
properties: {
|
21 |
+
version: '12.0'
|
22 |
+
minimalTlsVersion: '1.2'
|
23 |
+
publicNetworkAccess: 'Enabled'
|
24 |
+
administratorLogin: sqlAdmin
|
25 |
+
administratorLoginPassword: sqlAdminPassword
|
26 |
+
}
|
27 |
+
|
28 |
+
resource database 'databases' = {
|
29 |
+
name: databaseName
|
30 |
+
location: location
|
31 |
+
}
|
32 |
+
|
33 |
+
resource firewall 'firewallRules' = {
|
34 |
+
name: 'Azure Services'
|
35 |
+
properties: {
|
36 |
+
// Allow all clients
|
37 |
+
// Note: range [0.0.0.0-0.0.0.0] means "allow all Azure-hosted clients only".
|
38 |
+
// This is not sufficient, because we also want to allow direct access from developer machine, for debugging purposes.
|
39 |
+
startIpAddress: '0.0.0.1'
|
40 |
+
endIpAddress: '255.255.255.254'
|
41 |
+
}
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
resource sqlDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
|
46 |
+
name: '${name}-deployment-script'
|
47 |
+
location: location
|
48 |
+
kind: 'AzureCLI'
|
49 |
+
properties: {
|
50 |
+
azCliVersion: '2.37.0'
|
51 |
+
retentionInterval: 'PT1H' // Retain the script resource for 1 hour after it ends running
|
52 |
+
timeout: 'PT5M' // Five minutes
|
53 |
+
cleanupPreference: 'OnSuccess'
|
54 |
+
environmentVariables: [
|
55 |
+
{
|
56 |
+
name: 'APPUSERNAME'
|
57 |
+
value: appUser
|
58 |
+
}
|
59 |
+
{
|
60 |
+
name: 'APPUSERPASSWORD'
|
61 |
+
secureValue: appUserPassword
|
62 |
+
}
|
63 |
+
{
|
64 |
+
name: 'DBNAME'
|
65 |
+
value: databaseName
|
66 |
+
}
|
67 |
+
{
|
68 |
+
name: 'DBSERVER'
|
69 |
+
value: sqlServer.properties.fullyQualifiedDomainName
|
70 |
+
}
|
71 |
+
{
|
72 |
+
name: 'SQLCMDPASSWORD'
|
73 |
+
secureValue: sqlAdminPassword
|
74 |
+
}
|
75 |
+
{
|
76 |
+
name: 'SQLADMIN'
|
77 |
+
value: sqlAdmin
|
78 |
+
}
|
79 |
+
]
|
80 |
+
|
81 |
+
scriptContent: '''
|
82 |
+
wget https://github.com/microsoft/go-sqlcmd/releases/download/v0.8.1/sqlcmd-v0.8.1-linux-x64.tar.bz2
|
83 |
+
tar x -f sqlcmd-v0.8.1-linux-x64.tar.bz2 -C .
|
84 |
+
|
85 |
+
cat <<SCRIPT_END > ./initDb.sql
|
86 |
+
drop user ${APPUSERNAME}
|
87 |
+
go
|
88 |
+
create user ${APPUSERNAME} with password = '${APPUSERPASSWORD}'
|
89 |
+
go
|
90 |
+
alter role db_owner add member ${APPUSERNAME}
|
91 |
+
go
|
92 |
+
SCRIPT_END
|
93 |
+
|
94 |
+
./sqlcmd -S ${DBSERVER} -d ${DBNAME} -U ${SQLADMIN} -i ./initDb.sql
|
95 |
+
'''
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
resource sqlAdminPasswordSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
|
100 |
+
parent: keyVault
|
101 |
+
name: 'sqlAdminPassword'
|
102 |
+
properties: {
|
103 |
+
value: sqlAdminPassword
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
resource appUserPasswordSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
|
108 |
+
parent: keyVault
|
109 |
+
name: 'appUserPassword'
|
110 |
+
properties: {
|
111 |
+
value: appUserPassword
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
resource sqlAzureConnectionStringSercret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
|
116 |
+
parent: keyVault
|
117 |
+
name: connectionStringKey
|
118 |
+
properties: {
|
119 |
+
value: '${connectionString}; Password=${appUserPassword}'
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
|
124 |
+
name: keyVaultName
|
125 |
+
}
|
126 |
+
|
127 |
+
var connectionString = 'Server=${sqlServer.properties.fullyQualifiedDomainName}; Database=${sqlServer::database.name}; User=${appUser}'
|
128 |
+
output connectionStringKey string = connectionStringKey
|
129 |
+
output databaseName string = sqlServer::database.name
|
infra/core/gateway/apim-api-policy.xml
ADDED
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!-- Policy configuration for the API. Explore other sample policies at https://learn.microsoft.com/en-us/azure/api-management/policies/ -->
|
2 |
+
<policies>
|
3 |
+
<inbound>
|
4 |
+
<base />
|
5 |
+
<!-- This policy is needed to handle preflight requests using the OPTIONS method. Learn more at https://learn.microsoft.com/en-us/azure/api-management/api-management-cross-domain-policies -->
|
6 |
+
<cors allow-credentials="false">
|
7 |
+
<allowed-origins>
|
8 |
+
<origin>{0}</origin>
|
9 |
+
</allowed-origins>
|
10 |
+
<allowed-methods>
|
11 |
+
<method>PUT</method>
|
12 |
+
<method>GET</method>
|
13 |
+
<method>POST</method>
|
14 |
+
<method>DELETE</method>
|
15 |
+
<method>PATCH</method>
|
16 |
+
</allowed-methods>
|
17 |
+
<allowed-headers>
|
18 |
+
<header>*</header>
|
19 |
+
</allowed-headers>
|
20 |
+
<expose-headers>
|
21 |
+
<header>*</header>
|
22 |
+
</expose-headers>
|
23 |
+
</cors>
|
24 |
+
<!-- Optional policy to validate the request content. Learn more at https://learn.microsoft.com/en-us/azure/api-management/validation-policies#validate-content -->
|
25 |
+
<validate-content unspecified-content-type-action="ignore" max-size="1024" size-exceeded-action="detect" errors-variable-name="requestBodyValidation">
|
26 |
+
<content type="application/json" validate-as="json" action="detect" />
|
27 |
+
</validate-content>
|
28 |
+
<!-- Optional policy to send custom trace telemetry to Application Insights. Learn more at https://learn.microsoft.com/en-us/azure/api-management/api-management-advanced-policies#Trace -->
|
29 |
+
<trace source="@(context.Api.Name)" severity="verbose">
|
30 |
+
<message>Call to the @(context.Api.Name)</message>
|
31 |
+
<metadata name="User-Agent" value="@(context.Request.Headers.GetValueOrDefault("User-Agent",""))" />
|
32 |
+
<metadata name="Operation Method" value="@(context.Request.Method)" />
|
33 |
+
<metadata name="Host" value="@(context.Request.Url.Host)" />
|
34 |
+
<metadata name="Path" value="@(context.Request.Url.Path)" />
|
35 |
+
</trace>
|
36 |
+
</inbound>
|
37 |
+
<backend>
|
38 |
+
<limit-concurrency key="@(context.Request.IpAddress)" max-count="3">
|
39 |
+
<forward-request timeout="120" />
|
40 |
+
</limit-concurrency>
|
41 |
+
</backend>
|
42 |
+
<outbound>
|
43 |
+
<base />
|
44 |
+
<!-- Optional policy to validate the response headers. Learn more at https://learn.microsoft.com/en-us/azure/api-management/validation-policies#validate-headers -->
|
45 |
+
<validate-headers specified-header-action="ignore" unspecified-header-action="ignore" errors-variable-name="responseHeadersValidation" />
|
46 |
+
<!-- Optional policy to to send custom metrics to Application Insights. Learn more at https://learn.microsoft.com/en-us/azure/api-management/api-management-advanced-policies#emit-metrics -->
|
47 |
+
<choose>
|
48 |
+
<when condition="@(context.Response.StatusCode >= 200 && context.Response.StatusCode < 300)">
|
49 |
+
<emit-metric name="Successful requests" value="1" namespace="apim-metrics">
|
50 |
+
<dimension name="API" value="@(context.Api.Name)" />
|
51 |
+
<dimension name="Client IP" value="@(context.Request.IpAddress)" />
|
52 |
+
<dimension name="Status Code" value="@((String)context.Response.StatusCode.ToString())" />
|
53 |
+
<dimension name="Status Reason" value="@(context.Response.StatusReason)" />
|
54 |
+
</emit-metric>
|
55 |
+
</when>
|
56 |
+
<when condition="@(context.Response.StatusCode >= 400 && context.Response.StatusCode < 600)">
|
57 |
+
<emit-metric name="Failed requests" value="1" namespace="apim-metrics">
|
58 |
+
<dimension name="API" value="@(context.Api.Name)" />
|
59 |
+
<dimension name="Client IP" value="@(context.Request.IpAddress)" />
|
60 |
+
<dimension name="Status Code" value="@(context.Response.StatusCode.ToString())" />
|
61 |
+
<dimension name="Status Reason" value="@(context.Response.StatusReason)" />
|
62 |
+
<dimension name="Error Source" value="backend" />
|
63 |
+
</emit-metric>
|
64 |
+
</when>
|
65 |
+
</choose>
|
66 |
+
</outbound>
|
67 |
+
<on-error>
|
68 |
+
<base />
|
69 |
+
<!-- Optional policy to handle errors. Learn more at https://learn.microsoft.com/en-us/azure/api-management/api-management-error-handling-policies -->
|
70 |
+
<trace source="@(context.Api.Name)" severity="error">
|
71 |
+
<message>Failed to process the @(context.Api.Name)</message>
|
72 |
+
<metadata name="User-Agent" value="@(context.Request.Headers.GetValueOrDefault("User-Agent",""))" />
|
73 |
+
<metadata name="Operation Method" value="@(context.Request.Method)" />
|
74 |
+
<metadata name="Host" value="@(context.Request.Url.Host)" />
|
75 |
+
<metadata name="Path" value="@(context.Request.Url.Path)" />
|
76 |
+
<metadata name="Error Reason" value="@(context.LastError.Reason)" />
|
77 |
+
<metadata name="Error Message" value="@(context.LastError.Message)" />
|
78 |
+
</trace>
|
79 |
+
<emit-metric name="Failed requests" value="1" namespace="apim-metrics">
|
80 |
+
<dimension name="API" value="@(context.Api.Name)" />
|
81 |
+
<dimension name="Client IP" value="@(context.Request.IpAddress)" />
|
82 |
+
<dimension name="Status Code" value="500" />
|
83 |
+
<dimension name="Status Reason" value="@(context.LastError.Reason)" />
|
84 |
+
<dimension name="Error Source" value="gateway" />
|
85 |
+
</emit-metric>
|
86 |
+
<!-- Optional policy to hide error details and provide a custom generic message. Learn more at https://learn.microsoft.com/en-us/azure/api-management/api-management-advanced-policies#ReturnResponse -->
|
87 |
+
<return-response>
|
88 |
+
<set-status code="500" reason="Internal Server Error" />
|
89 |
+
<set-body>We're Sorry. An unexpected error has occurred. If this continues please contact Tech Support.</set-body>
|
90 |
+
</return-response>
|
91 |
+
</on-error>
|
92 |
+
</policies>
|
infra/core/gateway/apim.bicep
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
@description('The email address of the owner of the service')
|
6 |
+
@minLength(1)
|
7 |
+
param publisherEmail string = '[email protected]'
|
8 |
+
|
9 |
+
@description('The name of the owner of the service')
|
10 |
+
@minLength(1)
|
11 |
+
param publisherName string = 'n/a'
|
12 |
+
|
13 |
+
@description('The pricing tier of this API Management service')
|
14 |
+
@allowed([
|
15 |
+
'Consumption'
|
16 |
+
'Developer'
|
17 |
+
'Standard'
|
18 |
+
'Premium'
|
19 |
+
])
|
20 |
+
param sku string = 'Consumption'
|
21 |
+
|
22 |
+
@description('The instance size of this API Management service.')
|
23 |
+
@allowed([ 0, 1, 2 ])
|
24 |
+
param skuCount int = 0
|
25 |
+
|
26 |
+
@description('Azure Application Insights Name')
|
27 |
+
param applicationInsightsName string
|
28 |
+
|
29 |
+
resource apimService 'Microsoft.ApiManagement/service@2021-08-01' = {
|
30 |
+
name: name
|
31 |
+
location: location
|
32 |
+
tags: union(tags, { 'azd-service-name': name })
|
33 |
+
sku: {
|
34 |
+
name: sku
|
35 |
+
capacity: (sku == 'Consumption') ? 0 : ((sku == 'Developer') ? 1 : skuCount)
|
36 |
+
}
|
37 |
+
properties: {
|
38 |
+
publisherEmail: publisherEmail
|
39 |
+
publisherName: publisherName
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
resource apimLogger 'Microsoft.ApiManagement/service/loggers@2021-12-01-preview' = if (!empty(applicationInsightsName)) {
|
44 |
+
name: 'app-insights-logger'
|
45 |
+
parent: apimService
|
46 |
+
properties: {
|
47 |
+
credentials: {
|
48 |
+
instrumentationKey: applicationInsights.properties.InstrumentationKey
|
49 |
+
}
|
50 |
+
description: 'Logger to Azure Application Insights'
|
51 |
+
isBuffered: false
|
52 |
+
loggerType: 'applicationInsights'
|
53 |
+
resourceId: applicationInsights.id
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = if (!empty(applicationInsightsName)) {
|
58 |
+
name: applicationInsightsName
|
59 |
+
}
|
60 |
+
|
61 |
+
output apimServiceName string = apimService.name
|
infra/core/host/appservice.bicep
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
// Reference Properties
|
6 |
+
param applicationInsightsName string = ''
|
7 |
+
param appServicePlanId string
|
8 |
+
param keyVaultName string = ''
|
9 |
+
param managedIdentity bool = !empty(keyVaultName)
|
10 |
+
|
11 |
+
// Runtime Properties
|
12 |
+
@allowed([
|
13 |
+
'dotnet', 'dotnetcore', 'dotnet-isolated', 'node', 'python', 'java', 'powershell', 'custom'
|
14 |
+
])
|
15 |
+
param runtimeName string
|
16 |
+
param runtimeNameAndVersion string = '${runtimeName}|${runtimeVersion}'
|
17 |
+
param runtimeVersion string
|
18 |
+
|
19 |
+
// Microsoft.Web/sites Properties
|
20 |
+
param kind string = 'app,linux'
|
21 |
+
|
22 |
+
// Microsoft.Web/sites/config
|
23 |
+
param allowedOrigins array = []
|
24 |
+
param alwaysOn bool = true
|
25 |
+
param appCommandLine string = ''
|
26 |
+
param appSettings object = {}
|
27 |
+
param clientAffinityEnabled bool = false
|
28 |
+
param enableOryxBuild bool = contains(kind, 'linux')
|
29 |
+
param functionAppScaleLimit int = -1
|
30 |
+
param linuxFxVersion string = runtimeNameAndVersion
|
31 |
+
param minimumElasticInstanceCount int = -1
|
32 |
+
param numberOfWorkers int = -1
|
33 |
+
param scmDoBuildDuringDeployment bool = false
|
34 |
+
param use32BitWorkerProcess bool = false
|
35 |
+
param ftpsState string = 'FtpsOnly'
|
36 |
+
|
37 |
+
// Microsoft.Web/sites/networkConfig
|
38 |
+
param subnetResourceId string = ''
|
39 |
+
param virtualNetwork object
|
40 |
+
|
41 |
+
resource appService 'Microsoft.Web/sites@2022-03-01' = {
|
42 |
+
name: name
|
43 |
+
location: location
|
44 |
+
tags: tags
|
45 |
+
kind: kind
|
46 |
+
properties: {
|
47 |
+
serverFarmId: appServicePlanId
|
48 |
+
siteConfig: {
|
49 |
+
linuxFxVersion: linuxFxVersion
|
50 |
+
alwaysOn: alwaysOn
|
51 |
+
ftpsState: ftpsState
|
52 |
+
appCommandLine: appCommandLine
|
53 |
+
numberOfWorkers: numberOfWorkers != -1 ? numberOfWorkers : null
|
54 |
+
minimumElasticInstanceCount: minimumElasticInstanceCount != -1 ? minimumElasticInstanceCount : null
|
55 |
+
use32BitWorkerProcess: use32BitWorkerProcess
|
56 |
+
functionAppScaleLimit: functionAppScaleLimit != -1 ? functionAppScaleLimit : null
|
57 |
+
cors: {
|
58 |
+
allowedOrigins: union([ 'https://portal.azure.com', 'https://ms.portal.azure.com' ], allowedOrigins)
|
59 |
+
}
|
60 |
+
}
|
61 |
+
clientAffinityEnabled: clientAffinityEnabled
|
62 |
+
httpsOnly: true
|
63 |
+
}
|
64 |
+
|
65 |
+
identity: { type: managedIdentity ? 'SystemAssigned' : 'None' }
|
66 |
+
|
67 |
+
resource configAppSettings 'config' = {
|
68 |
+
name: 'appsettings'
|
69 |
+
properties: union(appSettings,
|
70 |
+
{
|
71 |
+
SCM_DO_BUILD_DURING_DEPLOYMENT: string(scmDoBuildDuringDeployment)
|
72 |
+
ENABLE_ORYX_BUILD: string(enableOryxBuild)
|
73 |
+
},
|
74 |
+
!empty(applicationInsightsName) ? { APPLICATIONINSIGHTS_CONNECTION_STRING: applicationInsights.properties.ConnectionString } : {},
|
75 |
+
!empty(keyVaultName) ? { AZURE_KEY_VAULT_ENDPOINT: keyVault.properties.vaultUri } : {})
|
76 |
+
}
|
77 |
+
|
78 |
+
resource configLogs 'config' = {
|
79 |
+
name: 'logs'
|
80 |
+
properties: {
|
81 |
+
applicationLogs: { fileSystem: { level: 'Verbose' } }
|
82 |
+
detailedErrorMessages: { enabled: true }
|
83 |
+
failedRequestsTracing: { enabled: true }
|
84 |
+
httpLogs: { fileSystem: { enabled: true, retentionInDays: 1, retentionInMb: 35 } }
|
85 |
+
}
|
86 |
+
dependsOn: [
|
87 |
+
configAppSettings
|
88 |
+
]
|
89 |
+
}
|
90 |
+
|
91 |
+
resource webappVnetConfig 'networkConfig' = if (!(empty(virtualNetwork))) {
|
92 |
+
name: 'virtualNetwork'
|
93 |
+
properties: {
|
94 |
+
subnetResourceId: subnetResourceId
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
dependsOn: empty(virtualNetwork) ? [] : [virtualNetwork]
|
99 |
+
}
|
100 |
+
|
101 |
+
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = if (!(empty(keyVaultName))) {
|
102 |
+
name: keyVaultName
|
103 |
+
}
|
104 |
+
|
105 |
+
resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = if (!empty(applicationInsightsName)) {
|
106 |
+
name: applicationInsightsName
|
107 |
+
}
|
108 |
+
|
109 |
+
output identityPrincipalId string = managedIdentity ? appService.identity.principalId : ''
|
110 |
+
output name string = appService.name
|
111 |
+
output uri string = 'https://${appService.properties.defaultHostName}'
|
infra/core/host/appserviceplan.bicep
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param kind string = ''
|
6 |
+
param reserved bool = true
|
7 |
+
param sku object
|
8 |
+
|
9 |
+
resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = {
|
10 |
+
name: name
|
11 |
+
location: location
|
12 |
+
tags: tags
|
13 |
+
sku: sku
|
14 |
+
kind: kind
|
15 |
+
properties: {
|
16 |
+
reserved: reserved
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
output id string = appServicePlan.id
|
infra/core/host/container-app.bicep
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param containerAppsEnvironmentName string = ''
|
6 |
+
param containerName string = 'main'
|
7 |
+
param containerRegistryName string = ''
|
8 |
+
param env array = []
|
9 |
+
param external bool = true
|
10 |
+
param imageName string
|
11 |
+
param keyVaultName string = ''
|
12 |
+
param managedIdentity bool = !empty(keyVaultName)
|
13 |
+
param targetPort int = 80
|
14 |
+
|
15 |
+
@description('CPU cores allocated to a single container instance, e.g. 0.5')
|
16 |
+
param containerCpuCoreCount string = '0.5'
|
17 |
+
|
18 |
+
@description('Memory allocated to a single container instance, e.g. 1Gi')
|
19 |
+
param containerMemory string = '1.0Gi'
|
20 |
+
|
21 |
+
resource app 'Microsoft.App/containerApps@2022-03-01' = {
|
22 |
+
name: name
|
23 |
+
location: location
|
24 |
+
tags: tags
|
25 |
+
identity: { type: managedIdentity ? 'SystemAssigned' : 'None' }
|
26 |
+
properties: {
|
27 |
+
managedEnvironmentId: containerAppsEnvironment.id
|
28 |
+
configuration: {
|
29 |
+
activeRevisionsMode: 'single'
|
30 |
+
ingress: {
|
31 |
+
external: external
|
32 |
+
targetPort: targetPort
|
33 |
+
transport: 'auto'
|
34 |
+
}
|
35 |
+
secrets: [
|
36 |
+
{
|
37 |
+
name: 'registry-password'
|
38 |
+
value: containerRegistry.listCredentials().passwords[0].value
|
39 |
+
}
|
40 |
+
]
|
41 |
+
registries: [
|
42 |
+
{
|
43 |
+
server: '${containerRegistry.name}.azurecr.io'
|
44 |
+
username: containerRegistry.name
|
45 |
+
passwordSecretRef: 'registry-password'
|
46 |
+
}
|
47 |
+
]
|
48 |
+
}
|
49 |
+
template: {
|
50 |
+
containers: [
|
51 |
+
{
|
52 |
+
image: imageName
|
53 |
+
name: containerName
|
54 |
+
env: env
|
55 |
+
resources: {
|
56 |
+
cpu: json(containerCpuCoreCount)
|
57 |
+
memory: containerMemory
|
58 |
+
}
|
59 |
+
}
|
60 |
+
]
|
61 |
+
}
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2022-03-01' existing = {
|
66 |
+
name: containerAppsEnvironmentName
|
67 |
+
}
|
68 |
+
|
69 |
+
// 2022-02-01-preview needed for anonymousPullEnabled
|
70 |
+
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2022-02-01-preview' existing = {
|
71 |
+
name: containerRegistryName
|
72 |
+
}
|
73 |
+
|
74 |
+
output identityPrincipalId string = managedIdentity ? app.identity.principalId : ''
|
75 |
+
output imageName string = imageName
|
76 |
+
output name string = app.name
|
77 |
+
output uri string = 'https://${app.properties.configuration.ingress.fqdn}'
|
infra/core/host/container-apps-environment.bicep
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param logAnalyticsWorkspaceName string
|
6 |
+
|
7 |
+
resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2022-03-01' = {
|
8 |
+
name: name
|
9 |
+
location: location
|
10 |
+
tags: tags
|
11 |
+
properties: {
|
12 |
+
appLogsConfiguration: {
|
13 |
+
destination: 'log-analytics'
|
14 |
+
logAnalyticsConfiguration: {
|
15 |
+
customerId: logAnalyticsWorkspace.properties.customerId
|
16 |
+
sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
|
17 |
+
}
|
18 |
+
}
|
19 |
+
}
|
20 |
+
}
|
21 |
+
|
22 |
+
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = {
|
23 |
+
name: logAnalyticsWorkspaceName
|
24 |
+
}
|
25 |
+
|
26 |
+
output name string = containerAppsEnvironment.name
|
infra/core/host/container-apps.bicep
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param containerAppsEnvironmentName string = ''
|
6 |
+
param containerRegistryName string = ''
|
7 |
+
param logAnalyticsWorkspaceName string = ''
|
8 |
+
|
9 |
+
module containerAppsEnvironment 'container-apps-environment.bicep' = {
|
10 |
+
name: '${name}-container-apps-environment'
|
11 |
+
params: {
|
12 |
+
name: containerAppsEnvironmentName
|
13 |
+
location: location
|
14 |
+
tags: tags
|
15 |
+
logAnalyticsWorkspaceName: logAnalyticsWorkspaceName
|
16 |
+
}
|
17 |
+
}
|
18 |
+
|
19 |
+
module containerRegistry 'container-registry.bicep' = {
|
20 |
+
name: '${name}-container-registry'
|
21 |
+
params: {
|
22 |
+
name: containerRegistryName
|
23 |
+
location: location
|
24 |
+
tags: tags
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
output environmentName string = containerAppsEnvironment.outputs.name
|
29 |
+
output registryLoginServer string = containerRegistry.outputs.loginServer
|
30 |
+
output registryName string = containerRegistry.outputs.name
|
infra/core/host/container-registry.bicep
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param adminUserEnabled bool = true
|
6 |
+
param anonymousPullEnabled bool = false
|
7 |
+
param dataEndpointEnabled bool = false
|
8 |
+
param encryption object = {
|
9 |
+
status: 'disabled'
|
10 |
+
}
|
11 |
+
param networkRuleBypassOptions string = 'AzureServices'
|
12 |
+
param publicNetworkAccess string = 'Enabled'
|
13 |
+
param sku object = {
|
14 |
+
name: 'Basic'
|
15 |
+
}
|
16 |
+
param zoneRedundancy string = 'Disabled'
|
17 |
+
|
18 |
+
// 2022-02-01-preview needed for anonymousPullEnabled
|
19 |
+
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2022-02-01-preview' = {
|
20 |
+
name: name
|
21 |
+
location: location
|
22 |
+
tags: tags
|
23 |
+
sku: sku
|
24 |
+
properties: {
|
25 |
+
adminUserEnabled: adminUserEnabled
|
26 |
+
anonymousPullEnabled: anonymousPullEnabled
|
27 |
+
dataEndpointEnabled: dataEndpointEnabled
|
28 |
+
encryption: encryption
|
29 |
+
networkRuleBypassOptions: networkRuleBypassOptions
|
30 |
+
publicNetworkAccess: publicNetworkAccess
|
31 |
+
zoneRedundancy: zoneRedundancy
|
32 |
+
}
|
33 |
+
}
|
34 |
+
|
35 |
+
output loginServer string = containerRegistry.properties.loginServer
|
36 |
+
output name string = containerRegistry.name
|
infra/core/host/functions.bicep
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
// Reference Properties
|
6 |
+
param applicationInsightsName string = ''
|
7 |
+
param appServicePlanId string
|
8 |
+
param keyVaultName string = ''
|
9 |
+
param managedIdentity bool = !empty(keyVaultName)
|
10 |
+
param storageAccountName string
|
11 |
+
|
12 |
+
// Runtime Properties
|
13 |
+
@allowed([
|
14 |
+
'dotnet', 'dotnetcore', 'dotnet-isolated', 'node', 'python', 'java', 'powershell', 'custom'
|
15 |
+
])
|
16 |
+
param runtimeName string
|
17 |
+
param runtimeNameAndVersion string = '${runtimeName}|${runtimeVersion}'
|
18 |
+
param runtimeVersion string
|
19 |
+
|
20 |
+
// Function Settings
|
21 |
+
@allowed([
|
22 |
+
'~4', '~3', '~2', '~1'
|
23 |
+
])
|
24 |
+
param extensionVersion string = '~4'
|
25 |
+
|
26 |
+
// Microsoft.Web/sites Properties
|
27 |
+
param kind string = 'functionapp,linux'
|
28 |
+
|
29 |
+
// Microsoft.Web/sites/config
|
30 |
+
param allowedOrigins array = []
|
31 |
+
param alwaysOn bool = true
|
32 |
+
param appCommandLine string = ''
|
33 |
+
param appSettings object = {}
|
34 |
+
param clientAffinityEnabled bool = false
|
35 |
+
param enableOryxBuild bool = contains(kind, 'linux')
|
36 |
+
param functionAppScaleLimit int = -1
|
37 |
+
param linuxFxVersion string = runtimeNameAndVersion
|
38 |
+
param minimumElasticInstanceCount int = -1
|
39 |
+
param numberOfWorkers int = -1
|
40 |
+
param scmDoBuildDuringDeployment bool = true
|
41 |
+
param use32BitWorkerProcess bool = false
|
42 |
+
|
43 |
+
module functions 'appservice.bicep' = {
|
44 |
+
name: '${name}-functions'
|
45 |
+
params: {
|
46 |
+
name: name
|
47 |
+
location: location
|
48 |
+
tags: tags
|
49 |
+
allowedOrigins: allowedOrigins
|
50 |
+
alwaysOn: alwaysOn
|
51 |
+
appCommandLine: appCommandLine
|
52 |
+
applicationInsightsName: applicationInsightsName
|
53 |
+
appServicePlanId: appServicePlanId
|
54 |
+
appSettings: union(appSettings, {
|
55 |
+
AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};AccountKey=${storage.listKeys().keys[0].value};EndpointSuffix=${environment().suffixes.storage}'
|
56 |
+
FUNCTIONS_EXTENSION_VERSION: extensionVersion
|
57 |
+
FUNCTIONS_WORKER_RUNTIME: runtimeName
|
58 |
+
})
|
59 |
+
clientAffinityEnabled: clientAffinityEnabled
|
60 |
+
enableOryxBuild: enableOryxBuild
|
61 |
+
functionAppScaleLimit: functionAppScaleLimit
|
62 |
+
keyVaultName: keyVaultName
|
63 |
+
kind: kind
|
64 |
+
linuxFxVersion: linuxFxVersion
|
65 |
+
managedIdentity: managedIdentity
|
66 |
+
minimumElasticInstanceCount: minimumElasticInstanceCount
|
67 |
+
numberOfWorkers: numberOfWorkers
|
68 |
+
runtimeName: runtimeName
|
69 |
+
runtimeVersion: runtimeVersion
|
70 |
+
runtimeNameAndVersion: runtimeNameAndVersion
|
71 |
+
scmDoBuildDuringDeployment: scmDoBuildDuringDeployment
|
72 |
+
use32BitWorkerProcess: use32BitWorkerProcess
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
resource storage 'Microsoft.Storage/storageAccounts@2021-09-01' existing = {
|
77 |
+
name: storageAccountName
|
78 |
+
}
|
79 |
+
|
80 |
+
output identityPrincipalId string = managedIdentity ? functions.outputs.identityPrincipalId : ''
|
81 |
+
output name string = functions.outputs.name
|
82 |
+
output uri string = functions.outputs.uri
|
infra/core/host/staticwebapp.bicep
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param sku object = {
|
6 |
+
name: 'Free'
|
7 |
+
tier: 'Free'
|
8 |
+
}
|
9 |
+
|
10 |
+
resource web 'Microsoft.Web/staticSites@2022-03-01' = {
|
11 |
+
name: name
|
12 |
+
location: location
|
13 |
+
tags: tags
|
14 |
+
sku: sku
|
15 |
+
properties: {
|
16 |
+
provider: 'Custom'
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
output name string = web.name
|
21 |
+
output uri string = 'https://${web.properties.defaultHostname}'
|
infra/core/monitor/applicationinsights-dashboard.bicep
ADDED
@@ -0,0 +1,1235 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param applicationInsightsName string
|
3 |
+
param location string = resourceGroup().location
|
4 |
+
param tags object = {}
|
5 |
+
|
6 |
+
// 2020-09-01-preview because that is the latest valid version
|
7 |
+
resource applicationInsightsDashboard 'Microsoft.Portal/dashboards@2020-09-01-preview' = {
|
8 |
+
name: name
|
9 |
+
location: location
|
10 |
+
tags: tags
|
11 |
+
properties: {
|
12 |
+
lenses: [
|
13 |
+
{
|
14 |
+
order: 0
|
15 |
+
parts: [
|
16 |
+
{
|
17 |
+
position: {
|
18 |
+
x: 0
|
19 |
+
y: 0
|
20 |
+
colSpan: 2
|
21 |
+
rowSpan: 1
|
22 |
+
}
|
23 |
+
metadata: {
|
24 |
+
inputs: [
|
25 |
+
{
|
26 |
+
name: 'id'
|
27 |
+
value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
28 |
+
}
|
29 |
+
{
|
30 |
+
name: 'Version'
|
31 |
+
value: '1.0'
|
32 |
+
}
|
33 |
+
]
|
34 |
+
#disable-next-line BCP036
|
35 |
+
type: 'Extension/AppInsightsExtension/PartType/AspNetOverviewPinnedPart'
|
36 |
+
asset: {
|
37 |
+
idInputName: 'id'
|
38 |
+
type: 'ApplicationInsights'
|
39 |
+
}
|
40 |
+
defaultMenuItemId: 'overview'
|
41 |
+
}
|
42 |
+
}
|
43 |
+
{
|
44 |
+
position: {
|
45 |
+
x: 2
|
46 |
+
y: 0
|
47 |
+
colSpan: 1
|
48 |
+
rowSpan: 1
|
49 |
+
}
|
50 |
+
metadata: {
|
51 |
+
inputs: [
|
52 |
+
{
|
53 |
+
name: 'ComponentId'
|
54 |
+
value: {
|
55 |
+
Name: applicationInsights.name
|
56 |
+
SubscriptionId: subscription().subscriptionId
|
57 |
+
ResourceGroup: resourceGroup().name
|
58 |
+
}
|
59 |
+
}
|
60 |
+
{
|
61 |
+
name: 'Version'
|
62 |
+
value: '1.0'
|
63 |
+
}
|
64 |
+
]
|
65 |
+
#disable-next-line BCP036
|
66 |
+
type: 'Extension/AppInsightsExtension/PartType/ProactiveDetectionAsyncPart'
|
67 |
+
asset: {
|
68 |
+
idInputName: 'ComponentId'
|
69 |
+
type: 'ApplicationInsights'
|
70 |
+
}
|
71 |
+
defaultMenuItemId: 'ProactiveDetection'
|
72 |
+
}
|
73 |
+
}
|
74 |
+
{
|
75 |
+
position: {
|
76 |
+
x: 3
|
77 |
+
y: 0
|
78 |
+
colSpan: 1
|
79 |
+
rowSpan: 1
|
80 |
+
}
|
81 |
+
metadata: {
|
82 |
+
inputs: [
|
83 |
+
{
|
84 |
+
name: 'ComponentId'
|
85 |
+
value: {
|
86 |
+
Name: applicationInsights.name
|
87 |
+
SubscriptionId: subscription().subscriptionId
|
88 |
+
ResourceGroup: resourceGroup().name
|
89 |
+
}
|
90 |
+
}
|
91 |
+
{
|
92 |
+
name: 'ResourceId'
|
93 |
+
value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
94 |
+
}
|
95 |
+
]
|
96 |
+
#disable-next-line BCP036
|
97 |
+
type: 'Extension/AppInsightsExtension/PartType/QuickPulseButtonSmallPart'
|
98 |
+
asset: {
|
99 |
+
idInputName: 'ComponentId'
|
100 |
+
type: 'ApplicationInsights'
|
101 |
+
}
|
102 |
+
}
|
103 |
+
}
|
104 |
+
{
|
105 |
+
position: {
|
106 |
+
x: 4
|
107 |
+
y: 0
|
108 |
+
colSpan: 1
|
109 |
+
rowSpan: 1
|
110 |
+
}
|
111 |
+
metadata: {
|
112 |
+
inputs: [
|
113 |
+
{
|
114 |
+
name: 'ComponentId'
|
115 |
+
value: {
|
116 |
+
Name: applicationInsights.name
|
117 |
+
SubscriptionId: subscription().subscriptionId
|
118 |
+
ResourceGroup: resourceGroup().name
|
119 |
+
}
|
120 |
+
}
|
121 |
+
{
|
122 |
+
name: 'TimeContext'
|
123 |
+
value: {
|
124 |
+
durationMs: 86400000
|
125 |
+
endTime: null
|
126 |
+
createdTime: '2018-05-04T01:20:33.345Z'
|
127 |
+
isInitialTime: true
|
128 |
+
grain: 1
|
129 |
+
useDashboardTimeRange: false
|
130 |
+
}
|
131 |
+
}
|
132 |
+
{
|
133 |
+
name: 'Version'
|
134 |
+
value: '1.0'
|
135 |
+
}
|
136 |
+
]
|
137 |
+
#disable-next-line BCP036
|
138 |
+
type: 'Extension/AppInsightsExtension/PartType/AvailabilityNavButtonPart'
|
139 |
+
asset: {
|
140 |
+
idInputName: 'ComponentId'
|
141 |
+
type: 'ApplicationInsights'
|
142 |
+
}
|
143 |
+
}
|
144 |
+
}
|
145 |
+
{
|
146 |
+
position: {
|
147 |
+
x: 5
|
148 |
+
y: 0
|
149 |
+
colSpan: 1
|
150 |
+
rowSpan: 1
|
151 |
+
}
|
152 |
+
metadata: {
|
153 |
+
inputs: [
|
154 |
+
{
|
155 |
+
name: 'ComponentId'
|
156 |
+
value: {
|
157 |
+
Name: applicationInsights.name
|
158 |
+
SubscriptionId: subscription().subscriptionId
|
159 |
+
ResourceGroup: resourceGroup().name
|
160 |
+
}
|
161 |
+
}
|
162 |
+
{
|
163 |
+
name: 'TimeContext'
|
164 |
+
value: {
|
165 |
+
durationMs: 86400000
|
166 |
+
endTime: null
|
167 |
+
createdTime: '2018-05-08T18:47:35.237Z'
|
168 |
+
isInitialTime: true
|
169 |
+
grain: 1
|
170 |
+
useDashboardTimeRange: false
|
171 |
+
}
|
172 |
+
}
|
173 |
+
{
|
174 |
+
name: 'ConfigurationId'
|
175 |
+
value: '78ce933e-e864-4b05-a27b-71fd55a6afad'
|
176 |
+
}
|
177 |
+
]
|
178 |
+
#disable-next-line BCP036
|
179 |
+
type: 'Extension/AppInsightsExtension/PartType/AppMapButtonPart'
|
180 |
+
asset: {
|
181 |
+
idInputName: 'ComponentId'
|
182 |
+
type: 'ApplicationInsights'
|
183 |
+
}
|
184 |
+
}
|
185 |
+
}
|
186 |
+
{
|
187 |
+
position: {
|
188 |
+
x: 0
|
189 |
+
y: 1
|
190 |
+
colSpan: 3
|
191 |
+
rowSpan: 1
|
192 |
+
}
|
193 |
+
metadata: {
|
194 |
+
inputs: []
|
195 |
+
type: 'Extension/HubsExtension/PartType/MarkdownPart'
|
196 |
+
settings: {
|
197 |
+
content: {
|
198 |
+
settings: {
|
199 |
+
content: '# Usage'
|
200 |
+
title: ''
|
201 |
+
subtitle: ''
|
202 |
+
}
|
203 |
+
}
|
204 |
+
}
|
205 |
+
}
|
206 |
+
}
|
207 |
+
{
|
208 |
+
position: {
|
209 |
+
x: 3
|
210 |
+
y: 1
|
211 |
+
colSpan: 1
|
212 |
+
rowSpan: 1
|
213 |
+
}
|
214 |
+
metadata: {
|
215 |
+
inputs: [
|
216 |
+
{
|
217 |
+
name: 'ComponentId'
|
218 |
+
value: {
|
219 |
+
Name: applicationInsights.name
|
220 |
+
SubscriptionId: subscription().subscriptionId
|
221 |
+
ResourceGroup: resourceGroup().name
|
222 |
+
}
|
223 |
+
}
|
224 |
+
{
|
225 |
+
name: 'TimeContext'
|
226 |
+
value: {
|
227 |
+
durationMs: 86400000
|
228 |
+
endTime: null
|
229 |
+
createdTime: '2018-05-04T01:22:35.782Z'
|
230 |
+
isInitialTime: true
|
231 |
+
grain: 1
|
232 |
+
useDashboardTimeRange: false
|
233 |
+
}
|
234 |
+
}
|
235 |
+
]
|
236 |
+
#disable-next-line BCP036
|
237 |
+
type: 'Extension/AppInsightsExtension/PartType/UsageUsersOverviewPart'
|
238 |
+
asset: {
|
239 |
+
idInputName: 'ComponentId'
|
240 |
+
type: 'ApplicationInsights'
|
241 |
+
}
|
242 |
+
}
|
243 |
+
}
|
244 |
+
{
|
245 |
+
position: {
|
246 |
+
x: 4
|
247 |
+
y: 1
|
248 |
+
colSpan: 3
|
249 |
+
rowSpan: 1
|
250 |
+
}
|
251 |
+
metadata: {
|
252 |
+
inputs: []
|
253 |
+
type: 'Extension/HubsExtension/PartType/MarkdownPart'
|
254 |
+
settings: {
|
255 |
+
content: {
|
256 |
+
settings: {
|
257 |
+
content: '# Reliability'
|
258 |
+
title: ''
|
259 |
+
subtitle: ''
|
260 |
+
}
|
261 |
+
}
|
262 |
+
}
|
263 |
+
}
|
264 |
+
}
|
265 |
+
{
|
266 |
+
position: {
|
267 |
+
x: 7
|
268 |
+
y: 1
|
269 |
+
colSpan: 1
|
270 |
+
rowSpan: 1
|
271 |
+
}
|
272 |
+
metadata: {
|
273 |
+
inputs: [
|
274 |
+
{
|
275 |
+
name: 'ResourceId'
|
276 |
+
value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
277 |
+
}
|
278 |
+
{
|
279 |
+
name: 'DataModel'
|
280 |
+
value: {
|
281 |
+
version: '1.0.0'
|
282 |
+
timeContext: {
|
283 |
+
durationMs: 86400000
|
284 |
+
createdTime: '2018-05-04T23:42:40.072Z'
|
285 |
+
isInitialTime: false
|
286 |
+
grain: 1
|
287 |
+
useDashboardTimeRange: false
|
288 |
+
}
|
289 |
+
}
|
290 |
+
isOptional: true
|
291 |
+
}
|
292 |
+
{
|
293 |
+
name: 'ConfigurationId'
|
294 |
+
value: '8a02f7bf-ac0f-40e1-afe9-f0e72cfee77f'
|
295 |
+
isOptional: true
|
296 |
+
}
|
297 |
+
]
|
298 |
+
#disable-next-line BCP036
|
299 |
+
type: 'Extension/AppInsightsExtension/PartType/CuratedBladeFailuresPinnedPart'
|
300 |
+
isAdapter: true
|
301 |
+
asset: {
|
302 |
+
idInputName: 'ResourceId'
|
303 |
+
type: 'ApplicationInsights'
|
304 |
+
}
|
305 |
+
defaultMenuItemId: 'failures'
|
306 |
+
}
|
307 |
+
}
|
308 |
+
{
|
309 |
+
position: {
|
310 |
+
x: 8
|
311 |
+
y: 1
|
312 |
+
colSpan: 3
|
313 |
+
rowSpan: 1
|
314 |
+
}
|
315 |
+
metadata: {
|
316 |
+
inputs: []
|
317 |
+
type: 'Extension/HubsExtension/PartType/MarkdownPart'
|
318 |
+
settings: {
|
319 |
+
content: {
|
320 |
+
settings: {
|
321 |
+
content: '# Responsiveness\r\n'
|
322 |
+
title: ''
|
323 |
+
subtitle: ''
|
324 |
+
}
|
325 |
+
}
|
326 |
+
}
|
327 |
+
}
|
328 |
+
}
|
329 |
+
{
|
330 |
+
position: {
|
331 |
+
x: 11
|
332 |
+
y: 1
|
333 |
+
colSpan: 1
|
334 |
+
rowSpan: 1
|
335 |
+
}
|
336 |
+
metadata: {
|
337 |
+
inputs: [
|
338 |
+
{
|
339 |
+
name: 'ResourceId'
|
340 |
+
value: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
341 |
+
}
|
342 |
+
{
|
343 |
+
name: 'DataModel'
|
344 |
+
value: {
|
345 |
+
version: '1.0.0'
|
346 |
+
timeContext: {
|
347 |
+
durationMs: 86400000
|
348 |
+
createdTime: '2018-05-04T23:43:37.804Z'
|
349 |
+
isInitialTime: false
|
350 |
+
grain: 1
|
351 |
+
useDashboardTimeRange: false
|
352 |
+
}
|
353 |
+
}
|
354 |
+
isOptional: true
|
355 |
+
}
|
356 |
+
{
|
357 |
+
name: 'ConfigurationId'
|
358 |
+
value: '2a8ede4f-2bee-4b9c-aed9-2db0e8a01865'
|
359 |
+
isOptional: true
|
360 |
+
}
|
361 |
+
]
|
362 |
+
#disable-next-line BCP036
|
363 |
+
type: 'Extension/AppInsightsExtension/PartType/CuratedBladePerformancePinnedPart'
|
364 |
+
isAdapter: true
|
365 |
+
asset: {
|
366 |
+
idInputName: 'ResourceId'
|
367 |
+
type: 'ApplicationInsights'
|
368 |
+
}
|
369 |
+
defaultMenuItemId: 'performance'
|
370 |
+
}
|
371 |
+
}
|
372 |
+
{
|
373 |
+
position: {
|
374 |
+
x: 12
|
375 |
+
y: 1
|
376 |
+
colSpan: 3
|
377 |
+
rowSpan: 1
|
378 |
+
}
|
379 |
+
metadata: {
|
380 |
+
inputs: []
|
381 |
+
type: 'Extension/HubsExtension/PartType/MarkdownPart'
|
382 |
+
settings: {
|
383 |
+
content: {
|
384 |
+
settings: {
|
385 |
+
content: '# Browser'
|
386 |
+
title: ''
|
387 |
+
subtitle: ''
|
388 |
+
}
|
389 |
+
}
|
390 |
+
}
|
391 |
+
}
|
392 |
+
}
|
393 |
+
{
|
394 |
+
position: {
|
395 |
+
x: 15
|
396 |
+
y: 1
|
397 |
+
colSpan: 1
|
398 |
+
rowSpan: 1
|
399 |
+
}
|
400 |
+
metadata: {
|
401 |
+
inputs: [
|
402 |
+
{
|
403 |
+
name: 'ComponentId'
|
404 |
+
value: {
|
405 |
+
Name: applicationInsights.name
|
406 |
+
SubscriptionId: subscription().subscriptionId
|
407 |
+
ResourceGroup: resourceGroup().name
|
408 |
+
}
|
409 |
+
}
|
410 |
+
{
|
411 |
+
name: 'MetricsExplorerJsonDefinitionId'
|
412 |
+
value: 'BrowserPerformanceTimelineMetrics'
|
413 |
+
}
|
414 |
+
{
|
415 |
+
name: 'TimeContext'
|
416 |
+
value: {
|
417 |
+
durationMs: 86400000
|
418 |
+
createdTime: '2018-05-08T12:16:27.534Z'
|
419 |
+
isInitialTime: false
|
420 |
+
grain: 1
|
421 |
+
useDashboardTimeRange: false
|
422 |
+
}
|
423 |
+
}
|
424 |
+
{
|
425 |
+
name: 'CurrentFilter'
|
426 |
+
value: {
|
427 |
+
eventTypes: [
|
428 |
+
4
|
429 |
+
1
|
430 |
+
3
|
431 |
+
5
|
432 |
+
2
|
433 |
+
6
|
434 |
+
13
|
435 |
+
]
|
436 |
+
typeFacets: {}
|
437 |
+
isPermissive: false
|
438 |
+
}
|
439 |
+
}
|
440 |
+
{
|
441 |
+
name: 'id'
|
442 |
+
value: {
|
443 |
+
Name: applicationInsights.name
|
444 |
+
SubscriptionId: subscription().subscriptionId
|
445 |
+
ResourceGroup: resourceGroup().name
|
446 |
+
}
|
447 |
+
}
|
448 |
+
{
|
449 |
+
name: 'Version'
|
450 |
+
value: '1.0'
|
451 |
+
}
|
452 |
+
]
|
453 |
+
#disable-next-line BCP036
|
454 |
+
type: 'Extension/AppInsightsExtension/PartType/MetricsExplorerBladePinnedPart'
|
455 |
+
asset: {
|
456 |
+
idInputName: 'ComponentId'
|
457 |
+
type: 'ApplicationInsights'
|
458 |
+
}
|
459 |
+
defaultMenuItemId: 'browser'
|
460 |
+
}
|
461 |
+
}
|
462 |
+
{
|
463 |
+
position: {
|
464 |
+
x: 0
|
465 |
+
y: 2
|
466 |
+
colSpan: 4
|
467 |
+
rowSpan: 3
|
468 |
+
}
|
469 |
+
metadata: {
|
470 |
+
inputs: [
|
471 |
+
{
|
472 |
+
name: 'options'
|
473 |
+
value: {
|
474 |
+
chart: {
|
475 |
+
metrics: [
|
476 |
+
{
|
477 |
+
resourceMetadata: {
|
478 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
479 |
+
}
|
480 |
+
name: 'sessions/count'
|
481 |
+
aggregationType: 5
|
482 |
+
namespace: 'microsoft.insights/components/kusto'
|
483 |
+
metricVisualization: {
|
484 |
+
displayName: 'Sessions'
|
485 |
+
color: '#47BDF5'
|
486 |
+
}
|
487 |
+
}
|
488 |
+
{
|
489 |
+
resourceMetadata: {
|
490 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
491 |
+
}
|
492 |
+
name: 'users/count'
|
493 |
+
aggregationType: 5
|
494 |
+
namespace: 'microsoft.insights/components/kusto'
|
495 |
+
metricVisualization: {
|
496 |
+
displayName: 'Users'
|
497 |
+
color: '#7E58FF'
|
498 |
+
}
|
499 |
+
}
|
500 |
+
]
|
501 |
+
title: 'Unique sessions and users'
|
502 |
+
visualization: {
|
503 |
+
chartType: 2
|
504 |
+
legendVisualization: {
|
505 |
+
isVisible: true
|
506 |
+
position: 2
|
507 |
+
hideSubtitle: false
|
508 |
+
}
|
509 |
+
axisVisualization: {
|
510 |
+
x: {
|
511 |
+
isVisible: true
|
512 |
+
axisType: 2
|
513 |
+
}
|
514 |
+
y: {
|
515 |
+
isVisible: true
|
516 |
+
axisType: 1
|
517 |
+
}
|
518 |
+
}
|
519 |
+
}
|
520 |
+
openBladeOnClick: {
|
521 |
+
openBlade: true
|
522 |
+
destinationBlade: {
|
523 |
+
extensionName: 'HubsExtension'
|
524 |
+
bladeName: 'ResourceMenuBlade'
|
525 |
+
parameters: {
|
526 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
527 |
+
menuid: 'segmentationUsers'
|
528 |
+
}
|
529 |
+
}
|
530 |
+
}
|
531 |
+
}
|
532 |
+
}
|
533 |
+
}
|
534 |
+
{
|
535 |
+
name: 'sharedTimeRange'
|
536 |
+
isOptional: true
|
537 |
+
}
|
538 |
+
]
|
539 |
+
#disable-next-line BCP036
|
540 |
+
type: 'Extension/HubsExtension/PartType/MonitorChartPart'
|
541 |
+
settings: {}
|
542 |
+
}
|
543 |
+
}
|
544 |
+
{
|
545 |
+
position: {
|
546 |
+
x: 4
|
547 |
+
y: 2
|
548 |
+
colSpan: 4
|
549 |
+
rowSpan: 3
|
550 |
+
}
|
551 |
+
metadata: {
|
552 |
+
inputs: [
|
553 |
+
{
|
554 |
+
name: 'options'
|
555 |
+
value: {
|
556 |
+
chart: {
|
557 |
+
metrics: [
|
558 |
+
{
|
559 |
+
resourceMetadata: {
|
560 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
561 |
+
}
|
562 |
+
name: 'requests/failed'
|
563 |
+
aggregationType: 7
|
564 |
+
namespace: 'microsoft.insights/components'
|
565 |
+
metricVisualization: {
|
566 |
+
displayName: 'Failed requests'
|
567 |
+
color: '#EC008C'
|
568 |
+
}
|
569 |
+
}
|
570 |
+
]
|
571 |
+
title: 'Failed requests'
|
572 |
+
visualization: {
|
573 |
+
chartType: 3
|
574 |
+
legendVisualization: {
|
575 |
+
isVisible: true
|
576 |
+
position: 2
|
577 |
+
hideSubtitle: false
|
578 |
+
}
|
579 |
+
axisVisualization: {
|
580 |
+
x: {
|
581 |
+
isVisible: true
|
582 |
+
axisType: 2
|
583 |
+
}
|
584 |
+
y: {
|
585 |
+
isVisible: true
|
586 |
+
axisType: 1
|
587 |
+
}
|
588 |
+
}
|
589 |
+
}
|
590 |
+
openBladeOnClick: {
|
591 |
+
openBlade: true
|
592 |
+
destinationBlade: {
|
593 |
+
extensionName: 'HubsExtension'
|
594 |
+
bladeName: 'ResourceMenuBlade'
|
595 |
+
parameters: {
|
596 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
597 |
+
menuid: 'failures'
|
598 |
+
}
|
599 |
+
}
|
600 |
+
}
|
601 |
+
}
|
602 |
+
}
|
603 |
+
}
|
604 |
+
{
|
605 |
+
name: 'sharedTimeRange'
|
606 |
+
isOptional: true
|
607 |
+
}
|
608 |
+
]
|
609 |
+
#disable-next-line BCP036
|
610 |
+
type: 'Extension/HubsExtension/PartType/MonitorChartPart'
|
611 |
+
settings: {}
|
612 |
+
}
|
613 |
+
}
|
614 |
+
{
|
615 |
+
position: {
|
616 |
+
x: 8
|
617 |
+
y: 2
|
618 |
+
colSpan: 4
|
619 |
+
rowSpan: 3
|
620 |
+
}
|
621 |
+
metadata: {
|
622 |
+
inputs: [
|
623 |
+
{
|
624 |
+
name: 'options'
|
625 |
+
value: {
|
626 |
+
chart: {
|
627 |
+
metrics: [
|
628 |
+
{
|
629 |
+
resourceMetadata: {
|
630 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
631 |
+
}
|
632 |
+
name: 'requests/duration'
|
633 |
+
aggregationType: 4
|
634 |
+
namespace: 'microsoft.insights/components'
|
635 |
+
metricVisualization: {
|
636 |
+
displayName: 'Server response time'
|
637 |
+
color: '#00BCF2'
|
638 |
+
}
|
639 |
+
}
|
640 |
+
]
|
641 |
+
title: 'Server response time'
|
642 |
+
visualization: {
|
643 |
+
chartType: 2
|
644 |
+
legendVisualization: {
|
645 |
+
isVisible: true
|
646 |
+
position: 2
|
647 |
+
hideSubtitle: false
|
648 |
+
}
|
649 |
+
axisVisualization: {
|
650 |
+
x: {
|
651 |
+
isVisible: true
|
652 |
+
axisType: 2
|
653 |
+
}
|
654 |
+
y: {
|
655 |
+
isVisible: true
|
656 |
+
axisType: 1
|
657 |
+
}
|
658 |
+
}
|
659 |
+
}
|
660 |
+
openBladeOnClick: {
|
661 |
+
openBlade: true
|
662 |
+
destinationBlade: {
|
663 |
+
extensionName: 'HubsExtension'
|
664 |
+
bladeName: 'ResourceMenuBlade'
|
665 |
+
parameters: {
|
666 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
667 |
+
menuid: 'performance'
|
668 |
+
}
|
669 |
+
}
|
670 |
+
}
|
671 |
+
}
|
672 |
+
}
|
673 |
+
}
|
674 |
+
{
|
675 |
+
name: 'sharedTimeRange'
|
676 |
+
isOptional: true
|
677 |
+
}
|
678 |
+
]
|
679 |
+
#disable-next-line BCP036
|
680 |
+
type: 'Extension/HubsExtension/PartType/MonitorChartPart'
|
681 |
+
settings: {}
|
682 |
+
}
|
683 |
+
}
|
684 |
+
{
|
685 |
+
position: {
|
686 |
+
x: 12
|
687 |
+
y: 2
|
688 |
+
colSpan: 4
|
689 |
+
rowSpan: 3
|
690 |
+
}
|
691 |
+
metadata: {
|
692 |
+
inputs: [
|
693 |
+
{
|
694 |
+
name: 'options'
|
695 |
+
value: {
|
696 |
+
chart: {
|
697 |
+
metrics: [
|
698 |
+
{
|
699 |
+
resourceMetadata: {
|
700 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
701 |
+
}
|
702 |
+
name: 'browserTimings/networkDuration'
|
703 |
+
aggregationType: 4
|
704 |
+
namespace: 'microsoft.insights/components'
|
705 |
+
metricVisualization: {
|
706 |
+
displayName: 'Page load network connect time'
|
707 |
+
color: '#7E58FF'
|
708 |
+
}
|
709 |
+
}
|
710 |
+
{
|
711 |
+
resourceMetadata: {
|
712 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
713 |
+
}
|
714 |
+
name: 'browserTimings/processingDuration'
|
715 |
+
aggregationType: 4
|
716 |
+
namespace: 'microsoft.insights/components'
|
717 |
+
metricVisualization: {
|
718 |
+
displayName: 'Client processing time'
|
719 |
+
color: '#44F1C8'
|
720 |
+
}
|
721 |
+
}
|
722 |
+
{
|
723 |
+
resourceMetadata: {
|
724 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
725 |
+
}
|
726 |
+
name: 'browserTimings/sendDuration'
|
727 |
+
aggregationType: 4
|
728 |
+
namespace: 'microsoft.insights/components'
|
729 |
+
metricVisualization: {
|
730 |
+
displayName: 'Send request time'
|
731 |
+
color: '#EB9371'
|
732 |
+
}
|
733 |
+
}
|
734 |
+
{
|
735 |
+
resourceMetadata: {
|
736 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
737 |
+
}
|
738 |
+
name: 'browserTimings/receiveDuration'
|
739 |
+
aggregationType: 4
|
740 |
+
namespace: 'microsoft.insights/components'
|
741 |
+
metricVisualization: {
|
742 |
+
displayName: 'Receiving response time'
|
743 |
+
color: '#0672F1'
|
744 |
+
}
|
745 |
+
}
|
746 |
+
]
|
747 |
+
title: 'Average page load time breakdown'
|
748 |
+
visualization: {
|
749 |
+
chartType: 3
|
750 |
+
legendVisualization: {
|
751 |
+
isVisible: true
|
752 |
+
position: 2
|
753 |
+
hideSubtitle: false
|
754 |
+
}
|
755 |
+
axisVisualization: {
|
756 |
+
x: {
|
757 |
+
isVisible: true
|
758 |
+
axisType: 2
|
759 |
+
}
|
760 |
+
y: {
|
761 |
+
isVisible: true
|
762 |
+
axisType: 1
|
763 |
+
}
|
764 |
+
}
|
765 |
+
}
|
766 |
+
}
|
767 |
+
}
|
768 |
+
}
|
769 |
+
{
|
770 |
+
name: 'sharedTimeRange'
|
771 |
+
isOptional: true
|
772 |
+
}
|
773 |
+
]
|
774 |
+
#disable-next-line BCP036
|
775 |
+
type: 'Extension/HubsExtension/PartType/MonitorChartPart'
|
776 |
+
settings: {}
|
777 |
+
}
|
778 |
+
}
|
779 |
+
{
|
780 |
+
position: {
|
781 |
+
x: 0
|
782 |
+
y: 5
|
783 |
+
colSpan: 4
|
784 |
+
rowSpan: 3
|
785 |
+
}
|
786 |
+
metadata: {
|
787 |
+
inputs: [
|
788 |
+
{
|
789 |
+
name: 'options'
|
790 |
+
value: {
|
791 |
+
chart: {
|
792 |
+
metrics: [
|
793 |
+
{
|
794 |
+
resourceMetadata: {
|
795 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
796 |
+
}
|
797 |
+
name: 'availabilityResults/availabilityPercentage'
|
798 |
+
aggregationType: 4
|
799 |
+
namespace: 'microsoft.insights/components'
|
800 |
+
metricVisualization: {
|
801 |
+
displayName: 'Availability'
|
802 |
+
color: '#47BDF5'
|
803 |
+
}
|
804 |
+
}
|
805 |
+
]
|
806 |
+
title: 'Average availability'
|
807 |
+
visualization: {
|
808 |
+
chartType: 3
|
809 |
+
legendVisualization: {
|
810 |
+
isVisible: true
|
811 |
+
position: 2
|
812 |
+
hideSubtitle: false
|
813 |
+
}
|
814 |
+
axisVisualization: {
|
815 |
+
x: {
|
816 |
+
isVisible: true
|
817 |
+
axisType: 2
|
818 |
+
}
|
819 |
+
y: {
|
820 |
+
isVisible: true
|
821 |
+
axisType: 1
|
822 |
+
}
|
823 |
+
}
|
824 |
+
}
|
825 |
+
openBladeOnClick: {
|
826 |
+
openBlade: true
|
827 |
+
destinationBlade: {
|
828 |
+
extensionName: 'HubsExtension'
|
829 |
+
bladeName: 'ResourceMenuBlade'
|
830 |
+
parameters: {
|
831 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
832 |
+
menuid: 'availability'
|
833 |
+
}
|
834 |
+
}
|
835 |
+
}
|
836 |
+
}
|
837 |
+
}
|
838 |
+
}
|
839 |
+
{
|
840 |
+
name: 'sharedTimeRange'
|
841 |
+
isOptional: true
|
842 |
+
}
|
843 |
+
]
|
844 |
+
#disable-next-line BCP036
|
845 |
+
type: 'Extension/HubsExtension/PartType/MonitorChartPart'
|
846 |
+
settings: {}
|
847 |
+
}
|
848 |
+
}
|
849 |
+
{
|
850 |
+
position: {
|
851 |
+
x: 4
|
852 |
+
y: 5
|
853 |
+
colSpan: 4
|
854 |
+
rowSpan: 3
|
855 |
+
}
|
856 |
+
metadata: {
|
857 |
+
inputs: [
|
858 |
+
{
|
859 |
+
name: 'options'
|
860 |
+
value: {
|
861 |
+
chart: {
|
862 |
+
metrics: [
|
863 |
+
{
|
864 |
+
resourceMetadata: {
|
865 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
866 |
+
}
|
867 |
+
name: 'exceptions/server'
|
868 |
+
aggregationType: 7
|
869 |
+
namespace: 'microsoft.insights/components'
|
870 |
+
metricVisualization: {
|
871 |
+
displayName: 'Server exceptions'
|
872 |
+
color: '#47BDF5'
|
873 |
+
}
|
874 |
+
}
|
875 |
+
{
|
876 |
+
resourceMetadata: {
|
877 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
878 |
+
}
|
879 |
+
name: 'dependencies/failed'
|
880 |
+
aggregationType: 7
|
881 |
+
namespace: 'microsoft.insights/components'
|
882 |
+
metricVisualization: {
|
883 |
+
displayName: 'Dependency failures'
|
884 |
+
color: '#7E58FF'
|
885 |
+
}
|
886 |
+
}
|
887 |
+
]
|
888 |
+
title: 'Server exceptions and Dependency failures'
|
889 |
+
visualization: {
|
890 |
+
chartType: 2
|
891 |
+
legendVisualization: {
|
892 |
+
isVisible: true
|
893 |
+
position: 2
|
894 |
+
hideSubtitle: false
|
895 |
+
}
|
896 |
+
axisVisualization: {
|
897 |
+
x: {
|
898 |
+
isVisible: true
|
899 |
+
axisType: 2
|
900 |
+
}
|
901 |
+
y: {
|
902 |
+
isVisible: true
|
903 |
+
axisType: 1
|
904 |
+
}
|
905 |
+
}
|
906 |
+
}
|
907 |
+
}
|
908 |
+
}
|
909 |
+
}
|
910 |
+
{
|
911 |
+
name: 'sharedTimeRange'
|
912 |
+
isOptional: true
|
913 |
+
}
|
914 |
+
]
|
915 |
+
#disable-next-line BCP036
|
916 |
+
type: 'Extension/HubsExtension/PartType/MonitorChartPart'
|
917 |
+
settings: {}
|
918 |
+
}
|
919 |
+
}
|
920 |
+
{
|
921 |
+
position: {
|
922 |
+
x: 8
|
923 |
+
y: 5
|
924 |
+
colSpan: 4
|
925 |
+
rowSpan: 3
|
926 |
+
}
|
927 |
+
metadata: {
|
928 |
+
inputs: [
|
929 |
+
{
|
930 |
+
name: 'options'
|
931 |
+
value: {
|
932 |
+
chart: {
|
933 |
+
metrics: [
|
934 |
+
{
|
935 |
+
resourceMetadata: {
|
936 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
937 |
+
}
|
938 |
+
name: 'performanceCounters/processorCpuPercentage'
|
939 |
+
aggregationType: 4
|
940 |
+
namespace: 'microsoft.insights/components'
|
941 |
+
metricVisualization: {
|
942 |
+
displayName: 'Processor time'
|
943 |
+
color: '#47BDF5'
|
944 |
+
}
|
945 |
+
}
|
946 |
+
{
|
947 |
+
resourceMetadata: {
|
948 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
949 |
+
}
|
950 |
+
name: 'performanceCounters/processCpuPercentage'
|
951 |
+
aggregationType: 4
|
952 |
+
namespace: 'microsoft.insights/components'
|
953 |
+
metricVisualization: {
|
954 |
+
displayName: 'Process CPU'
|
955 |
+
color: '#7E58FF'
|
956 |
+
}
|
957 |
+
}
|
958 |
+
]
|
959 |
+
title: 'Average processor and process CPU utilization'
|
960 |
+
visualization: {
|
961 |
+
chartType: 2
|
962 |
+
legendVisualization: {
|
963 |
+
isVisible: true
|
964 |
+
position: 2
|
965 |
+
hideSubtitle: false
|
966 |
+
}
|
967 |
+
axisVisualization: {
|
968 |
+
x: {
|
969 |
+
isVisible: true
|
970 |
+
axisType: 2
|
971 |
+
}
|
972 |
+
y: {
|
973 |
+
isVisible: true
|
974 |
+
axisType: 1
|
975 |
+
}
|
976 |
+
}
|
977 |
+
}
|
978 |
+
}
|
979 |
+
}
|
980 |
+
}
|
981 |
+
{
|
982 |
+
name: 'sharedTimeRange'
|
983 |
+
isOptional: true
|
984 |
+
}
|
985 |
+
]
|
986 |
+
#disable-next-line BCP036
|
987 |
+
type: 'Extension/HubsExtension/PartType/MonitorChartPart'
|
988 |
+
settings: {}
|
989 |
+
}
|
990 |
+
}
|
991 |
+
{
|
992 |
+
position: {
|
993 |
+
x: 12
|
994 |
+
y: 5
|
995 |
+
colSpan: 4
|
996 |
+
rowSpan: 3
|
997 |
+
}
|
998 |
+
metadata: {
|
999 |
+
inputs: [
|
1000 |
+
{
|
1001 |
+
name: 'options'
|
1002 |
+
value: {
|
1003 |
+
chart: {
|
1004 |
+
metrics: [
|
1005 |
+
{
|
1006 |
+
resourceMetadata: {
|
1007 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
1008 |
+
}
|
1009 |
+
name: 'exceptions/browser'
|
1010 |
+
aggregationType: 7
|
1011 |
+
namespace: 'microsoft.insights/components'
|
1012 |
+
metricVisualization: {
|
1013 |
+
displayName: 'Browser exceptions'
|
1014 |
+
color: '#47BDF5'
|
1015 |
+
}
|
1016 |
+
}
|
1017 |
+
]
|
1018 |
+
title: 'Browser exceptions'
|
1019 |
+
visualization: {
|
1020 |
+
chartType: 2
|
1021 |
+
legendVisualization: {
|
1022 |
+
isVisible: true
|
1023 |
+
position: 2
|
1024 |
+
hideSubtitle: false
|
1025 |
+
}
|
1026 |
+
axisVisualization: {
|
1027 |
+
x: {
|
1028 |
+
isVisible: true
|
1029 |
+
axisType: 2
|
1030 |
+
}
|
1031 |
+
y: {
|
1032 |
+
isVisible: true
|
1033 |
+
axisType: 1
|
1034 |
+
}
|
1035 |
+
}
|
1036 |
+
}
|
1037 |
+
}
|
1038 |
+
}
|
1039 |
+
}
|
1040 |
+
{
|
1041 |
+
name: 'sharedTimeRange'
|
1042 |
+
isOptional: true
|
1043 |
+
}
|
1044 |
+
]
|
1045 |
+
#disable-next-line BCP036
|
1046 |
+
type: 'Extension/HubsExtension/PartType/MonitorChartPart'
|
1047 |
+
settings: {}
|
1048 |
+
}
|
1049 |
+
}
|
1050 |
+
{
|
1051 |
+
position: {
|
1052 |
+
x: 0
|
1053 |
+
y: 8
|
1054 |
+
colSpan: 4
|
1055 |
+
rowSpan: 3
|
1056 |
+
}
|
1057 |
+
metadata: {
|
1058 |
+
inputs: [
|
1059 |
+
{
|
1060 |
+
name: 'options'
|
1061 |
+
value: {
|
1062 |
+
chart: {
|
1063 |
+
metrics: [
|
1064 |
+
{
|
1065 |
+
resourceMetadata: {
|
1066 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
1067 |
+
}
|
1068 |
+
name: 'availabilityResults/count'
|
1069 |
+
aggregationType: 7
|
1070 |
+
namespace: 'microsoft.insights/components'
|
1071 |
+
metricVisualization: {
|
1072 |
+
displayName: 'Availability test results count'
|
1073 |
+
color: '#47BDF5'
|
1074 |
+
}
|
1075 |
+
}
|
1076 |
+
]
|
1077 |
+
title: 'Availability test results count'
|
1078 |
+
visualization: {
|
1079 |
+
chartType: 2
|
1080 |
+
legendVisualization: {
|
1081 |
+
isVisible: true
|
1082 |
+
position: 2
|
1083 |
+
hideSubtitle: false
|
1084 |
+
}
|
1085 |
+
axisVisualization: {
|
1086 |
+
x: {
|
1087 |
+
isVisible: true
|
1088 |
+
axisType: 2
|
1089 |
+
}
|
1090 |
+
y: {
|
1091 |
+
isVisible: true
|
1092 |
+
axisType: 1
|
1093 |
+
}
|
1094 |
+
}
|
1095 |
+
}
|
1096 |
+
}
|
1097 |
+
}
|
1098 |
+
}
|
1099 |
+
{
|
1100 |
+
name: 'sharedTimeRange'
|
1101 |
+
isOptional: true
|
1102 |
+
}
|
1103 |
+
]
|
1104 |
+
#disable-next-line BCP036
|
1105 |
+
type: 'Extension/HubsExtension/PartType/MonitorChartPart'
|
1106 |
+
settings: {}
|
1107 |
+
}
|
1108 |
+
}
|
1109 |
+
{
|
1110 |
+
position: {
|
1111 |
+
x: 4
|
1112 |
+
y: 8
|
1113 |
+
colSpan: 4
|
1114 |
+
rowSpan: 3
|
1115 |
+
}
|
1116 |
+
metadata: {
|
1117 |
+
inputs: [
|
1118 |
+
{
|
1119 |
+
name: 'options'
|
1120 |
+
value: {
|
1121 |
+
chart: {
|
1122 |
+
metrics: [
|
1123 |
+
{
|
1124 |
+
resourceMetadata: {
|
1125 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
1126 |
+
}
|
1127 |
+
name: 'performanceCounters/processIOBytesPerSecond'
|
1128 |
+
aggregationType: 4
|
1129 |
+
namespace: 'microsoft.insights/components'
|
1130 |
+
metricVisualization: {
|
1131 |
+
displayName: 'Process IO rate'
|
1132 |
+
color: '#47BDF5'
|
1133 |
+
}
|
1134 |
+
}
|
1135 |
+
]
|
1136 |
+
title: 'Average process I/O rate'
|
1137 |
+
visualization: {
|
1138 |
+
chartType: 2
|
1139 |
+
legendVisualization: {
|
1140 |
+
isVisible: true
|
1141 |
+
position: 2
|
1142 |
+
hideSubtitle: false
|
1143 |
+
}
|
1144 |
+
axisVisualization: {
|
1145 |
+
x: {
|
1146 |
+
isVisible: true
|
1147 |
+
axisType: 2
|
1148 |
+
}
|
1149 |
+
y: {
|
1150 |
+
isVisible: true
|
1151 |
+
axisType: 1
|
1152 |
+
}
|
1153 |
+
}
|
1154 |
+
}
|
1155 |
+
}
|
1156 |
+
}
|
1157 |
+
}
|
1158 |
+
{
|
1159 |
+
name: 'sharedTimeRange'
|
1160 |
+
isOptional: true
|
1161 |
+
}
|
1162 |
+
]
|
1163 |
+
#disable-next-line BCP036
|
1164 |
+
type: 'Extension/HubsExtension/PartType/MonitorChartPart'
|
1165 |
+
settings: {}
|
1166 |
+
}
|
1167 |
+
}
|
1168 |
+
{
|
1169 |
+
position: {
|
1170 |
+
x: 8
|
1171 |
+
y: 8
|
1172 |
+
colSpan: 4
|
1173 |
+
rowSpan: 3
|
1174 |
+
}
|
1175 |
+
metadata: {
|
1176 |
+
inputs: [
|
1177 |
+
{
|
1178 |
+
name: 'options'
|
1179 |
+
value: {
|
1180 |
+
chart: {
|
1181 |
+
metrics: [
|
1182 |
+
{
|
1183 |
+
resourceMetadata: {
|
1184 |
+
id: '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${applicationInsights.name}'
|
1185 |
+
}
|
1186 |
+
name: 'performanceCounters/memoryAvailableBytes'
|
1187 |
+
aggregationType: 4
|
1188 |
+
namespace: 'microsoft.insights/components'
|
1189 |
+
metricVisualization: {
|
1190 |
+
displayName: 'Available memory'
|
1191 |
+
color: '#47BDF5'
|
1192 |
+
}
|
1193 |
+
}
|
1194 |
+
]
|
1195 |
+
title: 'Average available memory'
|
1196 |
+
visualization: {
|
1197 |
+
chartType: 2
|
1198 |
+
legendVisualization: {
|
1199 |
+
isVisible: true
|
1200 |
+
position: 2
|
1201 |
+
hideSubtitle: false
|
1202 |
+
}
|
1203 |
+
axisVisualization: {
|
1204 |
+
x: {
|
1205 |
+
isVisible: true
|
1206 |
+
axisType: 2
|
1207 |
+
}
|
1208 |
+
y: {
|
1209 |
+
isVisible: true
|
1210 |
+
axisType: 1
|
1211 |
+
}
|
1212 |
+
}
|
1213 |
+
}
|
1214 |
+
}
|
1215 |
+
}
|
1216 |
+
}
|
1217 |
+
{
|
1218 |
+
name: 'sharedTimeRange'
|
1219 |
+
isOptional: true
|
1220 |
+
}
|
1221 |
+
]
|
1222 |
+
#disable-next-line BCP036
|
1223 |
+
type: 'Extension/HubsExtension/PartType/MonitorChartPart'
|
1224 |
+
settings: {}
|
1225 |
+
}
|
1226 |
+
}
|
1227 |
+
]
|
1228 |
+
}
|
1229 |
+
]
|
1230 |
+
}
|
1231 |
+
}
|
1232 |
+
|
1233 |
+
resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = {
|
1234 |
+
name: applicationInsightsName
|
1235 |
+
}
|
infra/core/monitor/applicationinsights.bicep
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param dashboardName string
|
3 |
+
param location string = resourceGroup().location
|
4 |
+
param tags object = {}
|
5 |
+
|
6 |
+
param logAnalyticsWorkspaceId string
|
7 |
+
|
8 |
+
resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
|
9 |
+
name: name
|
10 |
+
location: location
|
11 |
+
tags: tags
|
12 |
+
kind: 'web'
|
13 |
+
properties: {
|
14 |
+
Application_Type: 'web'
|
15 |
+
WorkspaceResourceId: logAnalyticsWorkspaceId
|
16 |
+
}
|
17 |
+
}
|
18 |
+
|
19 |
+
module applicationInsightsDashboard 'applicationinsights-dashboard.bicep' = {
|
20 |
+
name: 'application-insights-dashboard'
|
21 |
+
params: {
|
22 |
+
name: dashboardName
|
23 |
+
location: location
|
24 |
+
applicationInsightsName: applicationInsights.name
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
output connectionString string = applicationInsights.properties.ConnectionString
|
29 |
+
output instrumentationKey string = applicationInsights.properties.InstrumentationKey
|
30 |
+
output name string = applicationInsights.name
|
infra/core/monitor/loganalytics.bicep
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2021-12-01-preview' = {
|
6 |
+
name: name
|
7 |
+
location: location
|
8 |
+
tags: tags
|
9 |
+
properties: any({
|
10 |
+
retentionInDays: 30
|
11 |
+
features: {
|
12 |
+
searchVersion: 1
|
13 |
+
}
|
14 |
+
sku: {
|
15 |
+
name: 'PerGB2018'
|
16 |
+
}
|
17 |
+
})
|
18 |
+
}
|
19 |
+
|
20 |
+
output id string = logAnalytics.id
|
21 |
+
output name string = logAnalytics.name
|
infra/core/monitor/monitoring.bicep
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param logAnalyticsName string
|
2 |
+
param applicationInsightsName string
|
3 |
+
param applicationInsightsDashboardName string
|
4 |
+
param location string = resourceGroup().location
|
5 |
+
param tags object = {}
|
6 |
+
|
7 |
+
module logAnalytics 'loganalytics.bicep' = {
|
8 |
+
name: 'loganalytics'
|
9 |
+
params: {
|
10 |
+
name: logAnalyticsName
|
11 |
+
location: location
|
12 |
+
tags: tags
|
13 |
+
}
|
14 |
+
}
|
15 |
+
|
16 |
+
module applicationInsights 'applicationinsights.bicep' = {
|
17 |
+
name: 'applicationinsights'
|
18 |
+
params: {
|
19 |
+
name: applicationInsightsName
|
20 |
+
location: location
|
21 |
+
tags: tags
|
22 |
+
dashboardName: applicationInsightsDashboardName
|
23 |
+
logAnalyticsWorkspaceId: logAnalytics.outputs.id
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
output applicationInsightsConnectionString string = applicationInsights.outputs.connectionString
|
28 |
+
output applicationInsightsInstrumentationKey string = applicationInsights.outputs.instrumentationKey
|
29 |
+
output applicationInsightsName string = applicationInsights.outputs.name
|
30 |
+
output logAnalyticsWorkspaceId string = logAnalytics.outputs.id
|
31 |
+
output logAnalyticsWorkspaceName string = logAnalytics.outputs.name
|
infra/core/security/dnszone.bicep
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param dnsHostName
|
2 |
+
param virtualNetwork object
|
3 |
+
|
4 |
+
resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
|
5 |
+
name: dnsHostName
|
6 |
+
location: 'global'
|
7 |
+
tags: tags
|
8 |
+
dependsOn: [
|
9 |
+
virtualNetwork
|
10 |
+
]
|
11 |
+
}
|
12 |
+
|
13 |
+
resource privateDnsZoneLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
|
14 |
+
parent: privateDnsZone
|
15 |
+
name: '${dnsHostName}-link'
|
16 |
+
location: 'global'
|
17 |
+
properties: {
|
18 |
+
registrationEnabled: false
|
19 |
+
virtualNetwork: {
|
20 |
+
id: virtualNetwork.id
|
21 |
+
}
|
22 |
+
}
|
23 |
+
}
|
infra/core/security/keyvault-access.bicep
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string = 'add'
|
2 |
+
|
3 |
+
param keyVaultName string = ''
|
4 |
+
param permissions object = { secrets: [ 'get', 'list' ] }
|
5 |
+
param principalId string
|
6 |
+
|
7 |
+
resource keyVaultAccessPolicies 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = {
|
8 |
+
parent: keyVault
|
9 |
+
name: name
|
10 |
+
properties: {
|
11 |
+
accessPolicies: [ {
|
12 |
+
objectId: principalId
|
13 |
+
tenantId: subscription().tenantId
|
14 |
+
permissions: permissions
|
15 |
+
} ]
|
16 |
+
}
|
17 |
+
}
|
18 |
+
|
19 |
+
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
|
20 |
+
name: keyVaultName
|
21 |
+
}
|
infra/core/security/keyvault-secret.bicep
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param tags object = {}
|
3 |
+
param keyVaultName string
|
4 |
+
param contentType string = 'string'
|
5 |
+
@description('The value of the secret. Provide only derived values like blob storage access, but do not hard code any secrets in your templates')
|
6 |
+
@secure()
|
7 |
+
param secretValue string
|
8 |
+
|
9 |
+
param enabled bool = true
|
10 |
+
param exp int = 0
|
11 |
+
param nbf int = 0
|
12 |
+
|
13 |
+
resource keyVaultSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = {
|
14 |
+
name: name
|
15 |
+
tags: tags
|
16 |
+
parent: keyVault
|
17 |
+
properties: {
|
18 |
+
attributes: {
|
19 |
+
enabled: enabled
|
20 |
+
exp: exp
|
21 |
+
nbf: nbf
|
22 |
+
}
|
23 |
+
contentType: contentType
|
24 |
+
value: secretValue
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
|
29 |
+
name: keyVaultName
|
30 |
+
}
|
infra/core/security/keyvault.bicep
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param principalId string = ''
|
6 |
+
|
7 |
+
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = {
|
8 |
+
name: name
|
9 |
+
location: location
|
10 |
+
tags: tags
|
11 |
+
properties: {
|
12 |
+
tenantId: subscription().tenantId
|
13 |
+
sku: { family: 'A', name: 'standard' }
|
14 |
+
accessPolicies: !empty(principalId) ? [
|
15 |
+
{
|
16 |
+
objectId: principalId
|
17 |
+
permissions: { secrets: [ 'get', 'list' ] }
|
18 |
+
tenantId: subscription().tenantId
|
19 |
+
}
|
20 |
+
] : []
|
21 |
+
}
|
22 |
+
}
|
23 |
+
|
24 |
+
output endpoint string = keyVault.properties.vaultUri
|
25 |
+
output name string = keyVault.name
|
infra/core/security/virtualnetwork.bicep
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param postgresServerName string
|
6 |
+
|
7 |
+
var databaseSubnetName = 'database-subnet'
|
8 |
+
var webappSubnetName = 'webapp-subnet'
|
9 |
+
|
10 |
+
resource virtualNetwork 'Microsoft.Network/virtualNetworks@2019-11-01' = {
|
11 |
+
name: name
|
12 |
+
location: location
|
13 |
+
tags: tags
|
14 |
+
properties: {
|
15 |
+
addressSpace: {
|
16 |
+
addressPrefixes: [
|
17 |
+
'10.0.0.0/16'
|
18 |
+
]
|
19 |
+
}
|
20 |
+
subnets: [
|
21 |
+
{
|
22 |
+
name: databaseSubnetName
|
23 |
+
properties: {
|
24 |
+
addressPrefix: '10.0.0.0/24'
|
25 |
+
delegations: [
|
26 |
+
{
|
27 |
+
name: '${name}-subnet-db'
|
28 |
+
properties: {
|
29 |
+
serviceName: 'Microsoft.DBforPostgreSQL/flexibleServers'
|
30 |
+
}
|
31 |
+
}
|
32 |
+
]
|
33 |
+
}
|
34 |
+
}
|
35 |
+
{
|
36 |
+
name: webappSubnetName
|
37 |
+
properties: {
|
38 |
+
addressPrefix: '10.0.1.0/24'
|
39 |
+
delegations: [
|
40 |
+
{
|
41 |
+
name: '${name}-subnet-web'
|
42 |
+
properties: {
|
43 |
+
serviceName: 'Microsoft.Web/serverFarms'
|
44 |
+
}
|
45 |
+
}
|
46 |
+
]
|
47 |
+
}
|
48 |
+
}
|
49 |
+
]
|
50 |
+
}
|
51 |
+
resource databaseSubnet 'subnets' existing = {
|
52 |
+
name: databaseSubnetName
|
53 |
+
}
|
54 |
+
resource webappSubnet 'subnets' existing = {
|
55 |
+
name: webappSubnetName
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
|
60 |
+
name: '${postgresServerName}.private.postgres.database.azure.com'
|
61 |
+
location: 'global'
|
62 |
+
tags: tags
|
63 |
+
dependsOn: [
|
64 |
+
virtualNetwork
|
65 |
+
]
|
66 |
+
}
|
67 |
+
|
68 |
+
resource privateDnsZoneLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
|
69 |
+
parent: privateDnsZone
|
70 |
+
name: '${name}-link'
|
71 |
+
location: 'global'
|
72 |
+
properties: {
|
73 |
+
registrationEnabled: false
|
74 |
+
virtualNetwork: {
|
75 |
+
id: virtualNetwork.id
|
76 |
+
}
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
output databaseSubnetId string = virtualNetwork::databaseSubnet.id
|
81 |
+
output webSubnetId string = virtualNetwork::webappSubnet.id
|
82 |
+
output privateDnsZoneId string = privateDnsZone.id
|
83 |
+
output privateDnsZoneLink object = privateDnsZoneLink
|
infra/core/storage/storage-account.bicep
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
param name string
|
2 |
+
param location string = resourceGroup().location
|
3 |
+
param tags object = {}
|
4 |
+
|
5 |
+
param allowBlobPublicAccess bool = false
|
6 |
+
param containers array = []
|
7 |
+
param kind string = 'StorageV2'
|
8 |
+
param minimumTlsVersion string = 'TLS1_2'
|
9 |
+
param sku object = { name: 'Standard_LRS' }
|
10 |
+
|
11 |
+
resource storage 'Microsoft.Storage/storageAccounts@2022-05-01' = {
|
12 |
+
name: name
|
13 |
+
location: location
|
14 |
+
tags: tags
|
15 |
+
kind: kind
|
16 |
+
sku: sku
|
17 |
+
properties: {
|
18 |
+
minimumTlsVersion: minimumTlsVersion
|
19 |
+
allowBlobPublicAccess: allowBlobPublicAccess
|
20 |
+
networkAcls: {
|
21 |
+
bypass: 'AzureServices'
|
22 |
+
defaultAction: 'Allow'
|
23 |
+
}
|
24 |
+
}
|
25 |
+
|
26 |
+
resource blobServices 'blobServices' = if (!empty(containers)) {
|
27 |
+
name: 'default'
|
28 |
+
resource container 'containers' = [for container in containers: {
|
29 |
+
name: container.name
|
30 |
+
properties: {
|
31 |
+
publicAccess: contains(container, 'publicAccess') ? container.publicAccess : 'None'
|
32 |
+
}
|
33 |
+
}]
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
output name string = storage.name
|
38 |
+
output primaryEndpoints object = storage.properties.primaryEndpoints
|
infra/main.bicep
CHANGED
@@ -22,16 +22,99 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
|
|
22 |
tags: tags
|
23 |
}
|
24 |
|
25 |
-
|
26 |
-
|
|
|
|
|
|
|
|
|
27 |
scope: resourceGroup
|
28 |
params: {
|
29 |
-
name:
|
30 |
location: location
|
31 |
-
resourceToken: resourceToken
|
32 |
tags: tags
|
33 |
-
|
34 |
}
|
35 |
}
|
36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
output AZURE_LOCATION string = location
|
|
|
22 |
tags: tags
|
23 |
}
|
24 |
|
25 |
+
var prefix = '${name}-${resourceToken}'
|
26 |
+
|
27 |
+
var postgresServerName = '${prefix}-postgresql'
|
28 |
+
|
29 |
+
module virtualNetwork 'core/security/virtualnetwork.bicep' = {
|
30 |
+
name: 'virtualnetwork'
|
31 |
scope: resourceGroup
|
32 |
params: {
|
33 |
+
name: '${prefix}-vnet'
|
34 |
location: location
|
|
|
35 |
tags: tags
|
36 |
+
postgresServerName: postgresServerName
|
37 |
}
|
38 |
}
|
39 |
|
40 |
+
var databaseName = 'django'
|
41 |
+
var databaseUser = 'django'
|
42 |
+
|
43 |
+
module postgresServer 'core/database/postgresql/flexibleserver.bicep' = {
|
44 |
+
name: 'postgresql'
|
45 |
+
scope: resourceGroup
|
46 |
+
params: {
|
47 |
+
name: postgresServerName
|
48 |
+
location: location
|
49 |
+
tags: tags
|
50 |
+
sku: {
|
51 |
+
name: 'Standard_B1ms'
|
52 |
+
tier: 'Burstable'
|
53 |
+
}
|
54 |
+
storage: {
|
55 |
+
storageSizeGB: 32
|
56 |
+
}
|
57 |
+
version: '13'
|
58 |
+
administratorLogin: databaseUser
|
59 |
+
administratorLoginPassword: databasePassword
|
60 |
+
databaseName: databaseName
|
61 |
+
delegatedSubnetResourceId: virtualNetwork.outputs.databaseSubnetId
|
62 |
+
privateDnsZoneArmResourceId: virtualNetwork.outputs.privateDnsZoneId
|
63 |
+
privateDnsZoneLink: virtualNetwork.outputs.privateDnsZoneLink
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
module web 'core/host/appservice.bicep' = {
|
68 |
+
name: 'appservice'
|
69 |
+
scope: resourceGroup
|
70 |
+
params: {
|
71 |
+
name: '${prefix}-appservice'
|
72 |
+
location: location
|
73 |
+
tags: union(tags, { 'azd-service-name': 'web' })
|
74 |
+
appServicePlanId: appServicePlan.outputs.id
|
75 |
+
runtimeName: 'python'
|
76 |
+
runtimeVersion: '3.9'
|
77 |
+
scmDoBuildDuringDeployment: true
|
78 |
+
ftpsState: 'Disabled'
|
79 |
+
managedIdentity: true
|
80 |
+
appCommandLine: 'python manage.py migrate && gunicorn --workers 2 --threads 4 --timeout 60 --access-logfile \'-\' --error-logfile \'-\' --bind=0.0.0.0:8000 --chdir=/home/site/wwwroot quizsite.wsgi'
|
81 |
+
virtualNetwork: virtualNetwork
|
82 |
+
subnetResourceId: virtualNetwork.outputs.webSubnetId
|
83 |
+
appSettings: {
|
84 |
+
DBHOST: postgresServerName
|
85 |
+
DBNAME: databaseName
|
86 |
+
DBUSER: databaseUser
|
87 |
+
DBPASS: databasePassword
|
88 |
+
}
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
|
93 |
+
module appServicePlan 'core/host/appserviceplan.bicep' = {
|
94 |
+
name: 'serviceplan'
|
95 |
+
scope: resourceGroup
|
96 |
+
params: {
|
97 |
+
name: '${prefix}-serviceplan'
|
98 |
+
location: location
|
99 |
+
tags: tags
|
100 |
+
sku: {
|
101 |
+
name: 'B1'
|
102 |
+
}
|
103 |
+
reserved: true
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
module logAnalyticsWorkspace 'core/monitor/loganalytics.bicep' = {
|
108 |
+
name: 'loganalytics'
|
109 |
+
scope: resourceGroup
|
110 |
+
params: {
|
111 |
+
name: '${prefix}-loganalytics'
|
112 |
+
location: location
|
113 |
+
tags: tags
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
+
|
118 |
+
|
119 |
+
output WEB_URI string = 'https://${web.outputs.uri}'
|
120 |
output AZURE_LOCATION string = location
|
infra/resources.bicep
DELETED
@@ -1,222 +0,0 @@
|
|
1 |
-
param name string
|
2 |
-
param location string
|
3 |
-
param resourceToken string
|
4 |
-
@secure()
|
5 |
-
param databasePassword string
|
6 |
-
param tags object
|
7 |
-
|
8 |
-
var prefix = '${name}-${resourceToken}'
|
9 |
-
|
10 |
-
var pgServerName = '${prefix}-postgres-server'
|
11 |
-
var databaseSubnetName = 'database-subnet'
|
12 |
-
var webappSubnetName = 'webapp-subnet'
|
13 |
-
|
14 |
-
resource virtualNetwork 'Microsoft.Network/virtualNetworks@2019-11-01' = {
|
15 |
-
name: '${prefix}-vnet'
|
16 |
-
location: location
|
17 |
-
tags: tags
|
18 |
-
properties: {
|
19 |
-
addressSpace: {
|
20 |
-
addressPrefixes: [
|
21 |
-
'10.0.0.0/16'
|
22 |
-
]
|
23 |
-
}
|
24 |
-
subnets: [
|
25 |
-
{
|
26 |
-
name: databaseSubnetName
|
27 |
-
properties: {
|
28 |
-
addressPrefix: '10.0.0.0/24'
|
29 |
-
delegations: [
|
30 |
-
{
|
31 |
-
name: '${prefix}-subnet-delegation'
|
32 |
-
properties: {
|
33 |
-
serviceName: 'Microsoft.DBforPostgreSQL/flexibleServers'
|
34 |
-
}
|
35 |
-
}
|
36 |
-
]
|
37 |
-
}
|
38 |
-
}
|
39 |
-
{
|
40 |
-
name: webappSubnetName
|
41 |
-
properties: {
|
42 |
-
addressPrefix: '10.0.1.0/24'
|
43 |
-
delegations: [
|
44 |
-
{
|
45 |
-
name: '${prefix}-subnet-delegation-web'
|
46 |
-
properties: {
|
47 |
-
serviceName: 'Microsoft.Web/serverFarms'
|
48 |
-
}
|
49 |
-
}
|
50 |
-
]
|
51 |
-
}
|
52 |
-
}
|
53 |
-
]
|
54 |
-
}
|
55 |
-
resource databaseSubnet 'subnets' existing = {
|
56 |
-
name: databaseSubnetName
|
57 |
-
}
|
58 |
-
resource webappSubnet 'subnets' existing = {
|
59 |
-
name: webappSubnetName
|
60 |
-
}
|
61 |
-
}
|
62 |
-
|
63 |
-
resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
|
64 |
-
name: '${pgServerName}.private.postgres.database.azure.com'
|
65 |
-
location: 'global'
|
66 |
-
tags: tags
|
67 |
-
dependsOn: [
|
68 |
-
virtualNetwork
|
69 |
-
]
|
70 |
-
}
|
71 |
-
|
72 |
-
resource privateDnsZoneLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
|
73 |
-
parent: privateDnsZone
|
74 |
-
name: '${pgServerName}-link'
|
75 |
-
location: 'global'
|
76 |
-
properties: {
|
77 |
-
registrationEnabled: false
|
78 |
-
virtualNetwork: {
|
79 |
-
id: virtualNetwork.id
|
80 |
-
}
|
81 |
-
}
|
82 |
-
}
|
83 |
-
|
84 |
-
resource web 'Microsoft.Web/sites@2022-03-01' = {
|
85 |
-
name: '${prefix}-app-service'
|
86 |
-
location: location
|
87 |
-
tags: union(tags, { 'azd-service-name': 'web' })
|
88 |
-
kind: 'app,linux'
|
89 |
-
properties: {
|
90 |
-
serverFarmId: appServicePlan.id
|
91 |
-
siteConfig: {
|
92 |
-
alwaysOn: true
|
93 |
-
linuxFxVersion: 'PYTHON|3.10'
|
94 |
-
ftpsState: 'Disabled'
|
95 |
-
appCommandLine: 'python manage.py migrate && gunicorn --workers 2 --threads 4 --timeout 60 --access-logfile \'-\' --error-logfile \'-\' --bind=0.0.0.0:8000 --chdir=/home/site/wwwroot quizsite.wsgi'
|
96 |
-
}
|
97 |
-
httpsOnly: true
|
98 |
-
}
|
99 |
-
identity: {
|
100 |
-
type: 'SystemAssigned'
|
101 |
-
}
|
102 |
-
|
103 |
-
resource appSettings 'config' = {
|
104 |
-
name: 'appsettings'
|
105 |
-
properties: {
|
106 |
-
DBHOST: postgresServer.name
|
107 |
-
DBNAME: djangoDatabase.name
|
108 |
-
DBUSER: postgresServer.properties.administratorLogin
|
109 |
-
DBPASS: databasePassword
|
110 |
-
SCM_DO_BUILD_DURING_DEPLOYMENT: 'true'
|
111 |
-
}
|
112 |
-
}
|
113 |
-
|
114 |
-
resource logs 'config' = {
|
115 |
-
name: 'logs'
|
116 |
-
properties: {
|
117 |
-
applicationLogs: {
|
118 |
-
fileSystem: {
|
119 |
-
level: 'Verbose'
|
120 |
-
}
|
121 |
-
}
|
122 |
-
detailedErrorMessages: {
|
123 |
-
enabled: true
|
124 |
-
}
|
125 |
-
failedRequestsTracing: {
|
126 |
-
enabled: true
|
127 |
-
}
|
128 |
-
httpLogs: {
|
129 |
-
fileSystem: {
|
130 |
-
enabled: true
|
131 |
-
retentionInDays: 1
|
132 |
-
retentionInMb: 35
|
133 |
-
}
|
134 |
-
}
|
135 |
-
}
|
136 |
-
}
|
137 |
-
|
138 |
-
resource webappVnetConfig 'networkConfig' = {
|
139 |
-
name: 'virtualNetwork'
|
140 |
-
properties: {
|
141 |
-
subnetResourceId: virtualNetwork::webappSubnet.id
|
142 |
-
}
|
143 |
-
}
|
144 |
-
|
145 |
-
dependsOn: [virtualNetwork]
|
146 |
-
|
147 |
-
}
|
148 |
-
|
149 |
-
resource appServicePlan 'Microsoft.Web/serverfarms@2021-03-01' = {
|
150 |
-
name: '${prefix}-service-plan'
|
151 |
-
location: location
|
152 |
-
tags: tags
|
153 |
-
sku: {
|
154 |
-
name: 'B1'
|
155 |
-
}
|
156 |
-
properties: {
|
157 |
-
reserved: true
|
158 |
-
}
|
159 |
-
}
|
160 |
-
|
161 |
-
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-03-01-preview' = {
|
162 |
-
name: '${prefix}-workspace'
|
163 |
-
location: location
|
164 |
-
tags: tags
|
165 |
-
properties: any({
|
166 |
-
retentionInDays: 30
|
167 |
-
features: {
|
168 |
-
searchVersion: 1
|
169 |
-
}
|
170 |
-
sku: {
|
171 |
-
name: 'PerGB2018'
|
172 |
-
}
|
173 |
-
})
|
174 |
-
}
|
175 |
-
|
176 |
-
resource postgresServer 'Microsoft.DBforPostgreSQL/flexibleServers@2022-01-20-preview' = {
|
177 |
-
location: location
|
178 |
-
tags: tags
|
179 |
-
name: pgServerName
|
180 |
-
sku: {
|
181 |
-
name: 'Standard_B1ms'
|
182 |
-
tier: 'Burstable'
|
183 |
-
}
|
184 |
-
properties: {
|
185 |
-
version: '13'
|
186 |
-
administratorLogin: 'django'
|
187 |
-
administratorLoginPassword: databasePassword
|
188 |
-
availabilityZone: '1'
|
189 |
-
storage: {
|
190 |
-
storageSizeGB: 32
|
191 |
-
}
|
192 |
-
backup: {
|
193 |
-
backupRetentionDays: 7
|
194 |
-
geoRedundantBackup: 'Disabled'
|
195 |
-
}
|
196 |
-
network: {
|
197 |
-
delegatedSubnetResourceId: virtualNetwork::databaseSubnet.id
|
198 |
-
privateDnsZoneArmResourceId: privateDnsZone.id
|
199 |
-
}
|
200 |
-
highAvailability: {
|
201 |
-
mode: 'Disabled'
|
202 |
-
}
|
203 |
-
maintenanceWindow: {
|
204 |
-
customWindow: 'Disabled'
|
205 |
-
dayOfWeek: 0
|
206 |
-
startHour: 0
|
207 |
-
startMinute: 0
|
208 |
-
}
|
209 |
-
}
|
210 |
-
|
211 |
-
dependsOn: [
|
212 |
-
privateDnsZoneLink
|
213 |
-
]
|
214 |
-
}
|
215 |
-
|
216 |
-
|
217 |
-
resource djangoDatabase 'Microsoft.DBforPostgreSQL/flexibleServers/databases@2022-01-20-preview' = {
|
218 |
-
parent: postgresServer
|
219 |
-
name: 'django'
|
220 |
-
}
|
221 |
-
|
222 |
-
output WEB_URI string = 'https://${web.properties.defaultHostName}'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|