Skip to content

Commit

Permalink
Merge pull request #5272 from dfe-analytical-services/dev-into-master
Browse files Browse the repository at this point in the history
Merging dev into master
  • Loading branch information
mmyoungman authored Sep 20, 2024
2 parents f1c01cf + 0d39dd2 commit f13a4ba
Show file tree
Hide file tree
Showing 247 changed files with 142,959 additions and 4,296 deletions.
49 changes: 49 additions & 0 deletions azure-pipelines-ui-tests.dfe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,55 @@ jobs:
path: tests/robot-tests/test-results/
artifactName: test-results-admin-public

- job: 'PublicAPI'
displayName: Public API suite - Robot UI tests
timeoutInMinutes: 160
cancelTimeoutInMinutes: 10
condition: succeededOrFailed()
pool: ees-ubuntu2204-large
workspace:
clean: all
steps:
- checkout: self
clean: true
fetchDepth: 5
fetchTags: false

- task: UsePythonVersion@0
displayName: Use Python 3.10
timeoutInMinutes: 5
inputs:
versionSpec: 3.10

- task: AzureKeyVault@2
displayName: 'Azure Key Vault: s101d01-kv-ees-01'
inputs:
azureSubscription: $(SPN_NAME)
KeyVaultName: s101d01-kv-ees-01
SecretsFilter: ees-test-ADMIN-PASSWORD,ees-test-ANALYST-PASSWORD,ees-test-expiredinvite-password,ees-test-NOINVITE-PASSWORD,ees-test-PENDINGINVITE-PASSWORD,ees-alerts-slackapptoken
RunAsPreJob: true

- task: PythonScript@0
displayName: Public API UI tests
inputs:
scriptPath: tests/robot-tests/scripts/run_tests_pipeline.py
arguments: --admin-pass '"$(ees-test-ADMIN-PASSWORD)"' --analyst-pass '"$(ees-test-ANALYST-PASSWORD)"' --expiredinvite-pass '"$(ees-test-expiredinvite-password)"' --noinvite-pass '"$(ees-test-NOINVITE-PASSWORD)"' --pendinginvite-pass '"$(ees-test-PENDINGINVITE-PASSWORD)"' --env "dev" --file "tests/public_api" --processes 4 --rerun-attempts 3
workingDirectory: tests/robot-tests
env:
SLACK_APP_TOKEN: $(ees-alerts-slackapptoken)

- task: PublishTestResults@2
displayName: Publish Test Results
inputs:
testResultsFiles: tests/robot-tests/test-results/xunit.xml
failTaskOnFailedTests: true

- task: PublishPipelineArtifact@1
displayName: Publish Test Pipeline Artifact
condition: succeededOrFailed()
inputs:
path: tests/robot-tests/test-results/
artifactName: test-results-admin-public-api

- job: 'PublicPlaywrightUItest'
displayName: Public suite - Playwright UI tests
Expand Down
6 changes: 0 additions & 6 deletions infrastructure/parameters/dev.parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,6 @@
"blobDeleteRetentionDays": {
"value": 3
},
"devopsSPN": {
"value": "e541f669-7fac-4d33-b480-29b523b9d968",
"metadata": {
"comments": "ObjectId for s101d-datahub-spn-ees-dfe-gov-uk"
}
},
"domain": {
"value": "dev.explore-education-statistics.service.gov.uk"
},
Expand Down
6 changes: 0 additions & 6 deletions infrastructure/parameters/pre-prod.parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,6 @@
"autoscalePublicApplication": {
"value": false
},
"devopsSPN": {
"value": "2d5a7bf2-a6b1-4474-b202-ab17dd87c375",
"metadata": {
"comments": "ObjectId for s101prep-datahub-spn-ees-dfe-gov-uk"
}
},
"domain": {
"value": "pre-production.explore-education-statistics.service.gov.uk"
},
Expand Down
6 changes: 0 additions & 6 deletions infrastructure/parameters/prod.parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,6 @@
"autoscalePublicApplication": {
"value": true
},
"devopsSPN": {
"value": "911681c3-8cc7-4afc-8355-4cf60359d743",
"metadata": {
"comments": "ObjectId for s101p-datahub-spn-ees-dfe-gov-uk"
}
},
"domain": {
"value": "explore-education-statistics.service.gov.uk"
},
Expand Down
8 changes: 1 addition & 7 deletions infrastructure/parameters/test.parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,6 @@
"deploySubnets": {
"value": true
},
"devopsSPN": {
"value": "22888fee-3aa4-411d-8016-bb8a8c3b825a",
"metadata": {
"comments": "ObjectId for s101t-datahub-spn-ees-dfe-gov-uk"
}
},
"domain": {
"value": "test.explore-education-statistics.service.gov.uk"
},
Expand Down Expand Up @@ -99,7 +93,7 @@
"value": true
},
"publicDataDbExists": {
"value": false
"value": true
}
}
}
19 changes: 19 additions & 0 deletions infrastructure/templates/public-api/abbreviations.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Originally sourced from https://github.com/Azure-Samples/todo-csharp-sql/blob/main/infra/abbreviations.json.
@export()
var abbreviations = {
appContainerApps: 'ca'
appManagedEnvironments: 'cae'
// TODO - remove the "-flexibleserver" suffix and change the suffix of our PSQL instance to "-01"
dBforPostgreSQLServers: 'psql-flexibleserver'
// 'ai' is non-standard - it should be 'appi'
insightsComponents: 'ai'
managedIdentityUserAssignedIdentities: 'id'
networkApplicationGateways: 'agw'
operationalInsightsWorkspaces: 'log'
// 'sa' is non-standard - it should be 'st'
storageStorageAccounts: 'sa'
// 'fa' is non-standard - it shoule be 'func'
webSitesFunctions: 'fa'
// 'asp' is non-standard - it should be 'plan'
webServerFarms: 'asp'
}
72 changes: 36 additions & 36 deletions infrastructure/templates/public-api/api-infrastructure-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,41 +53,41 @@ pool:
vmImage: $(vmImageName)

