diff --git a/.github/workflows/report-api-cd.yml b/.github/workflows/report-api-cd.yml new file mode 100644 index 00000000..b6652105 --- /dev/null +++ b/.github/workflows/report-api-cd.yml @@ -0,0 +1,34 @@ +name: Report-API CD GCP + +on: + push: + branches: + - main + paths: + - "report-api/**" + workflow_dispatch: + inputs: + target: + description: "Deploy To" + required: true + type: choice + options: + - dev + - test + - sandbox + - prod + +jobs: + report-api-cd: + permissions: + id-token: write + contents: write + + uses: bcgov/bcregistry-sre/.github/workflows/cloud-run-service-cd.yaml@main + with: + target: ${{ github.event.inputs.target }} # Corrected the input reference + app_name: "report-api" + working_directory: "./report-api" + secrets: + WORKLOAD_IDENTIFY_POOLS_PROVIDER: ${{ secrets.WORKLOAD_IDENTIFY_POOLS_PROVIDER }} + GCP_SERVICE_ACCOUNT: ${{ secrets.GCP_SERVICE_ACCOUNT }} diff --git a/.github/workflows/report-api-ci.yml b/.github/workflows/report-api-ci.yml new file mode 100644 index 00000000..0db985de --- /dev/null +++ b/.github/workflows/report-api-ci.yml @@ -0,0 +1,114 @@ +name: Report API CI + +on: + pull_request: + branches: + - main + paths: + - "report-api/**" + +defaults: + run: + shell: bash + working-directory: ./report-api + +jobs: + setup-job: + runs-on: ubuntu-20.04 + + if: github.repository == 'bcgov/bcros-common' + + steps: + - uses: actions/checkout@v4 + - run: "true" + + linting: + needs: setup-job + runs-on: ubuntu-20.04 + + strategy: + matrix: + python-version: [3.12] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + make setup + - name: Lint with pylint + id: pylint + run: | + make pylint + - name: Lint with flake8 + id: flake8 + run: | + make flake8 + + testing: + needs: setup-job + env: + FLASK_ENV: "testing" + JWT_OIDC_ISSUER: "http://localhost:8081/auth/realms/demo" + JWT_OIDC_WELL_KNOWN_CONFIG: "http://localhost:8081/auth/realms/demo/.well-known/openid-configuration" + JWT_OIDC_ALGORITHMS: "RS256" + JWT_OIDC_AUDIENCE: "sbc-auth-web" + JWT_OIDC_CLIENT_SECRET: "1111111111" + JWT_OIDC_JWKS_CACHE_TIMEOUT: "6000" + + runs-on: ubuntu-20.04 + + strategy: + matrix: + python-version: [3.12] + + services: + postgres: + image: postgres:12 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432:5432 + # needed because the postgres container does not provide a healthcheck + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + make setup + - name: Test with pytest + id: test + run: | + make test + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + file: ./report-api/coverage.xml + flags: reportapi + name: codecov-report-api + fail_ci_if_error: false + + build-check: + needs: setup-job + runs-on: ubuntu-20.04 + + strategy: + matrix: + python-version: [3.12] + + steps: + - uses: actions/checkout@v4 + - name: build to check strictness + id: build + run: | + make build-nc diff --git a/report-api/Dockerfile b/report-api/Dockerfile index 9cc892b8..95b3233a 100644 --- a/report-api/Dockerfile +++ b/report-api/Dockerfile @@ -23,9 +23,9 @@ RUN python3 -m pip install -r requirements.txt RUN python3 setup.py install -EXPOSE 5001 +EXPOSE 8080 ENV NUM_WORKERS=3 ENV TIMEOUT=360 -CMD gunicorn --bind 0.0.0.0:5001 --timeout $TIMEOUT --workers $NUM_WORKERS wsgi:application +CMD gunicorn --bind 0.0.0.0:8080 --timeout $TIMEOUT --workers $NUM_WORKERS wsgi:application diff --git a/report-api/config.py b/report-api/config.py index e06b7377..35aff99b 100755 --- a/report-api/config.py +++ b/report-api/config.py @@ -58,10 +58,8 @@ class _Config(): # pylint: disable=too-few-public-methods # JWT_OIDC Settings JWT_OIDC_WELL_KNOWN_CONFIG = os.getenv('JWT_OIDC_WELL_KNOWN_CONFIG') JWT_OIDC_ALGORITHMS = os.getenv('JWT_OIDC_ALGORITHMS') - JWT_OIDC_JWKS_URI = os.getenv('JWT_OIDC_JWKS_URI') JWT_OIDC_ISSUER = os.getenv('JWT_OIDC_ISSUER') JWT_OIDC_AUDIENCE = os.getenv('ACCOUNT_SERVICES_SERVICE_ACCOUNT_CLIENT_ID') - JWT_OIDC_CLIENT_SECRET = os.getenv('JWT_OIDC_CLIENT_SECRET') JWT_OIDC_CACHING_ENABLED = os.getenv('JWT_OIDC_CACHING_ENABLED') JWT_OIDC_JWKS_CACHE_TIMEOUT = int(os.getenv('JWT_OIDC_JWKS_CACHE_TIMEOUT', '300')) diff --git a/report-api/devops/gcp/clouddeploy-targets.yaml b/report-api/devops/gcp/clouddeploy-targets.yaml new file mode 100644 index 00000000..b4ad104f --- /dev/null +++ b/report-api/devops/gcp/clouddeploy-targets.yaml @@ -0,0 +1,106 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: deploy.cloud.google.com/v1 +kind: Target +metadata: + name: dev +description: Dev Environment +deployParameters: + deploy-env: "development" + deploy-project-id: "c4hnrd-dev" + service-name: "report-api-dev" + container-name: "report-api-dev" + cloudsql-instances: "" + app-env: "dev" + container-port: "8080" + service-account: "sa-api@c4hnrd-dev.iam.gserviceaccount.com" +run: + location: projects/c4hnrd-dev/locations/northamerica-northeast1 +executionConfigs: +- usages: [DEPLOY, RENDER] + artifactStorage: 'gs://c4hnrd-tools_clouddeploy/history' +--- + +apiVersion: deploy.cloud.google.com/v1 +kind: Target +metadata: + name: test +description: Test Environment +deployParameters: + deploy-env: "development" + deploy-project-id: "c4hnrd-test" + service-name: "report-api-test" + container-name: "report-api-test" + cloudsql-instances: "" + app-env: "test" + container-port: "8080" + service-account: "sa-api@c4hnrd-test.iam.gserviceaccount.com" +run: + location: projects/c4hnrd-test/locations/northamerica-northeast1 +executionConfigs: +- usages: [DEPLOY, RENDER] + artifactStorage: 'gs://c4hnrd-tools_clouddeploy/history' +--- + +apiVersion: deploy.cloud.google.com/v1 +kind: Target +metadata: + name: sandbox +description: Sandbox Environment +requireApproval: true +deployParameters: + deploy-env: "production" + deploy-project-id: "c4hnrd-tools" + service-name: "report-api-sandbox" + container-name: "report-api-sandbox" + cloudsql-instances: "" + app-env: "sandbox" + service-account: "sa-api@c4hnrd-tools.iam.gserviceaccount.com" + max-scale: "50" + container-concurrency: "20" + container-port: "8080" + resources-cpu: 4000m + resources-memory: 8Gi +run: + location: projects/c4hnrd-tools/locations/northamerica-northeast1 +executionConfigs: +- usages: [DEPLOY, RENDER] + artifactStorage: 'gs://c4hnrd-tools_clouddeploy/history' +--- + +apiVersion: deploy.cloud.google.com/v1 +kind: Target +metadata: + name: prod +description: Production Environment +requireApproval: true +deployParameters: + deploy-env: "production" + deploy-project-id: "c4hnrd-prod" + service-name: "report-api-prod" + container-name: "report-api-prod" + cloudsql-instances: "" + app-env: "production" + service-account: "sa-api@c4hnrd-prod.iam.gserviceaccount.com" + max-scale: "50" + container-concurrency: "20" + container-port: "8080" + resources-cpu: 4000m + resources-memory: 8Gi +run: + location: projects/c4hnrd-prod/locations/northamerica-northeast1 +executionConfigs: +- usages: [DEPLOY, RENDER] + artifactStorage: 'gs://c4hnrd-tools_clouddeploy/history' \ No newline at end of file diff --git a/report-api/devops/helm/Readme.md b/report-api/devops/helm/Readme.md deleted file mode 100644 index e2e3087e..00000000 --- a/report-api/devops/helm/Readme.md +++ /dev/null @@ -1,31 +0,0 @@ -helm repo list - -helm repo update - -helm search repo - -## Report API -helm install report-api bcregistry/bcregistry-api -f values.dev.yaml --namespace d893f6-dev - -helm install report-api bcregistry/bcregistry-api -f values.test.yaml --namespace d893f6-test - -helm install report-api bcregistry/bcregistry-api -f values.prod.yaml --namespace d893f6-prod - -helm upgrade report-api bcregistry/bcregistry-api -f values.dev.yaml --namespace d893f6-dev - -helm upgrade report-api bcregistry/bcregistry-api -f values.test.yaml --namespace d893f6-test - -helm upgrade report-api bcregistry/bcregistry-api -f values.prod.yaml --namespace d893f6-prod - -## PPR Report API -helm install ppr-report-api bcregistry/bcregistry-api -f values.dev.yaml --namespace 1dfe78-dev --set image.namespace=1dfe78-tools - -helm install ppr-report-api bcregistry/bcregistry-api -f values.test.yaml --namespace 1dfe78-test --set image.namespace=1dfe78-tools - -helm install ppr-report-api bcregistry/bcregistry-api -f values.prod.yaml --namespace 1dfe78-prod --set image.namespace=1dfe78-tools - -helm upgrade ppr-report-api bcregistry/bcregistry-api -f values.dev.yaml --namespace 1dfe78-dev --set image.namespace=1dfe78-tools - -helm upgrade ppr-report-api bcregistry/bcregistry-api -f values.test.yaml --namespace 1dfe78-test --set image.namespace=1dfe78-tools - -helm upgrade ppr-report-api bcregistry/bcregistry-api -f values.prod.yaml --namespace 1dfe78-prod --set image.namespace=1dfe78-tools \ No newline at end of file diff --git a/report-api/devops/helm/values.dev.yaml b/report-api/devops/helm/values.dev.yaml deleted file mode 100644 index 94e7b3fb..00000000 --- a/report-api/devops/helm/values.dev.yaml +++ /dev/null @@ -1,113 +0,0 @@ -# Default values for bcregistry-api. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -environment: "dev" -role: "api" - -image: - repository: "image-registry.openshift-image-registry.svc:5000" - namespace: "d893f6-tools" - pullPolicy: "Always" - pullSecrets: "" - digest: "" - tag: "dev" - -migrations: - enabled: false - -ports: - containerPort: 5001 - protocol: TCP - -resources: - limits: - cpu: 1250m - memory: 3584Mi - requests: - cpu: 100m - memory: 100Mi - -replicas: 1 - -revisionHistoryLimit: 10 - -livenessProbe: - httpGet: - path: /ops/healthz - port: 5001 - scheme: HTTP - initialDelaySeconds: 3 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - -readinessProbe: - httpGet: - path: /ops/readyz - port: 5001 - scheme: HTTP - initialDelaySeconds: 3 - timeoutSeconds: 30 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - -podAnnotations: {} - -podSecurityContext: {} - -securityContext: {} - -args: {} - -env: - {} - # SOME_ENV_VAR: - # value: "var2" - # secure: false - # SOME_SEC_ENV_VAR: - # value: "var" - # secure: true - -envFrom: - secretRef: true - configMapRef: false - -service: - type: ClusterIP - port: 8080 - targetPort: 5001 - protocol: TCP - -route: - create: true - annotations: - {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - # haproxy.router.openshift.io/ip_whitelist: '' - # haproxy.router.openshift.io/timeout: 900s - routerCanonicalHostname: apps.silver.devops.gov.bc.ca - path: "" - service: {} - wildcardPolicy: None - tls: {} - -autoscaling: - # Specifies whether the autoscaling should be created - create: true - minReplicas: 1 - maxReplicas: 1 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - -serviceAccount: - # Specifies whether a service account should be created - create: false - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" diff --git a/report-api/devops/helm/values.prod.yaml b/report-api/devops/helm/values.prod.yaml deleted file mode 100644 index c5c88b6a..00000000 --- a/report-api/devops/helm/values.prod.yaml +++ /dev/null @@ -1,113 +0,0 @@ -# Default values for bcregistry-api. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -environment: "prod" -role: "api" - -image: - repository: "image-registry.openshift-image-registry.svc:5000" - namespace: "d893f6-tools" - pullPolicy: "Always" - pullSecrets: "" - digest: "" - tag: "prod" - -migrations: - enabled: false - -ports: - containerPort: 5001 - protocol: TCP - -resources: - limits: - cpu: 1250m - memory: 3584Mi - requests: - cpu: 100m - memory: 100Mi - -replicas: 1 - -revisionHistoryLimit: 10 - -livenessProbe: - httpGet: - path: /ops/healthz - port: 5001 - scheme: HTTP - initialDelaySeconds: 3 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - -readinessProbe: - httpGet: - path: /ops/readyz - port: 5001 - scheme: HTTP - initialDelaySeconds: 3 - timeoutSeconds: 30 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - -podAnnotations: {} - -podSecurityContext: {} - -securityContext: {} - -args: {} - -env: - {} - # SOME_ENV_VAR: - # value: "var2" - # secure: false - # SOME_SEC_ENV_VAR: - # value: "var" - # secure: true - -envFrom: - secretRef: true - configMapRef: false - -service: - type: ClusterIP - port: 8080 - targetPort: 5001 - protocol: TCP - -route: - create: true - annotations: - {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - # haproxy.router.openshift.io/ip_whitelist: '' - # haproxy.router.openshift.io/timeout: 900s - routerCanonicalHostname: apps.silver.devops.gov.bc.ca - path: "" - service: {} - wildcardPolicy: None - tls: {} - -autoscaling: - # Specifies whether the autoscaling should be created - create: true - minReplicas: 2 - maxReplicas: 3 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - -serviceAccount: - # Specifies whether a service account should be created - create: false - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" diff --git a/report-api/devops/helm/values.test.yaml b/report-api/devops/helm/values.test.yaml deleted file mode 100644 index 75cf80a9..00000000 --- a/report-api/devops/helm/values.test.yaml +++ /dev/null @@ -1,113 +0,0 @@ -# Default values for bcregistry-api. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -environment: "test" -role: "api" - -image: - repository: "image-registry.openshift-image-registry.svc:5000" - namespace: "d893f6-tools" - pullPolicy: "Always" - pullSecrets: "" - digest: "" - tag: "test" - -migrations: - enabled: false - -ports: - containerPort: 5001 - protocol: TCP - -resources: - limits: - cpu: 1250m - memory: 3584Mi - requests: - cpu: 100m - memory: 100Mi - -replicas: 1 - -revisionHistoryLimit: 10 - -livenessProbe: - httpGet: - path: /ops/healthz - port: 5001 - scheme: HTTP - initialDelaySeconds: 3 - timeoutSeconds: 1 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - -readinessProbe: - httpGet: - path: /ops/readyz - port: 5001 - scheme: HTTP - initialDelaySeconds: 3 - timeoutSeconds: 30 - periodSeconds: 10 - successThreshold: 1 - failureThreshold: 3 - -podAnnotations: {} - -podSecurityContext: {} - -securityContext: {} - -args: {} - -env: - {} - # SOME_ENV_VAR: - # value: "var2" - # secure: false - # SOME_SEC_ENV_VAR: - # value: "var" - # secure: true - -envFrom: - secretRef: true - configMapRef: false - -service: - type: ClusterIP - port: 8080 - targetPort: 5001 - protocol: TCP - -route: - create: true - annotations: - {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - # haproxy.router.openshift.io/ip_whitelist: '' - # haproxy.router.openshift.io/timeout: 900s - routerCanonicalHostname: apps.silver.devops.gov.bc.ca - path: "" - service: {} - wildcardPolicy: None - tls: {} - -autoscaling: - # Specifies whether the autoscaling should be created - create: true - minReplicas: 1 - maxReplicas: 1 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - -serviceAccount: - # Specifies whether a service account should be created - create: false - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" diff --git a/report-api/devops/vaults.gcp.env b/report-api/devops/vaults.gcp.env new file mode 100644 index 00000000..ed4c3393 --- /dev/null +++ b/report-api/devops/vaults.gcp.env @@ -0,0 +1,8 @@ +JWT_OIDC_WELL_KNOWN_CONFIG="op://keycloak/$APP_ENV/jwt-base/JWT_OIDC_WELL_KNOWN_CONFIG" +JWT_OIDC_ALGORITHMS="op://keycloak/$APP_ENV/jwt-base/JWT_OIDC_ALGORITHMS" +JWT_OIDC_ISSUER="op://keycloak/$APP_ENV/jwt-base/JWT_OIDC_ISSUER" +JWT_OIDC_CACHING_ENABLED="op://keycloak/$APP_ENV/jwt-base/JWT_OIDC_CACHING_ENABLED" +JWT_OIDC_JWKS_CACHE_TIMEOUT="op://keycloak/$APP_ENV/jwt-base/JWT_OIDC_JWKS_CACHE_TIMEOUT" +ACCOUNT_SERVICES_SERVICE_ACCOUNT_CLIENT_ID="op://keycloak/$APP_ENV/account-services-account/ACCOUNT_SERVICES_SERVICE_ACCOUNT_CLIENT_ID" +SENTRY_DSN="op://sentry/$APP_ENV/relationship-api/SENTRY_DSN" +SENTRY_ENABLE="op://sentry/$APP_ENV/relationship-api/SENTRY_ENABLE" \ No newline at end of file