diff --git a/.github/workflows/terragrunt-deploy.yml b/.github/workflows/terragrunt-deploy.yml index f13406a11..69b3119bf 100644 --- a/.github/workflows/terragrunt-deploy.yml +++ b/.github/workflows/terragrunt-deploy.yml @@ -1,68 +1,44 @@ name: Deploy using terragrunt +permissions: + contents: read + packages: write + on: - workflow_call: + workflow_dispatch: inputs: DEFAULT_APPLICATION_ENVIRONMENT: required: true - type: string - TARGET_ENV: - required: true - type: string + type: choice + options: + - dev + - test + - prod IMAGE_TAG: required: true type: string - IS_HOTFIX: + SCHEMA_NAME: required: true type: string - default: 'false' - - MAX_RECEIVED_COUNT: - required: false - type: number - default: 10 - VISIBILITY_TIMEOUT_SECONDS: - required: false - type: number - default: 10 - PUSH_NOTIFICATION_AWS_USER: - required: false - type: string - default: "" - EVENT_BRIDGE_ARN: - required: false - type: string - default: "" - WFNEWS_URL: - required: false - type: string - default: "" - BAN_PROHIBITION_MONITOR_KEY: - required: false - type: string - default: "" - ACTIVE_FIRE_MONITOR_KEY: - required: false - type: string - default: "" - AREA_RESTRICTIONS_MONITOR_KEY: + default: app_wf1_prev + CHANGELOG_NAME: + type: choice + options: + - none + - changelog_app_wf1_prev + - changelog_app_wf1_prev_proxy + TARGET_LIQUIBASE_TAG: required: false type: string - default: "" - EVACUATION_MONITOR_KEY: - required: false - type: string - default: "" - LAMBDA_LAYER_KEY: - required: false + IS_HOTFIX: + required: true type: string - default: "" + default: 'false' env: - TF_VERSION: 1.5.3 + TF_VERSION: 1.8.5 TG_VERSION: 0.48.4 TG_SRC_PATH: terraform - TFC_WORKSPACE: wfnews-${{ inputs.TARGET_ENV }} REPOSITORY: ghcr.io jobs: @@ -71,11 +47,11 @@ jobs: runs-on: ubuntu-22.04 environment: ${{ inputs.DEFAULT_APPLICATION_ENVIRONMENT }} permissions: - id-token: write + id-token: write # This is required for requesting the JWT + contents: read # This is required for actions/checkout steps: - - name: Check out the repo - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # - name: retrieve lambda artifacts # uses: actions/download-artifact@v3 @@ -83,11 +59,36 @@ jobs: # name: lambda-functions # path: ${{env.TG_SRC_PATH}}/lambda-functions + - id: changeLogCount + name: Determine changelog to execute + run: | + if [ "${{ inputs.CHANGELOG_NAME }}" == "changelog_app_wf1_prev" ]; then + echo "NONPROXY_COUNT=1" >> $GITHUB_OUTPUT + echo "PROXY_COUNT=0" >> $GITHUB_OUTPUT + elif [ "${{ inputs.CHANGELOG_NAME }}" == "changelog_app_wf1_prev_proxy" ] ; then + echo "NONPROXY_COUNT=0" >> $GITHUB_OUTPUT + echo "PROXY_COUNT=1" >> $GITHUB_OUTPUT + else + echo "NONPROXY_COUNT=0" >> $GITHUB_OUTPUT + echo "PROXY_COUNT=0" >> $GITHUB_OUTPUT + fi + + - id: liquibaseCommand + name: Determine liquibase command + run: | + if [ "${{ inputs.TARGET_LIQUIBASE_TAG }}" == "" ]; then + echo "LIQUIBASE_COMMAND=update" >> $GITHUB_OUTPUT + echo "TARGET_LIQUIBASE_TAG=""" >> $GITHUB_OUTPUT + else + echo "LIQUIBASE_COMMAND=update-to-tag" >> $GITHUB_OUTPUT + echo "TARGET_LIQUIBASE_TAG=--tag=${{inputs.TARGET_LIQUIBASE_TAG}}" >> $GITHUB_OUTPUT + fi + - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v2 with: role-to-assume: ${{ secrets.AWS_TERRAFORM_ROLE_TO_ASSUME }} - role-session-name: wfnews-terraform-s3 + role-session-name: wfprev-terraform-s3 aws-region: ca-central-1 - uses: hashicorp/setup-terraform@v2 @@ -98,168 +99,27 @@ jobs: - uses: peter-murray/terragrunt-github-action@v1.0.0 with: terragrunt_version: ${{ env.TG_VERSION }} - - - name: Terragrunt Apply - working-directory: ${{env.TG_SRC_PATH}}/${{ inputs.TARGET_ENV }} - env: - # AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID }} - # AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}} - - UNIQUE_DEPLOY_ID: ${{ github.run_id }} - BCWILDFIRE_CERT_ARN: ${{secrets.BCWILDFIRE_CERT_ARN}} - BASE_BCWILDFIRE_CERT_ARN: ${{secrets.BASE_BCWILDFIRE_CERT_ARN}} + - name: Terragrunt Apply + working-directory: ${{env.TG_SRC_PATH}} - agolAreaRestrictions: ${{vars.AGOL_AREA_RESTRICTIONS}} - agolBansAndProhibitions: ${{vars.AGOL_BANS_AND_PROHIBITIONS}} - agolDangerRatings: ${{vars.AGOL_DANGER_RATINGS}} - agolUrl: ${{vars.AGOL_URL}} - ALB_NAME: ${{ vars.ALB_NAME }} - API_KEY: ${{ secrets.API_KEY }} - NGINX_IMAGE: ${{vars.REGISTRY}}/${{ github.repository_owner }}/${{ vars.NGINX_IMAGE }}:${{ inputs.IMAGE_TAG }} - CLIENT_CPU_UNITS: ${{vars.CLIENT_CPU_UNITS}} - CLIENT_IMAGE: ${{vars.REGISTRY}}/${{ github.repository_owner }}/${{ vars.CLIENT_IMAGE }}${{ inputs.IS_HOTFIX=='true' && '-hotfix' || ''}}:${{ inputs.IMAGE_TAG }} - CLIENT_MEMORY: ${{vars.CLIENT_MEMORY}} - CLOUDFRONT_HEADER: ${{ secrets.CLOUDFRONT_HEADER }} - DB_INSTANCE_TYPE: ${{vars.DB_INSTANCE_TYPE}} - DB_PASS: ${{ secrets.WFONE_DB_PASS }} - DB_SIZE: ${{ vars.DB_SIZE }} - DB_POSTGRES_VERSION: ${{ vars.DB_POSTGRES_VERSION }} - DEFAULT_APPLICATION_ENVIRONMENT: ${{inputs.DEFAULT_APPLICATION_ENVIRONMENT}} - drivebcBaseUrl: ${{vars.DRIVEBC_BASE_URL}} - GITHUB_RELEASE_NAME: ${{ github.event.release.name }} - INSTANCE_COUNT: ${{vars.INSTANCE_COUNT}} - LIQUIBASE_IMAGE: ${{vars.REGISTRY}}/${{ github.repository_owner }}/${{ vars.LIQUIBASE_IMAGE }}:${{ inputs.IMAGE_TAG }} + env: + # Necessary for all components + GITHUB_USERNAME: ${{ secrets.FETCH_IMAGE_USER }} + GITHUB_TOKEN: ${{ secrets.FETCH_IMAGE_TOKEN }} + TFC_PROJECT: ${{ secrets.TFC_PROJECT }} + TARGET_ENV: ${{ inputs.DEFAULT_APPLICATION_ENVIRONMENT }} + APP_COUNT: ${{vars.APP_COUNT}} LOGGING_LEVEL: ${{vars.LOGGING_LEVEL}} - MAX_UPLOAD_SIZE: ${{ vars.MAX_UPLOAD_SIZE }} - openmapsBaseUrl: ${{vars.OPENMAPS_BASE_URL}} - SERVER_CPU_UNITS: ${{vars.SERVER_CPU_UNITS}} - SERVER_IMAGE: ${{vars.REGISTRY}}/${{ github.repository_owner }}/${{ vars.SERVER_IMAGE }}${{ inputs.IS_HOTFIX=='true' && '-hotfix' || ''}}:${{ inputs.IMAGE_TAG }} - SERVER_MEMORY: ${{vars.SERVER_MEMORY}} - siteMinderURLPrefix: ${{vars.SITEMINDER_URL_PREFIX}} - syncIntervalMinutes: ${{vars.SYNC_INTERVAL_MINUTES}} - SMTP_ADMIN_EMAIL: ${{vars.SMTP_ADMIN_EMAIL}} - SMTP_EMAIL_ERROR_SUBJECT: ${{vars.SMTP_EMAIL_ERROR_SUBJECT}} - SMTP_EMAIL_FREQ: ${{vars.SMTP_EMAIL_FREQ}} - SMTP_EMAIL_SUBJECT: ${{vars.SMTP_EMAIL_SUBJECT}} - SMTP_EMAIL_SYNC_ERROR_FREQ: ${{vars.SMTP_EMAIL_SYNC_ERROR_FREQ}} - SMTP_FROM_EMAIL: ${{vars.SMTP_FROM_EMAIL}} - SMTP_HOST_NAME: ${{vars.SMTP_HOST_NAME}} - SMTP_PASSWORD: ${{secrets.WFONE_NOTIFICATIONS_API_SMTP_CREDENTIALS_PASSWORD}} - SNS_EMAIL_TARGETS: ${{ secrets.SNS_EMAIL_TARGETS }} - SUBNET_FILTER: ${{ vars.SUBNET_FILTER }} - TARGET_ENV: ${{ inputs.TARGET_ENV }} - TFC_PROJECT: ${{ secrets.LICENSE_PLATE }} - VPC_NAME: ${{ vars.VPC_NAME }} - WEBADE_OAUTH2_AUTHORIZE_URL: ${{vars.WEBADE_OAUTH2_AUTHORIZE_URL}} - WEBADE_OAUTH2_REST_CLIENT_ID: ${{vars.WEBADE_OAUTH2_REST_CLIENT_ID}} - WEBADE_OAUTH2_UI_CLIENT_ID: ${{vars.WEBADE_OAUTH2_UI_CLIENT_ID}} - WEBADE_OAUTH2_WFNEWS_REST_CLIENT_SECRET: ${{secrets.WEBADE_OAUTH2_WFNEWS_REST_CLIENT_SECRET}} - WEBADE_OAUTH2_WFNEWS_UI_CLIENT_SECRET: ${{secrets.WEBADE_OAUTH2_WFNEWS_UI_CLIENT_SECRET}} - WEBADE-OAUTH2_CHECK_TOKEN_URL: ${{vars.WEBADE_OAUTH2_CHECK_TOKEN_URL}} - WEBADE-OAUTH2_TOKEN_CLIENT_URL: ${{vars.WEBADE_OAUTH2_TOKEN_CLIENT_URL}} - WEBADE-OAUTH2_TOKEN_URL: ${{vars.WEBADE_OAUTH2_TOKEN_URL}} - YOUTUBE_API_KEY: ${{secrets.YOUTUBE_API_KEY}} - YOUTUBE_CHANNEL_ID: ${{secrets.YOUTUBE_CHANNEL_ID}} - WFDM_REST_URL: ${{vars.WFDM_REST_URL}} - FIRE_REPORT_API_URL: ${{vars.FIRE_REPORT_API_URL}} - NOTIFICATION_API_URL: ${{vars.NOTIFICATION_API_URL}} - WFRM_RESOURCE_API_URL: ${{vars.WFRM_RESOURCE_API_URL}} - POINT_ID_URL: ${{vars.POINT_ID_URL}} - WFIM_CLIENT_URL: ${{vars.WFIM_CLIENT_URL}} - WFIM_REST_URL: ${{vars.WFIM_REST_URL}} - WFIM_CODE_TABLES_URL: ${{vars.WFIM_CODE_TABLES_URL}} - WFNEWS_AGOL_QUERY_URL: ${{vars.WFNEWS_AGOL_QUERY_URL}} - WFNEWS_EMAIL_NOTIFICATIONS_ENABLED: ${{vars.WFNEWS_EMAIL_NOTIFICATIONS_ENABLED}} - WFNEWS_MAX_CONNECTIONS: ${{vars.WFNEWS_MAX_CONNECTIONS}} - WFNEWS_USERNAME: ${{vars.WFNEWS_USERNAME}} - - MAX_RECEIVED_COUNT: ${{inputs.MAX_RECEIVED_COUNT }} - VISIBILITY_TIMEOUT_SECONDS: ${{inputs.VISIBILITY_TIMEOUT_SECONDS }} - ACCEPTED_IPS: ${{vars.ACCEPTED_IPS }} - PUSH_NOTIFICATION_AWS_USER: ${{inputs.PUSH_NOTIFICATION_AWS_USER }} - EVENT_BRIDGE_ARN: ${{inputs.EVENT_BRIDGE_ARN }} - SECRET_NAME: ${{secrets.DB_LAMBDA_SECRET_NAME }} - BAN_PROHIBITION_MONITOR_KEY: ${{inputs.BAN_PROHIBITION_MONITOR_KEY }} - ACTIVE_FIRE_MONITOR_KEY: ${{inputs.ACTIVE_FIRE_MONITOR_KEY }} - AREA_RESTRICTIONS_MONITOR_KEY: ${{inputs.AREA_RESTRICTIONS_MONITOR_KEY }} - EVACUATION_MONITOR_KEY: ${{inputs.EVACUATION_MONITOR_KEY }} - LAMBDA_LAYER_KEY: ${{inputs.LAMBDA_LAYER_KEY }} - - # POINTID API VARIABLES - DATABASE_WEATHER_URL: ${{ vars.DATABASE_WEATHER_URL }} - DATABASE_WEATHER_USER: ${{vars.DATABASE_WEATHER_USER }} - BCGW_URL: ${{vars.BCGW_URL }} - WFGS_URL: ${{vars.WFGS_URL }} - MAX_ALLOWED_RADIUS: ${{vars.MAX_ALLOWED_RADIUS }} - POINTID_ASYNC_JOB_INTERVAL: ${{vars.POINTID_ASYNC_JOB_INTERVAL }} - POINTID_ASYNC_JOB_REF_LAT: ${{vars.POINTID_ASYNC_JOB_REF_LAT }} - POINTID_ASYNC_JOB_REF_LONG: ${{vars.POINTID_ASYNC_JOB_REF_LONG }} - POINTID_ASYNC_JOB_REF_RADIUS: ${{vars.POINTID_ASYNC_JOB_REF_RADIUS }} - WEATHER_HOST: ${{vars.WEATHER_HOST }} - WEATHER_USER: ${{vars.WEATHER_USER }} - WFARCGIS_URL: ${{vars.WFARCGIS_URL }} - WFARCGIS_LAYER_AREA_RESTRICTIONS: ${{vars.WFARCGIS_LAYER_AREA_RESTRICTIONS }} - WFARCGIS_LAYER_BANS_PROHIBITION_AREAS: ${{vars.WFARCGIS_LAYER_BANS_PROHIBITION_AREAS }} - WFARCGIS_LAYER_DANGER_RATING: ${{vars.WFARCGIS_LAYER_DANGER_RATING }} - WFARCGIS_LAYER_ACTIVE_FIRES: ${{vars.WFARCGIS_LAYER_ACTIVE_FIRES }} - WFARCGIS_LAYER_EVACUATION_ORDERS_ALERTS: ${{vars.WFARCGIS_LAYER_EVACUATION_ORDERS_ALERTS }} - WFARCGIS_LAYER_FIRE_CENTRE_BOUNDARIES: ${{vars.WFARGIS_LAYER_FIRE_CENTRE_BOUNDARIES }} - POINTID_WEBADE_OAUTH2_CLIENT_ID: ${{vars.POINTID_WEBADE_OAUTH2_CLIENT_ID }} - POINTID_WEBADE_OAUTH2_TOKEN_URL: ${{vars.POINTID_WEBADE_OAUTH2_TOKEN_URL }} - POINTID_WEBADE_OAUTH2_CLIENT_SCOPES: ${{vars.POINTID_WEBADE_OAUTH2_CLIENT_SCOPES }} - FIREWEATHER_BASEURL: ${{vars.FIREWEATHER_BASEURL }} - FIREWEATHER_STATIONS_KEY: ${{vars.FIREWEATHER_STATIONS_KEY }} - WFNEWS_QUEUESIZE: ${{vars.WFNEWS_QUEUESIZE }} - DATABASE_WEATHER_PWD: ${{secrets.DATABASE_WEATHER_PWD }} - WEATHER_PASSWORD: ${{secrets.WEATHER_PASSWORD }} - POINTID_WEBADE_OAUTH2_CLIENT_SECRET: ${{secrets.POINTID_WEBADE_OAUTH2_CLIENT_SECRET }} - POINTID_IMAGE: ${{vars.REGISTRY}}/${{ github.repository_owner }}/${{ vars.POINTID_IMAGE }}${{ inputs.IS_HOTFIX=='true' && '-hotfix' || ''}}:${{ inputs.IMAGE_TAG }} - - # WFONE NOTIFICATIONS API - WFONE_NOTIFICATIONS_API_DATASOURCE_MAX_CONNECTIONS: ${{vars.WFONE_NOTIFICATIONS_API_DATASOURCE_MAX_CONNECTIONS}} - WFONE_NOTIFICATIONS_API_DATASOURCE_PASSWORD: ${{secrets.WFONE_NOTIFICATIONS_API_DATASOURCE_PASSWORD}} - WFONE_NOTIFICATIONS_API_DATASOURCE_USER: ${{vars.WFONE_NOTIFICATIONS_API_DATASOURCE_USER}} - WFONE_NOTIFICATIONS_API_EMAIL_ADMIN_EMAIL: ${{secrets.WFONE_NOTIFICATIONS_API_EMAIL_ADMIN_EMAIL}} - WFONE_NOTIFICATIONS_API_EMAIL_FROM_EMAIL: ${{vars.WFONE_NOTIFICATIONS_API_EMAIL_FROM_EMAIL}} - WFONE_NOTIFICATIONS_API_EMAIL_NOTIFICATIONS_ENABLED: ${{vars.WFONE_NOTIFICATIONS_API_EMAIL_NOTIFICATIONS_ENABLED}} - WFONE_NOTIFICATIONS_API_EMAIL_SYNC_SEND_ERROR_FREQ: ${{vars.WFONE_NOTIFICATIONS_API_EMAIL_SYNC_SEND_ERROR_FREQ}} - WFONE_NOTIFICATIONS_API_EMAIL_SYNC_SEND_ERROR_SUBJECT: ${{vars.WFONE_NOTIFICATIONS_API_EMAIL_SYNC_SEND_ERROR_SUBJECT}} - WFONE_NOTIFICATIONS_API_EMAIL_SYNC_SEND_FREQ: ${{vars.WFONE_NOTIFICATIONS_API_EMAIL_SYNC_SEND_FREQ}} - WFONE_NOTIFICATIONS_API_EMAIL_SYNC_SUBJECT: ${{vars.WFONE_NOTIFICATIONS_API_EMAIL_SYNC_SUBJECT}} - WFONE_NOTIFICATIONS_API_PUSH_ITEM_EXPIRE_HOURS: ${{vars.WFONE_NOTIFICATIONS_API_PUSH_ITEM_EXPIRE_HOURS}} - WFONE_NOTIFICATIONS_API_QUARTZ_CONSUMER_INTERVAL_SECONDS: ${{vars.WFONE_NOTIFICATIONS_API_QUARTZ_CONSUMER_INTERVAL_SECONDS}} - WFONE_NOTIFICATIONS_API_SMTP_CREDENTIALS_PASSWORD: ${{secrets.WFONE_NOTIFICATIONS_API_SMTP_CREDENTIALS_PASSWORD}} - WFONE_NOTIFICATIONS_API_SMTP_CREDENTIALS_USER: ${{secrets.WFONE_NOTIFICATIONS_API_SMTP_CREDENTIALS_USER}} - WFONE_NOTIFICATIONS_API_SMTP_HOST_NAME: ${{vars.WFONE_NOTIFICATIONS_API_SMTP_HOST_NAME}} - WFONE_NOTIFICATIONS_API_WEBADE_OAUTH2_CLIENT_ID: ${{vars.WFONE_NOTIFICATIONS_API_WEBADE_OAUTH2_CLIENT_ID}} - WFONE_NOTIFICATIONS_API_WEBADE_OAUTH2_REST_CLIENT_SECRET: ${{secrets.WFONE_NOTIFICATIONS_API_WEBADE_OAUTH2_REST_CLIENT_SECRET}} - WFONE_NOTIFICATIONS_API_WEBADE_OAUTH2_WFIM_CLIENT_ID: ${{vars.WFONE_NOTIFICATIONS_API_WEBADE_OAUTH2_CLIENT_ID}} - WFONE_NOTIFICATIONS_API_IMAGE: ${{vars.REGISTRY}}/${{ github.repository_owner }}/${{ vars.NOTIFICATIONS_API_IMAGE }}${{ inputs.IS_HOTFIX=='true' && '-hotfix' || ''}}:${{ inputs.IMAGE_TAG }} - WFONE_NOTIFICATIONS_API_WEBADE_OAUTH2_CHECK_TOKEN_URL: ${{vars.WEBADE_OAUTH2_CHECK_TOKEN_URL}} - WFONE_NOTIFICATIONS_API_WEBADE_OAUTH2_TOKEN_CLIENT_URL: ${{vars.WEBADE_OAUTH2_TOKEN_CLIENT_URL}} - WFONE_NOTIFICATIONS_API_WEBADE_OAUTH2_TOKEN_URL: ${{vars.WEBADE_OAUTH2_TOKEN_URL}} - - - - #WFONE-PUSH-NOTIFICATION-API - WFONE_PUSH_ITEM_EXPIRE_HOURS_EVAC: ${{ vars.WFONE_PUSH_ITEM_EXPIRE_HOURS_EVAC }} - WFONE_PUSH_ITEM_EXPIRE_HOURS_FIRE: ${{ vars.WFONE_PUSH_ITEM_EXPIRE_HOURS_FIRE }} - WFONE_PUSH_ITEM_EXPIRE_HOURS_BAN: ${{ vars.WFONE_PUSH_ITEM_EXPIRE_HOURS_BAN }} - WFONE_PUSH_ITEM_EXPIRE_HOURS_RESTRICTED_AREA: ${{ vars.WFONE_PUSH_ITEM_EXPIRE_HOURS_RESTRICTED_AREA }} - WFONE_NOTIFICATIONS_PUSH_SQS_MONITOR_ATTRIBUTE: ${{ vars.WFONE_PUSH_NOTIFICATION_SQS_MONITOR_ATTRIBUTE }} - WFONE_NOTIFICATIONS_PUSH_SQS_MAX_MESSAGES: ${{ vars.WFONE_PUSH_NOTIFICATION_SQS_MAX_MESSAGES }} - WFONE_NOTIFICATIONS_PUSH_SQS_WAIT_SECONDS: ${{ vars.WFONE_PUSH_NOTIFICATION_SQS_WAIT_SECONDS }} - WFONE_NOTIFICATIONS_PUSH_CONSUMER_INTERVAL_SECONDS: ${{ vars.WFONE_PUSH_NOTIFICATION_CONSUMER_INTERVAL_SECONDS }} - WFONE_FIREBASE_DB_URL: ${{ vars.WFONE_FIREBASE_DB_URL }} - WFONE_NOTIFICATIONS_PUSH_PREFIX: ${{ vars.WFONE_PUSH_NOTIFICATION_PREFIX }} - WFONE_NOTIFICATIONS_PUSH_NEAR_ME_INTERVAL_SECONDS: ${{ vars.WFONE_PUSH_NOTIFICATION_NEAR_ME_INTERVAL_SECONDS }} - WFONE_NOTIFICATIONS_PUSH_AWS_ACCESS_KEY: ${{ secrets.WFONE_PUSH_NOTIFICATION_AWS_ACCESS_KEY }} - WFONE_NOTIFICATIONS_PUSH_AWS_SECRET_KEY: ${{ secrets.WFONE_PUSH_NOTIFICATION_AWS_SECRET_KEY }} - WFONE_DB_PASS: ${{ secrets.WFONE_DB_PASS }} - WFONE_NOTIFICATIONS_PUSH_API_IMAGE: ${{vars.REGISTRY}}/${{ github.repository_owner }}/${{ vars.NOTIFICATIONS_PUSH_API_IMAGE }}${{ inputs.IS_HOTFIX=='true' && '-hotfix' || ''}}:${{ inputs.IMAGE_TAG }} - FIREBASE_CONFIG_JSON: ${{ secrets.FIREBASE_CONFIG_JSON }} + # Necessary for WFPREV API + WFPREV_API_NAME: wfprev-api + WFPREV_API_IMAGE: ${{ vars.REPOSITORY }}/${{ github.repository }}-wfprev-api:${{ inputs.IMAGE_TAG }} + WFPREV_API_CPU_UNITS: ${{vars.WFPREV_API_CPU_UNITS}} + WFPREV_API_MEMORY: ${{vars.WFPREV_API_MEMORY}} + WFPREV_API_PORT: ${{vars.WFPREV_API_PORT}} + # WFPREV UI + client_image: ${{ vars.REPOSITORY }}/${{ github.repository }}-wfprev-ui:${{ inputs.IMAGE_TAG }} + WEBADE_OAUTH2_WFPREV_UI_CLIENT_SECRET: ${{ secrets.WEBADE_OAUTH2_WFPREV_UI_CLIENT_SECRET }} run: terragrunt apply --terragrunt-non-interactive -auto-approve - diff --git a/terraform/alb.tf b/terraform/alb.tf index 423c0875f..a6887efd4 100644 --- a/terraform/alb.tf +++ b/terraform/alb.tf @@ -3,14 +3,14 @@ # Must use a pre-existing ALB, such as default that is pre-provisioned as part of the account creation # This ALB has all traffic on *.LICENSE-PLATE-ENV.nimbus.cloud.gob.bc.ca routed to it -# data "aws_lb" "wfhr_main" { +# data "aws_lb" "wfprev_main" { # name = var.alb_name # } # # Redirect all traffic from the ALB to the target group -# data "aws_alb_listener" "wfhr_main_front_end" { -# load_balancer_arn = data.aws_lb.wfhr_main.id +# data "aws_alb_listener" "wfprev_main_front_end" { +# load_balancer_arn = data.aws_lb.wfprev.id # port = 443 # } @@ -20,7 +20,7 @@ data "aws_acm_certificate" "example" { statuses = ["ISSUED"] } -resource "aws_lb" "wfhr_main" { +resource "aws_lb" "wfprev_main" { name = var.ALB_NAME internal = true load_balancer_type = "application" @@ -35,28 +35,11 @@ resource "aws_lb" "wfhr_main" { } -# resource "aws_lb_listener" "wfhr_main" { -# load_balancer_arn = "${aws_lb.wfhr_main.arn}" -# port = "443" -# protocol = "HTTPS" -# ssl_policy = "ELBSecurityPolicy-2016-08" -# certificate_arn = data.aws_acm_certificate.example.arn - -# default_action { -# type = "fixed-response" -# fixed_response { -# content_type = "text/plain" -# status_code = 200 -# } -# } -# } - - ////////////////////////// /// LISTENER RESOURCES /// ////////////////////////// -resource "aws_lb_listener" "wfhr_main" { - load_balancer_arn = "${aws_lb.wfhr_main.arn}" +resource "aws_lb_listener" "wfprev_main" { + load_balancer_arn = "${aws_lb.wfprev_main.arn}" port = "80" protocol = "HTTP" @@ -69,164 +52,13 @@ resource "aws_lb_listener" "wfhr_main" { } } -resource "aws_lb_listener_rule" "wfhr_payroll_api_host_based_weighted_routing" { - listener_arn = aws_lb_listener.wfhr_main.arn - - action { - type = "forward" - target_group_arn = aws_alb_target_group.wfhr_payroll_api.arn - } - - condition { - path_pattern { - values = [for sn in var.PAYROLL_API_NAMES : "/${aws_apigatewayv2_stage.wfhr_stage.name}/${sn}"] - } - } -# condition { -# http_header { -# http_header_name = "X-Cloudfront-Header" -# values = ["${var.cloudfront_header}"] -# } -# } -} - -resource "aws_lb_listener_rule" "wfhr_ediaries_war_host_based_weighted_routing" { - listener_arn = aws_lb_listener.wfhr_main.arn - - action { - type = "forward" - target_group_arn = aws_alb_target_group.wfhr_ediaries_war.arn - } - - condition { - path_pattern { - values = [for sn in var.EDIARIES_WAR_NAMES : "/${aws_apigatewayv2_stage.wfhr_stage.name}/${sn}"] - } - } -} - -resource "aws_lb_listener_rule" "wfhr_earnings_war_host_based_weighted_routing" { - listener_arn = aws_lb_listener.wfhr_main.arn - - action { - type = "forward" - target_group_arn = aws_alb_target_group.wfhr_earnings_war.arn - } - - condition { - path_pattern { - values = [for sn in var.EARNINGS_WAR_NAMES : "/${aws_apigatewayv2_stage.wfhr_stage.name}/${sn}"] - } - } -} - -resource "aws_lb_listener_rule" "wfhr_earnings_api_host_based_weighted_routing" { - listener_arn = aws_lb_listener.wfhr_main.arn - - action { - type = "forward" - target_group_arn = aws_alb_target_group.wfhr_earnings_api.arn - } - - condition { - path_pattern { - values = [for sn in var.EARNINGS_API_NAMES : "/${aws_apigatewayv2_stage.wfhr_stage.name}/${sn}"] - } - } -} - -resource "aws_lb_listener_rule" "wfhr_diary_submission_listener_api_host_based_weighted_routing" { - listener_arn = aws_lb_listener.wfhr_main.arn - - action { - type = "forward" - target_group_arn = aws_alb_target_group.wfhr_diary_submission_listener_api.arn - } - - condition { - path_pattern { - values = [for sn in var.DIARY_SUBMISSION_LISTENER_API_NAMES : "/${aws_apigatewayv2_stage.wfhr_stage.name}/${sn}"] - } - } - -} - - -resource "aws_lb_listener_rule" "wfhr_earnings_submission_listener_api_host_based_weighted_routing" { - listener_arn = aws_lb_listener.wfhr_main.arn - - action { - type = "forward" - target_group_arn = aws_alb_target_group.wfhr_earnings_submission_listener_api.arn - } - - condition { - path_pattern { - values = [for sn in var.EARNINGS_SUBMISSION_LISTENER_API_NAMES : "/${aws_apigatewayv2_stage.wfhr_stage.name}/${sn}"] - } - } - -} - - -resource "aws_lb_listener_rule" "wfhr_chips_sync_api_host_based_weighted_routing" { - listener_arn = aws_lb_listener.wfhr_main.arn - action { - type = "forward" - target_group_arn = aws_alb_target_group.wfhr_chips_sync_api.arn - } - - condition { - path_pattern { - values = [for sn in var.CHIPS_SYNC_NAMES : "/${aws_apigatewayv2_stage.wfhr_stage.name}/${sn}"] - } - } -} - -resource "aws_lb_listener_rule" "wfhr_psa_chips_data_stub_api_host_based_weighted_routing" { - listener_arn = aws_lb_listener.wfhr_main.arn - - action { - type = "forward" - target_group_arn = aws_alb_target_group.wfhr_psa_chips_data_stub_api.arn - } - - condition { - path_pattern { - values = [for sn in var.PSA_CHIPS_STUB_NAMES : "/${aws_apigatewayv2_stage.wfhr_stage.name}/${sn}"] - } - } -} - -resource "aws_lb_listener_rule" "wfhr_jasper_reports_server" { - // MUST have listener for target group to exist, but can set condition which will always be false - listener_arn = aws_lb_listener.wfhr_main.arn - action { - type = "forward" - target_group_arn = aws_alb_target_group.wfhr_jasper_reports_server.arn - } - - condition { - #NOTE: can still only be accessed from inside appropriate security group, despite listener - source_ip { - values = [for sn in module.network.aws_subnet.app : sn.cidr_block] - } - } - - condition { - path_pattern { - values = [for sn in var.JASPER_REPORTS_SERVER_NAMES : "/${aws_apigatewayv2_stage.wfhr_stage.name}/${sn}"] - } - } - -} ////////////////////////////// /// TARGET GROUP RESOURCES /// ////////////////////////////// -resource "aws_alb_target_group" "wfhr_payroll_api" { - name = "wfhr-payroll-api-${var.TARGET_ENV}" - port = var.PAYROLL_API_PORT +resource "aws_alb_target_group" "wfprev_api" { + name = "wfprev-payroll-api-${var.TARGET_ENV}" + port = var.WFPREV_API_PORT protocol = "HTTP" vpc_id = module.network.aws_vpc.id target_type = "ip" @@ -238,154 +70,16 @@ resource "aws_alb_target_group" "wfhr_payroll_api" { protocol = "HTTP" matcher = "200" timeout = "3" - path = "/${aws_apigatewayv2_stage.wfhr_stage.name}/wfhr-payroll-api/checkHealth?callstack=test" + path = "/${aws_apigatewayv2_stage.wfprev_stage.name}/wfprev-api/checkHealth?callstack=test" unhealthy_threshold = "2" } # tags = local.common_tags } -resource "aws_alb_target_group" "wfhr_ediaries_war" { - name = "wfhr-ediaries-war-${var.TARGET_ENV}" - port = var.EDIARIES_WAR_PORT - protocol = "HTTP" - vpc_id = module.network.aws_vpc.id - target_type = "ip" - deregistration_delay = 30 - - health_check { - healthy_threshold = "2" - interval = "300" - protocol = "HTTP" - matcher = "200" - timeout = "3" - path = "/${aws_apigatewayv2_stage.wfhr_stage.name}/wfhr-ediaries-ui/" - unhealthy_threshold = "2" - } -} - -resource "aws_alb_target_group" "wfhr_earnings_war" { - name = "wfhr-earnings-war-${var.TARGET_ENV}" - port = var.EDIARIES_WAR_PORT - protocol = "HTTP" - vpc_id = module.network.aws_vpc.id - target_type = "ip" - deregistration_delay = 30 - - health_check { - healthy_threshold = "2" - interval = "300" - protocol = "HTTP" - matcher = "200" - timeout = "3" - path = "/${aws_apigatewayv2_stage.wfhr_stage.name}/wfhr-earnings/" - unhealthy_threshold = "2" - } -} - -resource "aws_alb_target_group" "wfhr_chips_sync_api" { - name = "wfhr-chips-sync-api-${var.TARGET_ENV}" - port = var.CHIPS_SYNC_PORT - protocol = "HTTP" - vpc_id = module.network.aws_vpc.id - target_type = "ip" - deregistration_delay = 30 - - health_check { - healthy_threshold = "2" - interval = "300" - protocol = "HTTP" - matcher = "200" - timeout = "3" - path = "/${aws_apigatewayv2_stage.wfhr_stage.name}/wfhr-chips-sync-api/checkHealth?callstack=test" - unhealthy_threshold = "2" - } -} - -resource "aws_alb_target_group" "wfhr_psa_chips_data_stub_api" { - name = "wfhr-psa-chips-data-stub-api-${var.TARGET_ENV}" - port = var.PSA_CHIPS_STUB_PORT - protocol = "HTTP" - vpc_id = module.network.aws_vpc.id - target_type = "ip" - deregistration_delay = 30 - - health_check { - healthy_threshold = "2" - interval = "300" - protocol = "HTTP" - #Does not have checkHealth endpoint and API is secure - expect 401 on any request without credentials - matcher = "401" - timeout = "3" - path = "/${aws_apigatewayv2_stage.wfhr_stage.name}/wfhr-psa-chips-data-stub-api" - unhealthy_threshold = "2" - } -} - -resource "aws_alb_target_group" "wfhr_earnings_api" { - name = "wfhr-earnings-api-${var.TARGET_ENV}" - port = var.EARNINGS_API_PORT - protocol = "HTTP" - vpc_id = module.network.aws_vpc.id - target_type = "ip" - - deregistration_delay = 30 - - health_check { - healthy_threshold = "2" - interval = "300" - protocol = "HTTP" - matcher = "200" - timeout = "3" - path = "/${aws_apigatewayv2_stage.wfhr_stage.name}/wfhr-earnings-api/checkHealth?callstack=test" - unhealthy_threshold = "2" - } -} - - -resource "aws_alb_target_group" "wfhr_diary_submission_listener_api" { - name = "wfhr-diary-submission-lstnr-${var.TARGET_ENV}" - port = var.DIARY_SUBMISSION_LISTENER_API_PORT - protocol = "HTTP" - vpc_id = module.network.aws_vpc.id - target_type = "ip" - deregistration_delay = 30 - - health_check { - healthy_threshold = "2" - interval = "300" - protocol = "HTTP" - #TODO: Replace matcher and path with correct values once checkHealth endpoint available - matcher = "200" - timeout = "3" - path = "/${aws_apigatewayv2_stage.wfhr_stage.name}/wfhr-diary-submission-listener-api/checkHealth?callstack=test" - unhealthy_threshold = "2" - } -} - -resource "aws_alb_target_group" "wfhr_jasper_reports_server" { - name = "wfhr-jasper-reports-${var.TARGET_ENV}" - port = var.JASPER_REPORTS_SERVER_PORT - protocol = "HTTP" - vpc_id = module.network.aws_vpc.id - target_type = "ip" - deregistration_delay = 30 - - health_check { - healthy_threshold = "2" - interval = "300" - protocol = "HTTP" - #TODO: Replace matcher and path with correct values once checkHealth endpoint available - matcher = "200" - timeout = "3" - path = "/jasperserver/" - unhealthy_threshold = "2" - } -} - -resource "aws_alb_target_group" "wfhr_earnings_submission_listener_api" { - name = "wfhr-earn-submission-lstnr-${var.TARGET_ENV}" - port = var.EARNINGS_SUBMISSION_LISTENER_API_PORT +resource "aws_alb_target_group" "wfprev_ui" { + name = "wfprev-ui-${var.TARGET_ENV}" + port = var.WFPREV_UI_PORT protocol = "HTTP" vpc_id = module.network.aws_vpc.id target_type = "ip" @@ -395,10 +89,9 @@ resource "aws_alb_target_group" "wfhr_earnings_submission_listener_api" { healthy_threshold = "2" interval = "300" protocol = "HTTP" - #TODO: Replace matcher and path with correct values once checkHealth endpoint available matcher = "200" timeout = "3" - path = "/${aws_apigatewayv2_stage.wfhr_stage.name}/wfhr-earnings-submission-listener-api/checkHealth?callstack=test" + path = "/${aws_apigatewayv2_stage.wfprev_stage.name}/wfprev-ui/" unhealthy_threshold = "2" } } \ No newline at end of file diff --git a/terraform/api_gateway.tf b/terraform/api_gateway.tf index 2ffc20ddf..af7b87690 100644 --- a/terraform/api_gateway.tf +++ b/terraform/api_gateway.tf @@ -1,19 +1,19 @@ // access externally -resource "aws_apigatewayv2_api" "wfhr_api_gateway" { - name = "wfhr-api-gateway-${var.TARGET_ENV}" +resource "aws_apigatewayv2_api" "wfprev_api_gateway" { + name = "wfprev-api-gateway-${var.TARGET_ENV}" protocol_type = "HTTP" } resource "aws_apigatewayv2_route" "base_route" { - api_id = aws_apigatewayv2_api.wfhr_api_gateway.id + api_id = aws_apigatewayv2_api.wfprev_api_gateway.id route_key = "$default" - target = "integrations/${aws_apigatewayv2_integration.wfhr_vpc_integration.id}" + target = "integrations/${aws_apigatewayv2_integration.wfprev_vpc_integration.id}" } -resource "aws_apigatewayv2_vpc_link" "wfhr_vpc_link" { - name = "wfhr-vpc-link-${var.TARGET_ENV}" +resource "aws_apigatewayv2_vpc_link" "wfprev_vpc_link" { + name = "wfprev-vpc-link-${var.TARGET_ENV}" security_group_ids = [data.aws_security_group.web.id] subnet_ids = module.network.aws_subnet_ids.web.ids @@ -22,15 +22,15 @@ resource "aws_apigatewayv2_vpc_link" "wfhr_vpc_link" { } } -resource "aws_apigatewayv2_integration" "wfhr_vpc_integration" { - api_id = aws_apigatewayv2_api.wfhr_api_gateway.id - description = "WFHR Payroll API integration" +resource "aws_apigatewayv2_integration" "wfprev_vpc_integration" { + api_id = aws_apigatewayv2_api.wfprev_api_gateway.id + description = "WFPREV API integration" integration_type = "HTTP_PROXY" - integration_uri = aws_lb_listener.wfhr_main.arn + integration_uri = aws_lb_listener.wfprev_main.arn integration_method = "ANY" connection_type = "VPC_LINK" - connection_id = aws_apigatewayv2_vpc_link.wfhr_vpc_link.id + connection_id = aws_apigatewayv2_vpc_link.wfprev_vpc_link.id response_parameters { @@ -42,20 +42,20 @@ resource "aws_apigatewayv2_integration" "wfhr_vpc_integration" { } -resource "aws_apigatewayv2_stage" "wfhr_stage" { - api_id = aws_apigatewayv2_api.wfhr_api_gateway.id +resource "aws_apigatewayv2_stage" "wfprev_stage" { + api_id = aws_apigatewayv2_api.wfprev_api_gateway.id name = "pub" } -resource "aws_apigatewayv2_deployment" "wfhr_deployment" { - api_id = aws_apigatewayv2_api.wfhr_api_gateway.id +resource "aws_apigatewayv2_deployment" "wfprev_deployment" { + api_id = aws_apigatewayv2_api.wfprev_api_gateway.id triggers = { redeployment = sha1(join(",",tolist([ - jsonencode(aws_apigatewayv2_integration.wfhr_vpc_integration), + jsonencode(aws_apigatewayv2_integration.wfprev_vpc_integration), jsonencode(aws_apigatewayv2_route.base_route), - jsonencode(aws_apigatewayv2_integration.wfhr_vpc_integration), - jsonencode(aws_apigatewayv2_vpc_link.wfhr_vpc_link) + jsonencode(aws_apigatewayv2_integration.wfprev_vpc_integration), + jsonencode(aws_apigatewayv2_vpc_link.wfprev_vpc_link) ]))) } lifecycle { diff --git a/terraform/ecs.tf b/terraform/ecs.tf index c0a82f5c7..fe995da75 100644 --- a/terraform/ecs.tf +++ b/terraform/ecs.tf @@ -40,37 +40,33 @@ resource "aws_ecs_task_definition" "wfprev_server" { volume { name = "temp" } - tags = local.common_tags container_definitions = jsonencode([{ essential = true readonlyRootFilesystem = true name = var.server_container_name image = var.server_image + repositoryCredentials = { + credentialsParameter = aws_secretsmanager_secret.githubCredentials.arn + } cpu = var.server_cpu_units memory = var.server_memory networkMode = "awsvpc" - portMappings = [{ + portMappings = [ + { protocol = "tcp" containerPort = var.server_port hostPort = var.server_port - }] + } + ] environment = [ { name = "LOGGING_LEVEL" value = var.logging_level }, - { - name = "DB_NAME" - value = aws_db_instance.wfprev_pgsqlDB.name - }, { name = "AWS_REGION" value = var.aws_region }, - { - name = "bucketName" - value = aws_s3_bucket.wfprev_upload_bucket.id - }, { name = "WEBADE_OAUTH2_CLIENT_ID" value = var.WEBADE_OAUTH2_REST_CLIENT_ID @@ -88,7 +84,7 @@ resource "aws_ecs_task_definition" "wfprev_server" { value = "jdbc:postgresql://${aws_db_instance.wfprev_pgsqlDB.endpoint}/${aws_db_instance.wfprev_pgsqlDB.name}" }, { - name = "WFNEWS_USERNAME" + name = "WFPREV_USERNAME" value = var.WFPREV_USERNAME }, { @@ -130,8 +126,94 @@ resource "aws_ecs_task_definition" "wfprev_server" { }]) } +# WFPrev Client Task Definition + +resource "aws_ecs_task_definition" "wfprev_client" { + family = "wfprev-client-task-${var.target_env}" + # execution_role_arn = aws_iam_role.wfprev_ecs_task_execution_role.arn + # task_role_arn = aws_iam_role.wfprev_app_container_role.arn + network_mode = "awsvpc" + requires_compatibilities = ["FARGATE"] + cpu = var.client_cpu_units + memory = var.client_memory + volume { + name = "work" + } + volume { + name = "logging" + } + container_definitions = jsonencode([ + { + essential = true + readonlyRootFilesystem = true + name = var.client_container_name + image = var.client_image + cpu = var.client_cpu_units + memory = var.client_memory + networkMode = "awsvpc" + portMappings = [ + { + protocol = "tcp" + containerPort = var.client_port + hostPort = var.client_port + } + ] + environment = [ + { + name = "LOGGING_LEVEL" + value = "${var.logging_level}" + }, + { + name = "AWS_REGION", + value = var.aws_region + }, + { + #Base URL will use the + name = "BASE_URL", + value = var.target_env == "prod" ? "https://${var.gov_client_url}/" : "https://${aws_route53_record.wfprev_client.name}/" + }, + { + name = "WEBADE_OAUTH2_WFPREV_REST_CLIENT_SECRET", + value = var.WEBADE_OAUTH2_WFPREV_UI_CLIENT_SECRET + }, + { + name = "WEBADE-OAUTH2_TOKEN_URL", + value = var.WEBADE-OAUTH2_TOKEN_URL + }, + { + name = "WEBADE-OAUTH2_CHECK_TOKEN_V2_URL" + value = var.WEBADE-OAUTH2_CHECK_TOKEN_URL + } + ] + logConfiguration = { + logDriver = "awslogs" + options = { + awslogs-create-group = "true" + awslogs-group = "/ecs/${var.client_name}" + awslogs-region = var.aws_region + awslogs-stream-prefix = "ecs" + } + } + mountPoints = [ + { + sourceVolume = "logging" + containerPath = "/usr/local/tomcat/logs" + readOnly = false + }, + { + sourceVolume = "work" + containerPath = "/usr/local/tomcat/work" + readOnly = false + } + ] + volumesFrom = [] + } + ]) +} + + # Placeholder for Other Task Definitions like Nginx, Liquibase, etc. -# For each additional component, create similar task definitions based on wfnews structure +# For each additional component, create similar task definitions based on wfprev structure ////////////////////////////// //// SERVICES //// @@ -165,7 +247,7 @@ resource "aws_ecs_service" "wfprev_server" { } load_balancer { - target_group_arn = aws_alb_target_group.wfprev_server.id + target_group_arn = aws_alb_target_group.wfprev_api.id container_name = var.server_container_name container_port = var.server_port } @@ -175,5 +257,45 @@ resource "aws_ecs_service" "wfprev_server" { # tags = local.common_tags } +# ECS Service for WFPrev Client + +resource "aws_ecs_service" "client" { + name = "wfprev-client-service-${var.target_env}" + cluster = aws_ecs_cluster.wfprev_main.id + task_definition = aws_ecs_task_definition.wfprev_client.arn + desired_count = var.app_count + enable_ecs_managed_tags = true + propagate_tags = "TASK_DEFINITION" + health_check_grace_period_seconds = 60 + wait_for_steady_state = false + + + capacity_provider_strategy { + capacity_provider = "FARGATE_SPOT" + weight = 80 + } + capacity_provider_strategy { + capacity_provider = "FARGATE" + weight = 20 + base = 1 + } + + + network_configuration { + security_groups = [aws_security_group.wfnews_ecs_tasks.id, data.aws_security_group.app.id] + subnets = module.network.aws_subnet_ids.app.ids + assign_public_ip = true + } + + load_balancer { + target_group_arn = aws_alb_target_group.wfprev_ui.id + container_name = var.client_container_name + container_port = var.client_port + } + + # depends_on = [aws_iam_role_policy_attachment.wfprev_ecs_task_execution_role] +} + + # Placeholder for other ECS Services like Nginx, Liquibase, etc. # Define similar ECS services for additional task definitions. diff --git a/terraform/iam.tf b/terraform/iam.tf index 60712f4c0..b0ace335c 100644 --- a/terraform/iam.tf +++ b/terraform/iam.tf @@ -106,6 +106,31 @@ resource "aws_iam_policy" "cloudfrontInvalidate" { EOF } +resource "aws_iam_role" "wfprev_app_container_role" { + name = "wfprev_app_container_role" + + assume_role_policy = <