stages:
- template: validate-stage-template.yml
parameters:
stageName: 'Validate_Against_Development'
condition: eq(variables.isDev, true)
environment: 'Development'
serviceConnection: $(serviceConnectionDevelopment)
parameterFile: $(devParamFile)
- template: validate-stage-template.yml
parameters:
stageName: 'Validate_Against_Development'
condition: eq(variables.isDev, true)
environment: 'Development'
serviceConnection: $(serviceConnectionDevelopment)
parameterFile: $(devParamFile)

- template: deploy-stage-template.yml
parameters:
stageName: 'Deploy_to_Development'
condition: and(not(or(failed(), canceled())), eq(variables.isDev, true))
dependsOn: 'Validate_Against_Development'
environment: 'Development'
serviceConnection: $(serviceConnectionDevelopment)
subscription: $(subscription)
parameterFile: $(devParamFile)

- template: deploy-stage-template.yml
parameters:
stageName: 'Deploy_to_Development'
condition: and(succeeded(), eq(variables.isDev, true))
dependsOn: 'Validate_Against_Development'
environment: 'Development'
serviceConnection: $(serviceConnectionDevelopment)
subscription: $(subscription)
parameterFile: $(devParamFile)
- template: validate-stage-template.yml
parameters:
stageName: 'Validate_Against_Test'
condition: eq(variables.isTest, true)
environment: 'Test'
serviceConnection: $(serviceConnectionTest)
parameterFile: $(testParamFile)

- template: validate-stage-template.yml
parameters:
stageName: 'Validate_Against_Test'
condition: eq(variables.isTest, true)
environment: 'Test'
serviceConnection: $(serviceConnectionTest)
parameterFile: $(testParamFile)

- template: deploy-stage-template.yml
parameters:
stageName: 'Deploy_to_Test'
dependsOn: 'Validate_Against_Test'
condition: and(succeeded(), eq(variables.isTest, true))
environment: 'Test'
serviceConnection: $(serviceConnectionTest)
subscription: $(subscription)
parameterFile: $(testParamFile)
- template: deploy-stage-template.yml
parameters:
stageName: 'Deploy_to_Test'
dependsOn: 'Validate_Against_Test'
condition: and(not(or(failed(), canceled())), eq(variables.isTest, true))
environment: 'Test'
serviceConnection: $(serviceConnectionTest)
subscription: $(subscription)
parameterFile: $(testParamFile)

# - template: validate-stage-template.yml
# parameters:
Expand All @@ -100,7 +100,7 @@ stages:
# - template: deploy-stage-template.yml
# parameters:
# stageName: 'Deploy_to_PreProduction'
# condition: and(succeeded(), eq(variables.isMaster, true))
# condition: and(not(or(failed('Validate_Against_PreProduction'), canceled('Validate_Against_PreProduction')), eq(variables.isMaster, true))
# dependsOn: 'Validate_Against_PreProduction'
# environment: 'Pre-production'
# serviceConnection: $(serviceConnectionPreProduction)
Expand All @@ -110,15 +110,15 @@ stages:
# - template: validate-stage-template.yml
# parameters:
# stageName: 'Validate_Against_Production'
# condition: and(succeeded(), eq(variables.isMaster, true))
# condition: and(not(or(failed('Deploy_to_PreProduction'), canceled('Deploy_to_PreProduction')), eq(variables.isMaster, true))
# environment: 'Production'
# serviceConnection: $(serviceConnectionProduction)
# parameterFile: $(prodParamFile)
#
# - template: deploy-stage-template.yml
# parameters:
# stageName: 'Deploy_to_Production'
# condition: and(succeeded(), eq(variables.isMaster, true))
# condition: and(not(or(failed('Validate_Against_Production'), canceled('Validate_Against_Production')), eq(variables.isMaster, true))
# dependsOn: 'Validate_Against_Production'
# environment: 'Production'
# serviceConnection: $(serviceConnectionProduction)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { resourceNamesType } from '../../types.bicep'

