Skip to content

Commit 728a7f3

Browse files
Merge pull request #5222 from dfe-analytical-services/EES-5479-modularise-bicep
Ees 5479 modularise bicep
2 parents 7e0661a + 2f415ec commit 728a7f3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1379
-909
lines changed

infrastructure/parameters/test.parameters.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
"value": true
9494
},
9595
"publicDataDbExists": {
96-
"value": false
96+
"value": true
9797
}
9898
}
9999
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Originally sourced from https://github.com/Azure-Samples/todo-csharp-sql/blob/main/infra/abbreviations.json.
2+
@export()
3+
var abbreviations = {
4+
appContainerApps: 'ca'
5+
appManagedEnvironments: 'cae'
6+
// TODO - remove the "-flexibleserver" suffix and change the suffix of our PSQL instance to "-01"
7+
dBforPostgreSQLServers: 'psql-flexibleserver'
8+
// 'ai' is non-standard - it should be 'appi'
9+
insightsComponents: 'ai'
10+
managedIdentityUserAssignedIdentities: 'id'
11+
networkApplicationGateways: 'agw'
12+
operationalInsightsWorkspaces: 'log'
13+
// 'sa' is non-standard - it should be 'st'
14+
storageStorageAccounts: 'sa'
15+
// 'fa' is non-standard - it shoule be 'func'
16+
webSitesFunctions: 'fa'
17+
// 'asp' is non-standard - it should be 'plan'
18+
webServerFarms: 'asp'
19+
}

infrastructure/templates/public-api/api-infrastructure-pipeline.yml

+37-37
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ resources:
2121
variables:
2222
- group: Public API Infrastructure - common
2323
- name: isDev
24-
value: $[eq(variables['Build.SourceBranch'], 'refs/heads/dev')]
24+
value: $[eq(variables['Build.SourceBranch'], 'refs/heads/EES-5479-modularise-bicep')]
2525
- name: isTest
2626
value: $[eq(variables['Build.SourceBranch'], 'refs/heads/test')]
2727
- name: isMaster
@@ -53,41 +53,41 @@ pool:
5353
vmImage: $(vmImageName)
5454

5555
stages:
56-
- template: validate-stage-template.yml
57-
parameters:
58-
stageName: 'Validate_Against_Development'
59-
condition: eq(variables.isDev, true)
60-
environment: 'Development'
61-
serviceConnection: $(serviceConnectionDevelopment)
62-
parameterFile: $(devParamFile)
56+
- template: validate-stage-template.yml
57+
parameters:
58+
stageName: 'Validate_Against_Development'
59+
condition: eq(variables.isDev, true)
60+
environment: 'Development'
61+
serviceConnection: $(serviceConnectionDevelopment)
62+
parameterFile: $(devParamFile)
63+
64+
- template: deploy-stage-template.yml
65+
parameters:
66+
stageName: 'Deploy_to_Development'
67+
condition: and(not(or(failed(), canceled())), eq(variables.isDev, true))
68+
dependsOn: 'Validate_Against_Development'
69+
environment: 'Development'
70+
serviceConnection: $(serviceConnectionDevelopment)
71+
subscription: $(subscription)
72+
parameterFile: $(devParamFile)
6373

64-
- template: deploy-stage-template.yml
65-
parameters:
66-
stageName: 'Deploy_to_Development'
67-
condition: and(succeeded(), eq(variables.isDev, true))
68-
dependsOn: 'Validate_Against_Development'
69-
environment: 'Development'
70-
serviceConnection: $(serviceConnectionDevelopment)
71-
subscription: $(subscription)
72-
parameterFile: $(devParamFile)
74+
- template: validate-stage-template.yml
75+
parameters:
76+
stageName: 'Validate_Against_Test'
77+
condition: eq(variables.isTest, true)
78+
environment: 'Test'
79+
serviceConnection: $(serviceConnectionTest)
80+
parameterFile: $(testParamFile)
7381

74-
- template: validate-stage-template.yml
75-
parameters:
76-
stageName: 'Validate_Against_Test'
77-
condition: eq(variables.isTest, true)
78-
environment: 'Test'
79-
serviceConnection: $(serviceConnectionTest)
80-
parameterFile: $(testParamFile)
81-
82-
- template: deploy-stage-template.yml
83-
parameters:
84-
stageName: 'Deploy_to_Test'
85-
dependsOn: 'Validate_Against_Test'
86-
condition: and(succeeded(), eq(variables.isTest, true))
87-
environment: 'Test'
88-
serviceConnection: $(serviceConnectionTest)
89-
subscription: $(subscription)
90-
parameterFile: $(testParamFile)
82+
- template: deploy-stage-template.yml
83+
parameters:
84+
stageName: 'Deploy_to_Test'
85+
dependsOn: 'Validate_Against_Test'
86+
condition: and(not(or(failed(), canceled())), eq(variables.isTest, true))
87+
environment: 'Test'
88+
serviceConnection: $(serviceConnectionTest)
89+
subscription: $(subscription)
90+
parameterFile: $(testParamFile)
9191