@description('Specifies common resource naming variables.')
param resourceNames resourceNamesType

@description('Specifies the location for all resources.')
param location string

@description('Specifies the id of the Container App Environment in which to deploy this Container App.')
param containerAppEnvironmentId string

@description('The tags of the Docker images to deploy.')
param dockerImagesTag string

@description('The URL of the Public API.')
param publicApiUrl string

@description('The URL of the Public site.')
param publicSiteUrl string

@description('The URL of the Content API.')
param contentApiUrl string

@description('Specifies the Application (Client) Id of the App Registration used to represent the API Container App.')
param apiAppRegistrationClientId string

@description('Specifies the Application Insights connection string for this Container App to use for its monitoring.')
param appInsightsConnectionString string

@description('Specifies a set of tags with which to tag the resource in Azure.')
param tagValues object

var dataFilesFileShareMountPath = '/data/public-api-data'

resource adminAppService 'Microsoft.Web/sites@2023-12-01' existing = {
name: resourceNames.existingResources.adminApp
}

resource adminAppServiceIdentity 'Microsoft.ManagedIdentity/identities@2023-01-31' existing = {
scope: adminAppService
name: 'default'
}

var adminAppClientId = adminAppServiceIdentity.properties.clientId
var adminAppPrincipalId = adminAppServiceIdentity.properties.principalId

resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
name: resourceNames.existingResources.keyVault
}

resource apiContainerAppManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = {
name: resourceNames.publicApi.apiAppIdentity
}

module apiContainerAppModule '../../components/containerApp.bicep' = {
name: 'apiContainerAppDeploy'
params: {
location: location
containerAppName: resourceNames.publicApi.apiApp
acrLoginServer: keyVault.getSecret('DOCKER-REGISTRY-SERVER-DOMAIN')
containerAppImageName: 'ees-public-api/api:${dockerImagesTag}'
dockerPullManagedIdentityClientId: keyVault.getSecret('DOCKER-REGISTRY-SERVER-USERNAME')
dockerPullManagedIdentitySecretValue: keyVault.getSecret('DOCKER-REGISTRY-SERVER-PASSWORD')
userAssignedManagedIdentityId: apiContainerAppManagedIdentity.id
managedEnvironmentId: containerAppEnvironmentId
corsPolicy: {
allowedOrigins: [
publicSiteUrl
'http://localhost:3000'
'http://127.0.0.1'
]
}
volumeMounts: [
{
volumeName: 'public-api-fileshare-mount'
mountPath: dataFilesFileShareMountPath
}
]
volumes: [
{
name: 'public-api-fileshare-mount'
storageType: 'AzureFile'
storageName: resourceNames.publicApi.publicApiFileshare
}
]
appSettings: [
{
name: 'ConnectionStrings__PublicDataDb'
value: 'Server=${resourceNames.sharedResources.postgreSqlFlexibleServer}.postgres.database.azure.com;Database=public_data;Port=5432;User Id=${resourceNames.publicApi.apiAppIdentity}'
}
{
// This settings allows the Container App to identify which user-assigned identity it should use in order to
// perform Managed Identity-based authentication and authorization with other Azure services / resources.
//
// It is used in conjunction with the Azure.Identity .NET library to retrieve access tokens for the user-assigned
// identity.
name: 'AZURE_CLIENT_ID'
value: apiContainerAppManagedIdentity.properties.clientId
}
{
name: 'AppSettings__HostUrl'
value: publicApiUrl
}
{
name: 'AppInsights__ConnectionString'
value: appInsightsConnectionString
}
{
name: 'ContentApi__Url'
value: contentApiUrl
}
{
name: 'MiniProfiler__Enabled'
value: 'true'
}
{
name: 'DataFiles__BasePath'
value: dataFilesFileShareMountPath
}
{
name: 'OpenIdConnect__TenantId'
value: tenant().tenantId
}
{
name: 'OpenIdConnect__ClientId'
value: apiAppRegistrationClientId
}
]
entraIdAuthentication: {
appRegistrationClientId: apiAppRegistrationClientId
allowedClientIds: [
adminAppClientId
]
allowedPrincipalIds: [
adminAppPrincipalId
]
requireAuthentication: false
}
tagValues: tagValues
}
}

output containerAppFqdn string = apiContainerAppModule.outputs.containerAppFqdn
output containerAppName string = apiContainerAppModule.outputs.containerAppName
output containerAppHealthProbeRelativeUrl string = '/docs'
Loading

0 comments on commit f13a4ba

Please sign in to comment.