9292
# - template: validate-stage-template.yml
9393
# parameters:
@@ -100,7 +100,7 @@ stages:
100100
# - template: deploy-stage-template.yml
101101
# parameters:
102102
# stageName: 'Deploy_to_PreProduction'
103-
# condition: and(succeeded(), eq(variables.isMaster, true))
103+
# condition: and(not(or(failed('Validate_Against_PreProduction'), canceled('Validate_Against_PreProduction')), eq(variables.isMaster, true))
104104
# dependsOn: 'Validate_Against_PreProduction'
105105
# environment: 'Pre-production'
106106
# serviceConnection: $(serviceConnectionPreProduction)
@@ -110,15 +110,15 @@ stages:
110110
# - template: validate-stage-template.yml
111111
# parameters:
112112
# stageName: 'Validate_Against_Production'
113-
# condition: and(succeeded(), eq(variables.isMaster, true))
113+
# condition: and(not(or(failed('Deploy_to_PreProduction'), canceled('Deploy_to_PreProduction')), eq(variables.isMaster, true))
114114
# environment: 'Production'
115115
# serviceConnection: $(serviceConnectionProduction)
116116
# parameterFile: $(prodParamFile)
117117
#
118118
# - template: deploy-stage-template.yml
119119
# parameters:
120120
# stageName: 'Deploy_to_Production'
121-
# condition: and(succeeded(), eq(variables.isMaster, true))
121+
# condition: and(not(or(failed('Validate_Against_Production'), canceled('Validate_Against_Production')), eq(variables.isMaster, true))
122122
# dependsOn: 'Validate_Against_Production'
123123
# environment: 'Production'
124124
# serviceConnection: $(serviceConnectionProduction)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import { resourceNamesType } from '../../types.bicep'
2+
3+
@description('Specifies common resource naming variables.')
4+
param resourceNames resourceNamesType
5+
6+
@description('Specifies the location for all resources.')
7+
param location string
8+
9+
@description('Specifies the id of the Container App Environment in which to deploy this Container App.')
10+
param containerAppEnvironmentId string
11+
12+
@description('The tags of the Docker images to deploy.')
13+
param dockerImagesTag string
14+
15+
@description('The URL of the Public API.')
16+
param publicApiUrl string
17+
18+
@description('The URL of the Content API.')
19+
param contentApiUrl string
20+
21+
@description('Specifies the Application (Client) Id of the App Registration used to represent the API Container App.')
22+
param apiAppRegistrationClientId string
23+
24+
@description('Specifies the Application Insights connection string for this Container App to use for its monitoring.')
25+
param appInsightsConnectionString string
26+
27+
@description('Specifies a set of tags with which to tag the resource in Azure.')
28+
param tagValues object
29+
30+
var dataFilesFileShareMountPath = '/data/public-api-data'
31+
32+
resource adminAppService 'Microsoft.Web/sites@2023-12-01' existing = {
33+
name: resourceNames.existingResources.adminApp
34+
}
35+
36+
resource adminAppServiceIdentity 'Microsoft.ManagedIdentity/identities@2023-01-31' existing = {
37+
scope: adminAppService
38+
name: 'default'
39+
}
40+
41+
var adminAppClientId = adminAppServiceIdentity.properties.clientId
42+
var adminAppPrincipalId = adminAppServiceIdentity.properties.principalId
43+
44+
resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
45+
name: resourceNames.existingResources.keyVault
46+
}
47+
48+
resource apiContainerAppManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = {
49+
name: resourceNames.publicApi.apiAppIdentity
50+
}
51+
52+
module apiContainerAppModule '../../components/containerApp.bicep' = {
53+
name: 'apiContainerAppDeploy'
54+
params: {
55+
location: location
56+
containerAppName: resourceNames.publicApi.apiApp
57+
acrLoginServer: keyVault.getSecret('DOCKER-REGISTRY-SERVER-DOMAIN')
58+
containerAppImageName: 'ees-public-api/api:${dockerImagesTag}'
59+
dockerPullManagedIdentityClientId: keyVault.getSecret('DOCKER-REGISTRY-SERVER-USERNAME')
60+
dockerPullManagedIdentitySecretValue: keyVault.getSecret('DOCKER-REGISTRY-SERVER-PASSWORD')
61+
userAssignedManagedIdentityId: apiContainerAppManagedIdentity.id
62+
managedEnvironmentId: containerAppEnvironmentId
63+
corsPolicy: {
64+
allowedOrigins: [
65+
publicApiUrl
66+
'http://localhost:3000'
67+
'http://127.0.0.1'
68+
]
69+
}
70+
volumeMounts: [
71+
{
72+
volumeName: 'public-api-fileshare-mount'
73+
mountPath: dataFilesFileShareMountPath
74+
}
75+
]
76+
volumes: [
77+
{
78+
name: 'public-api-fileshare-mount'
79+
storageType: 'AzureFile'
80+
storageName: resourceNames.publicApi.publicApiFileshare
81+
}
82+
]
83+
appSettings: [
84+
{
85+
name: 'ConnectionStrings__PublicDataDb'
86+
value: 'Server=${resourceNames.sharedResources.postgreSqlFlexibleServer}.postgres.database.azure.com;Database=public_data;Port=5432;User Id=${resourceNames.publicApi.apiAppIdentity}'
87+
}
88+
{
89+
// This settings allows the Container App to identify which user-assigned identity it should use in order to
90+
// perform Managed Identity-based authentication and authorization with other Azure services / resources.
91+
//
92+
// It is used in conjunction with the Azure.Identity .NET library to retrieve access tokens for the user-assigned
93+
// identity.
94+
name: 'AZURE_CLIENT_ID'
95+
value: apiContainerAppManagedIdentity.properties.clientId
96+
}
97+
{
98+
name: 'ContentApi__Url'
99+
value: contentApiUrl
100+
}
101+
{
102+
name: 'MiniProfiler__Enabled'
103+
value: 'true'
104+
}
105+
{
106+
name: 'DataFiles__BasePath'
107+
value: dataFilesFileShareMountPath
108+
}
109+
{
110+
name: 'OpenIdConnect__TenantId'
111+
value: tenant().tenantId
112+
}
113+
{
114+
name: 'OpenIdConnect__ClientId'
115+
value: apiAppRegistrationClientId
116+
}
117+
{
118+
name: 'ApplicationInsights__ConnectionString'
119+
value: appInsightsConnectionString
120+
}
121+
]
122+
entraIdAuthentication: {
123+
appRegistrationClientId: apiAppRegistrationClientId
124+
allowedClientIds: [
125+
adminAppClientId
126+
]
127+
allowedPrincipalIds: [
128+
adminAppPrincipalId
129+
]
130+
requireAuthentication: false
131+
}
132+
tagValues: tagValues
133+
}
134+
}
135+
136+
output containerAppFqdn string = apiContainerAppModule.outputs.containerAppFqdn
137+
output containerAppName string = apiContainerAppModule.outputs.containerAppName
138+
output containerAppHealthProbeRelativeUrl string = '/docs'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { resourceNamesType } from '../../types.bicep'
2+
3+
@description('Specifies common resource naming variables.')
4+
param resourceNames resourceNamesType
5+
6+
@description('Specifies the location for all resources.')
7+
param location string
8+
9+
@description('Specifies a set of tags with which to tag the resource in Azure.')
10+
param tagValues object
11+
12+
resource apiContainerAppManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
13+
name: resourceNames.publicApi.apiAppIdentity
14+
location: location
15+
tags: tagValues
16+
}
17+
18+
// TODO - commenting out for now, as we can't apply roles to Container Registries in other Resource Groups.
19+
// When we have a shared Resource Group for our ACR with special privileges, we can start to use the Container App
20+
// Identity again to pull Docker images, but for now we continue to use our shared SPN.
21+
// module apiContainerAppAcrPullRoleAssignmentModule '../../components/containerRegistryRoleAssignment.bicep' = {
22+
// name: '${resourceNames.publicApi.apiAppIdentity}AcrPullRoleAssignmentDeploy'
23+
// scope: resourceGroup(resourceNames.existingResources.acrResourceGroup)
24+
// params: {
25+
// role: 'AcrPull'
26+
// containerRegistryName: resourceNames.existingResources.acr
27+
// principalIds: [apiContainerAppManagedIdentity.properties.principalId]
28+
// }
29+
// }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { resourceNamesType } from '../../types.bicep'
2+
3+
@description('Specifies common resource naming variables.')
4+
param resourceNames resourceNamesType
5+
6+
@description('Specifies the location for all resources.')
7+
param location string
8+
9+
module applicationInsightsModule '../../components/appInsights.bicep' = {
10+
name: 'appInsightsDeploy'
11+
params: {
12+
location: location
13+
appInsightsName: resourceNames.publicApi.appInsights
14+
}
15+
}
16+
17+
output appInsightsName string = resourceNames.publicApi.appInsights
18+
output appInsightsKey string = applicationInsightsModule.outputs.applicationInsightsKey
19+
output appInsightsConnectionString string = applicationInsightsModule.outputs.applicationInsightsConnectionString

0 commit comments

Comments
 (0)