diff --git a/.github/ct.yaml b/.github/ct.yaml new file mode 100644 index 00000000..531244f4 --- /dev/null +++ b/.github/ct.yaml @@ -0,0 +1,10 @@ +remote: origin +target-branch: master +chart-dirs: + - helm +chart-repos: + - bitnami=https://charts.bitnami.com/bitnami +helm-extra-args: --timeout 600s +check-version-increment: true +debug: false +validate-maintainers: false \ No newline at end of file diff --git a/.github/workflows/lint_test.yaml b/.github/workflows/lint_test.yaml new file mode 100644 index 00000000..1ca99744 --- /dev/null +++ b/.github/workflows/lint_test.yaml @@ -0,0 +1,50 @@ +name: Lint and Test Charts + +on: pull_request + +jobs: + lint-test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set up Helm + uses: azure/setup-helm@v3 + with: + version: v3.10.0 + + - uses: actions/setup-python@v4 + with: + python-version: '3.9' + check-latest: true + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2.3.1 + + - name: Run chart-testing (list-changed) + id: list-changed + run: | + changed=$(ct list-changed --config .github/ct.yaml) + if [[ -n "$changed" ]]; then + echo "::set-output name=changed::true" + fi + + - name: Run chart-testing (lint) + run: ct lint --config .github/ct.yaml + + # deploy-charts-to-kind: + # name: ${{ matrix.environments }} - gen3 data portal build + # timeout-minutes: 20 + # runs-on: ubuntu-latest + # needs: [get-changes-for-envs] + # if: ${{ needs.get-changes-for-envs.outputs.matrix != '[]' && needs.get-changes-for-envs.outputs.matrix != '' }} + # steps: + # - name: Create kind cluster + # uses: helm/kind-action@v1.4.0 + # if: steps.list-changed.outputs.changed == 'true' + + # - name: Run chart-testing (install) + # run: ct install diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 361bedc1..bc0e8a18 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -4,6 +4,8 @@ on: push: branches: - master +env: + HELM_DOCS_VERSION: "1.7.0" jobs: release: @@ -20,13 +22,21 @@ jobs: run: | git config user.name "$GITHUB_ACTOR" git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + - name: Install Helm - uses: azure/setup-helm@v1 + uses: azure/setup-helm@v3 with: - version: v3.8.1 + version: v3.10.0 + + - name: Install Helm-docs + run: | + cd /tmp + wget https://github.com/norwoodj/helm-docs/releases/download/v${{env.HELM_DOCS_VERSION}}/helm-docs_${{env.HELM_DOCS_VERSION}}_Linux_x86_64.tar.gz + tar -xvf helm-docs_${{env.HELM_DOCS_VERSION}}_Linux_x86_64.tar.gz + sudo mv helm-docs /usr/local/sbin - name: Run chart-releaser - uses: helm/chart-releaser-action@v1.4.0 + uses: helm/chart-releaser-action@v1.4.1 with: charts_dir: helm env: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 195d4659..51a19a00 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,3 +9,18 @@ repos: hooks: - id: no-commit-to-branch args: [--branch, develop, --branch, master, --pattern, release/.*] + + # - repo: https://github.com/gruntwork-io/pre-commit + # rev: v0.1.17 # Get the latest from: https://github.com/gruntwork-io/pre-commit/releases + # hooks: + # - id: helmlint + + - repo: local + hooks: + - id: helm-docs + args: [] + description: Uses 'helm-docs' to create documentation from the Helm chart's 'values.yaml' file, and inserts the result into a corresponding 'README.md' file. + entry: git-hook/helm-docs.sh + language: script + name: Helm Docs + require_serial: true \ No newline at end of file diff --git a/.secrets.baseline b/.secrets.baseline index 453d0398..71f27075 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$", "lines": null }, - "generated_at": "2022-10-25T14:38:38Z", + "generated_at": "2022-12-08T17:27:52Z", "plugins_used": [ { "name": "AWSKeyDetector" @@ -58,81 +58,44 @@ } ], "results": { - "helm/audit/templates/secrets.yaml": [ + "README.md": [ { - "hashed_secret": "57d8659e51a2da40fda65f6a4cc294cc3f59cf6d", + "hashed_secret": "ac0fedaac180de6bd70a97b711692a92dade479e", "is_secret": false, "is_verified": false, - "line_number": 25, + "line_number": 80, "type": "Secret Keyword" - } - ], - "helm/common/templates/_db_setup_job.tpl": [ + }, { - "hashed_secret": "d2e2ab0f407e4ee3cf2ab87d61c31b25a74085e5", + "hashed_secret": "64ab0c1d3edc1c8c166351207b840ac7b2a90523", "is_secret": false, "is_verified": false, - "line_number": 85, + "line_number": 109, "type": "Secret Keyword" } ], - "helm/common/templates/_postgres_secrets.tpl": [ + "docs/databases.md": [ { - "hashed_secret": "07b87392697bbdd9d97f6cd887f901820a0150df", - "is_secret": false, - "is_verified": false, - "line_number": 27, - "type": "Secret Keyword" - }, - { - "hashed_secret": "e343239977fa87adac52528619fc6bf2e1a82ee7", + "hashed_secret": "ac0fedaac180de6bd70a97b711692a92dade479e", "is_secret": false, "is_verified": false, - "line_number": 55, - "type": "Secret Keyword" - }, - { - "hashed_secret": "d2e2ab0f407e4ee3cf2ab87d61c31b25a74085e5", - "is_secret": false, - "is_verified": false, - "line_number": 92, + "line_number": 22, "type": "Secret Keyword" } ], - "helm/common/templates/_secrets.tpl": [ - { - "hashed_secret": "e540cdd1328b2b21e29a95405c301b9313b7c346", - "is_secret": false, - "is_verified": false, - "line_number": 96, - "type": "Secret Keyword" - }, - { - "hashed_secret": "67caac52553e052426982b6f096e73318b151765", - "is_secret": false, - "is_verified": false, - "line_number": 115, - "type": "Secret Keyword" - }, - { - "hashed_secret": "17849dced8de4397e88a8b1c746477aead486a2b", - "is_secret": false, - "is_verified": false, - "line_number": 116, - "type": "Secret Keyword" - }, + "helm/common/templates/_postgres_secrets.tpl": [ { - "hashed_secret": "df39b4caf493869772ff3a0f95cca6a9ae7934dc", + "hashed_secret": "07b87392697bbdd9d97f6cd887f901820a0150df", "is_secret": false, "is_verified": false, - "line_number": 117, + "line_number": 34, "type": "Secret Keyword" }, { - "hashed_secret": "07b87392697bbdd9d97f6cd887f901820a0150df", + "hashed_secret": "e343239977fa87adac52528619fc6bf2e1a82ee7", "is_secret": false, "is_verified": false, - "line_number": 119, + "line_number": 62, "type": "Secret Keyword" } ], @@ -141,7 +104,7 @@ "hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3", "is_secret": false, "is_verified": false, - "line_number": 69, + "line_number": 65, "type": "Secret Keyword" } ], @@ -205,34 +168,34 @@ "hashed_secret": "5d07e1b80e448a213b392049888111e1779a52db", "is_secret": false, "is_verified": false, - "line_number": 870, + "line_number": 1796, "type": "Secret Keyword" } ], - "helm/hatchery/templates/hatchery-manifest.yaml": [ + "helm/hatchery/README.md": [ { - "hashed_secret": "0da0e0005ca04acb407af2681d0bede6d9406039", + "hashed_secret": "1740c48fa3141d4851b14f97e3bc0f46f7670672", "is_secret": false, "is_verified": false, - "line_number": 147, + "line_number": 45, "type": "Secret Keyword" } ], - "helm/indexd/indexd-secret/config_helper.py": [ + "helm/hatchery/values.yaml": [ { - "hashed_secret": "bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f", + "hashed_secret": "9b5925ea817163740dfb287a9894e8ab3aba2c18", "is_secret": false, "is_verified": false, - "line_number": 66, - "type": "Basic Auth Credentials" + "line_number": 128, + "type": "Secret Keyword" } ], - "helm/indexd/indexd-secret/local_settings.py": [ + "helm/indexd/indexd-settings/local_settings.py": [ { "hashed_secret": "0a0d18c85e096611b5685b62bc60ec534d19bacc", "is_secret": false, "is_verified": false, - "line_number": 59, + "line_number": 60, "type": "Basic Auth Credentials" } ], @@ -241,7 +204,7 @@ "hashed_secret": "c2dae5a3c7ce218639b38d8a0256f02fe81d439e", "is_secret": false, "is_verified": false, - "line_number": 25, + "line_number": 19, "type": "Secret Keyword" } ], @@ -304,7 +267,7 @@ "hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3", "is_secret": false, "is_verified": false, - "line_number": 150, + "line_number": 168, "type": "Secret Keyword" } ], @@ -322,16 +285,7 @@ "hashed_secret": "13d9ed7e3d69f1b6330dff80bc4658931708eddc", "is_secret": false, "is_verified": false, - "line_number": 153, - "type": "Secret Keyword" - } - ], - "helm/wts/templates/secret.yaml": [ - { - "hashed_secret": "d2e2ab0f407e4ee3cf2ab87d61c31b25a74085e5", - "is_secret": false, - "is_verified": false, - "line_number": 29, + "line_number": 108, "type": "Secret Keyword" } ] diff --git a/README.md b/README.md index bfd2b237..6cfe26c5 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ -![gen3-log](docs/images/gen3-blue-dark.png) # gen3-helm -Helm charts for deploying Gen3 services to a kubernetes cluster. + +Helm charts for deploying [Gen3](https://gen3.org) on any kubernetes cluster. + # Deployment instructions +For a full set of configuration options see the [README.md for gen3](./helm/gen3/README.md) ## TL;DR ``` @@ -12,68 +14,47 @@ helm repo add gen3 http://helm.gen3.org helm upgrade --install gen3 gen3/gen3 -f ./values.yaml ``` -Use the following as a template for your `values.yaml` file +Use the following as a template for your `values.yaml` file for a minimum deployment of gen3 using these helm charts. + -You can set the postgres passwords to be what you want, if you leave them blank, they will be autogenerated for you. ``` global: - hostname: localhost - postgres: - host: postgres-postgresql.postgres.svc.cluster.local - master: - username: postgres - password: - port: 5432 - -arborist: - postgres: - password: test - -audit: - postgres: - password: test + hostname: example-commons.com fence: - postgres: - password: test FENCE_CONFIG: OPENID_CONNECT: google: - client_id: "" - client_secret: "" + client_id: "insert.google.client_id.here" + client_secret: "insert.google.client_secret.here" +``` -indexd: - postgres: - password: test +This is to have a gen3 deployment with google login. You may also use MOCK_AUTH using the following config. NB! This will bypass any login and is only recommended for testing environments -manifestservice: - postgres: - password: test -metadata: - postgres: - password: test +``` +global: + hostname: example-commons.com -peregrine: - postgres: - password: test +fence: + FENCE_CONFIG: + # if true, will automatically login a user with username "test" + # WARNING: DO NOT ENABLE IN PRODUCTION (for testing purposes only) + MOCK_AUTH: true +``` -pidgin: - postgres: - password: test -requestor: - postgres: - password: test +## Selective deployments +All service helm charts are sub-charts of the gen3 chart (which acts as an umbrella chart) +To enable or disable a service you can add this pattern to your values.yaml -sheepdog: - postgres: - password: test +``` +fence: + enable: true wts: - postgres: - password: test + enable: false ``` @@ -85,21 +66,51 @@ Any kubernetes cluster _should_ work. We are testing with EKS, AKS, GKE and Ranc It is suggested to use [Rancher Desktop](https://rancherdesktop.io/) as Kubernetes on your laptop, especially on M1 Mac's. You also get ingress and other benefits out of the box. ### Postgres -We need a postgres database. For development clusters you can deploy the postgres helm chart using the following commands: +We need a postgres database. For development/CI clusters an instance of postgres is deployed and automatically configured for you. + +For production environments please fill out these values and provide a master password for postgres ``` -helm repo add bitnami https://charts.bitnami.com/bitnami -helm install postgres bitnami/postgresql -n postgres --create-namespace +global: + postgres: + db_create: true + master: + host: insert.postgres.hostname.here + username: postgres + password: + port: "5432" ``` -This will setup a postgres instance in a namespace called `postgres` - -For production installations use a managed postgres service. - ### Login Options Gen3 does not have any IDP, but can integrate with many. We will cover Google login here, but refer to the fence documentation for additional options. -#### Google login + +TL/DR: At minimum to have google logins working you need to set these settings in your `values.yaml` file + +``` +global: + aws: + # If you're deploying to an EKS set this to true. This will annotate ingress/service accounts appropriately. + # In the future we will be adding support for GKE/AKS using same method. + enabled: true + aws_access_key_id: + aws_secret_access_key: + postgres: + master: + host: "rds.host.com" + username: "postgres" + password: "test" + port: "5432" +fence: + FENCE_CONFIG: + OPENID_CONNECT: + google: + client_id: "insert.google.client_id.here" + client_secret: "insert.google.client_secret.here" +``` + + +#### Google login generation You need to set up a google credential for google login as that's the default enabled option in fence. @@ -113,12 +124,13 @@ Click Create credentials > OAuth client ID. Select the Web application application type. Name your OAuth 2.0 client and click Create. -For `Authorized Javascript Origins` add `https://localhost` +For `Authorized Javascript Origins` add `https://` -For `"Authorized redirect URIs"` add `https://localhost/user/login/google/login/` +For `"Authorized redirect URIs"` add `https:///user/login/google/login/` After configuration is complete, take note of the client ID that was created. You will need the client ID and client secret to complete the next steps. +# Production deployments +For production deployments you have to use an external postgres server and elasticsearch server. -# Production Deployment -These helm charts are not yet ready for production, but check back again soon. +NOTE: Gen3 helm charts are currently not used in production by CTDS, but we are aiming to do that soon and will have additional documentation on that. \ No newline at end of file diff --git a/docs/databases.md b/docs/databases.md new file mode 100644 index 00000000..47d784cb --- /dev/null +++ b/docs/databases.md @@ -0,0 +1,47 @@ +# Databases in gen3 helm charts +This document will describe how databases are provisioned in gen3 when deploying with helm charts + +## Database credentials +The detault behaviour of gen3 helm charts is to auto-generate database credentials and save them as kubernetes secrets. + +Each service then consumes this same secret and mounts them as ENV vars to access databases. + +You can override this default behaviour by providing postgres credentials through Values.yaml files. + +If you are deploying a dev/CI environment, a postgres server is deployed alongside gen3, and that is used to hold databases for testing. + +For production deployments you need to provide the master credentials for a postgres server through these values. + +``` +global: + postgres: + db_create: true + master: + host: insert.postgres.hostname.here + username: postgres + password: + port: "5432" + +``` + +These values will then be used to provision databases for the environment. + +## Automatic database creation through jobs +When deploying gen3 helm charts you need to specifiy a postgres server. For dev/CI environments an installation of postgres is included, and is not intended for use in production. + +We hihgly recommend the use of a managed postgres service such as RDS when deploying gen3 to cloud environments. + +The dev/ci postgres is deployed using this helm chart https://bitnami.com/stack/postgresql/helm + +If you set the `global.postgres.db_create` value to true, then a job is kicked off for each service that relies on postgres to provision databases. + +This will kick off a [database creation job](../helm/common/templates/_db_setup_job.tpl) + + + + +## Database restoration. +There is a job to restore dummy data for Postgres and Elasticsearch to speed up setting up ephemeral enviornments for testing purposes, and to avoid running expensive ETL jobs in CI to have a fully featured gen3 environment + +In the future this job may be used to set up fully tested production environments, negating the need to run ETL in production, and have all your databases tested before doing a data-release. + diff --git a/git-hook/helm-docs.sh b/git-hook/helm-docs.sh new file mode 100755 index 00000000..6d7fc4c7 --- /dev/null +++ b/git-hook/helm-docs.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -e + +if ! command -v helm-docs > /dev/null 2>&1; then + echo "Please install helm-docs to run the pre-commit hook! https://github.com/norwoodj/helm-docs#installation" + exit 1 +fi + +helm-docs "${@}" \ No newline at end of file diff --git a/helm/ambassador/Chart.yaml b/helm/ambassador/Chart.yaml index 65b0542d..0628ebcb 100644 --- a/helm/ambassador/Chart.yaml +++ b/helm/ambassador/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/ambassador/README.md b/helm/ambassador/README.md new file mode 100644 index 00000000..8ce49390 --- /dev/null +++ b/helm/ambassador/README.md @@ -0,0 +1,50 @@ +# ambassador + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.4.2](https://img.shields.io/badge/AppVersion-1.4.2-informational?style=flat-square) + +A Helm chart for deploying ambassador for gen3 + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `10` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `60` | | +| fullnameOverride | string | `"ambassador-deployment"` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/datawire/ambassador"` | | +| image.tag | string | `"1.4.2"` | | +| imagePullSecrets | list | `[]` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations."consul.hashicorp.com/connect-inject" | string | `"false"` | | +| podAnnotations."prometheus.io/path" | string | `"/metrics"` | | +| podAnnotations."prometheus.io/port" | string | `"8877"` | | +| podAnnotations."prometheus.io/scrape" | string | `"true"` | | +| podAnnotations."sidecar.istio.io/inject" | string | `"false"` | | +| podLabels.app | string | `"ambassador"` | | +| podLabels.netnolimit | string | `"yes"` | | +| podLabels.public | string | `"yes"` | | +| podLabels.service | string | `"ambassador"` | | +| podLabels.userhelper | string | `"yes"` | | +| podSecurityContext.runAsUser | int | `8888` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | string | `"500m"` | | +| resources.limits.memory | string | `"400Mi"` | | +| resources.requests.cpu | string | `"100m"` | | +| resources.requests.memory | string | `"100Mi"` | | +| securityContext | object | `{}` | | +| selectorLabels.service | string | `"ambassador"` | | +| service.port | int | `8877` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| tolerations | list | `[]` | | +| userNamespace | string | `"jupyter-pods"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/ambassador/templates/service.yaml b/helm/ambassador/templates/service.yaml index d5ac2776..082ddbfd 100644 --- a/helm/ambassador/templates/service.yaml +++ b/helm/ambassador/templates/service.yaml @@ -1,17 +1,15 @@ -# TODO: evaluate if we need this apiVersion: v1 kind: Service metadata: - name: {{ .Values.rbac.rbacServiceName }} + name: ambassador-admin labels: - service: {{ .Values.rbac.rbacServiceName }} + service: ambassador-admin spec: - type: {{ .Values.service.type }} + type: ClusterIP ports: - - name: {{ .Values.rbac.rbacServiceName }} - port: {{ .Values.rbac.servicePort }} - targetPort: {{ .Values.rbac.servicePort }} - nodePort: null + - name: ambassador-admin + port: 8877 + targetPort: 8877 selector: {{- include "ambassador.selectorLabels" . | nindent 4 }} --- diff --git a/helm/ambassador/templates/serviceaccount.yaml b/helm/ambassador/templates/serviceaccount.yaml index 7748a61e..d1ae1a61 100644 --- a/helm/ambassador/templates/serviceaccount.yaml +++ b/helm/ambassador/templates/serviceaccount.yaml @@ -2,7 +2,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: ambassador + name: {{ include "ambassador.fullname" . }} rules: - apiGroups: [""] resources: @@ -25,7 +25,7 @@ metadata: roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: ambassador + name: {{ include "ambassador.fullname" . }} subjects: - kind: ServiceAccount name: ambassador diff --git a/helm/ambassador/values.yaml b/helm/ambassador/values.yaml index 950205dc..155f2995 100644 --- a/helm/ambassador/values.yaml +++ b/helm/ambassador/values.yaml @@ -59,7 +59,7 @@ selectorLabels: userNamespace: "jupyter-pods" -resources: +resources: limits: cpu: 500m memory: 400Mi @@ -79,7 +79,3 @@ nodeSelector: {} tolerations: [] affinity: {} - -rbac: - rbacServiceName: ambassador-admin - servicePort: 8877 \ No newline at end of file diff --git a/helm/arborist/Chart.lock b/helm/arborist/Chart.lock index 52a7fd5c..c601b9eb 100644 --- a/helm/arborist/Chart.lock +++ b/helm/arborist/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: common repository: file://../common - version: 0.0.1 -digest: sha256:a25c79b74ec6d89ca5c732e4222f8726ed02aa6a4a21f376afc499e53696c9b5 -generated: "2022-10-20T21:34:32.587406-05:00" + version: 0.1.0 +digest: sha256:636a65e9846bdff17cc4e65b0849061f783759a37aa51fb85ff6fd8ba5e68467 +generated: "2022-12-07T10:38:58.713724+01:00" diff --git a/helm/arborist/Chart.yaml b/helm/arborist/Chart.yaml index b875d331..4e91e1c2 100644 --- a/helm/arborist/Chart.yaml +++ b/helm/arborist/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,5 @@ appVersion: "2022.10" dependencies: - name: common - version: 0.0.1 - repository: file://../common \ No newline at end of file + version: 0.1.0 + repository: file://../common diff --git a/helm/arborist/README.md b/helm/arborist/README.md new file mode 100644 index 00000000..886d7fe8 --- /dev/null +++ b/helm/arborist/README.md @@ -0,0 +1,95 @@ +# arborist + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 arborist + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../common | common | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| env[0].name | string | `"JWKS_ENDPOINT"` | | +| env[0].value | string | `"http://fence-service/.well-known/jwks"` | | +| env[1].name | string | `"PGPASSWORD"` | | +| env[1].valueFrom.secretKeyRef.key | string | `"password"` | | +| env[1].valueFrom.secretKeyRef.name | string | `"arborist-dbcreds"` | | +| env[1].valueFrom.secretKeyRef.optional | bool | `false` | | +| env[2].name | string | `"PGUSER"` | | +| env[2].valueFrom.secretKeyRef.key | string | `"username"` | | +| env[2].valueFrom.secretKeyRef.name | string | `"arborist-dbcreds"` | | +| env[2].valueFrom.secretKeyRef.optional | bool | `false` | | +| env[3].name | string | `"PGDATABASE"` | | +| env[3].valueFrom.secretKeyRef.key | string | `"database"` | | +| env[3].valueFrom.secretKeyRef.name | string | `"arborist-dbcreds"` | | +| env[3].valueFrom.secretKeyRef.optional | bool | `false` | | +| env[4].name | string | `"PGHOST"` | | +| env[4].valueFrom.secretKeyRef.key | string | `"host"` | | +| env[4].valueFrom.secretKeyRef.name | string | `"arborist-dbcreds"` | | +| env[4].valueFrom.secretKeyRef.optional | bool | `false` | | +| env[5].name | string | `"PGPORT"` | | +| env[5].valueFrom.secretKeyRef.key | string | `"port"` | | +| env[5].valueFrom.secretKeyRef.name | string | `"arborist-dbcreds"` | | +| env[5].valueFrom.secretKeyRef.optional | bool | `false` | | +| env[6].name | string | `"PGSSLMODE"` | | +| env[6].value | string | `"disable"` | | +| fullnameOverride | string | `""` | | +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"quay.io/cdis/arborist"` | | +| image.tag | string | `""` | | +| imagePullSecrets | list | `[]` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | | +| podSecurityContext | object | `{}` | | +| postgres.database | string | `"arborist"` | | +| postgres.db_create | string | `nil` | | +| postgres.host | string | `nil` | | +| postgres.password | string | `nil` | | +| postgres.port | string | `"5432"` | | +| postgres.username | string | `"arborist"` | | +| replicaCount | int | `1` | | +| resources | object | `{}` | | +| securityContext | object | `{}` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| tolerations | list | `[]` | | +| volumeMounts | string | `nil` | | +| volumes[0].name | string | `"creds-volume"` | | +| volumes[0].secret.secretName | string | `"arborist-dbcreds"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/arborist/templates/db-init.yaml b/helm/arborist/templates/db-init.yaml index e53cb144..02dc09b9 100644 --- a/helm/arborist/templates/db-init.yaml +++ b/helm/arborist/templates/db-init.yaml @@ -1,3 +1,4 @@ -{{- include "common.db-setup-job" . }} --- -{{- include "common.db-secret" . }} +{{ include "common.db-setup-job" . }} +--- +{{ include "common.db-secret" . }} diff --git a/helm/arborist/templates/deployment.yaml b/helm/arborist/templates/deployment.yaml index 26dfb3c5..59ed15e3 100644 --- a/helm/arborist/templates/deployment.yaml +++ b/helm/arborist/templates/deployment.yaml @@ -58,6 +58,7 @@ spec: args: - "-c" - | + set -e # set env vars export PGSSLMODE="disable" diff --git a/helm/arborist/values.yaml b/helm/arborist/values.yaml index f2314f8e..d4d71413 100644 --- a/helm/arborist/values.yaml +++ b/helm/arborist/values.yaml @@ -2,22 +2,38 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. global: + dev: true postgres: - host: postgres-postgresql.postgres.svc.cluster.local + db_create: true master: + host: username: postgres - password: - port: 5432 + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false -db_create: true postgres: - host: - # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you + db_create: + host: + # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you database: arborist username: arborist - port: 5432 + port: "5432" # If left empty password will be auto-generated - password: + password: replicaCount: 1 @@ -91,10 +107,10 @@ volumes: volumeMounts: -# TODO: REMOVE? +# TODO: REMOVE? env: -# TODO: Revisit this? +# TODO: Revisit this? - name: JWKS_ENDPOINT value: "http://fence-service/.well-known/jwks" - name: PGPASSWORD @@ -129,4 +145,3 @@ env: optional: false - name: PGSSLMODE value: disable - diff --git a/helm/argo-wrapper/Chart.yaml b/helm/argo-wrapper/Chart.yaml index 71738137..5af96f2a 100644 --- a/helm/argo-wrapper/Chart.yaml +++ b/helm/argo-wrapper/Chart.yaml @@ -15,10 +15,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "2022.10" +appVersion: "master" diff --git a/helm/argo-wrapper/README.md b/helm/argo-wrapper/README.md new file mode 100644 index 00000000..9bafcdeb --- /dev/null +++ b/helm/argo-wrapper/README.md @@ -0,0 +1,60 @@ +# argo-wrapper + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) + +A Helm chart for gen3 Argo Wrapper Service + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key | string | `"app"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator | string | `"In"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0] | string | `"argo-wrapper"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey | string | `"kubernetes.io/hostname"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight | int | `100` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| dataDog.enabled | bool | `false` | | +| dataDog.env | string | `"dev"` | | +| environment | string | `"default"` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/cdis/argo-wrapper"` | | +| image.tag | string | `""` | | +| indexdAdminUser | string | `"fence"` | | +| internalS3Bucket | string | `"argo-internal-bucket"` | | +| livenessProbe.httpGet.path | string | `"/test"` | | +| livenessProbe.httpGet.port | int | `8000` | | +| livenessProbe.initialDelaySeconds | int | `30` | | +| livenessProbe.periodSeconds | int | `60` | | +| livenessProbe.timeoutSeconds | int | `30` | | +| podAnnotations."gen3.io/network-ingress" | string | `"argo-wrapper"` | | +| ports[0].containerPort | int | `8000` | | +| ports[0].protocol | string | `"TCP"` | | +| pvc | string | `"test-pvc"` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | string | `"100m"` | | +| resources.limits.memory | string | `"128Mi"` | | +| revisionHistoryLimit | int | `2` | | +| s3Bucket | string | `"argo-artifact-downloadable"` | | +| scalingGroups[0].user1 | string | `"workflow1"` | | +| scalingGroups[1].user2 | string | `"workflow2"` | | +| scalingGroups[2].user3 | string | `"workflow3"` | | +| service.port | int | `8000` | | +| service.type | string | `"ClusterIP"` | | +| strategy.rollingUpdate.maxSurge | int | `1` | | +| strategy.rollingUpdate.maxUnavailable | int | `0` | | +| strategy.type | string | `"RollingUpdate"` | | +| volumeMounts[0].mountPath | string | `"/argo.json"` | | +| volumeMounts[0].name | string | `"argo-config"` | | +| volumeMounts[0].readOnly | bool | `true` | | +| volumeMounts[0].subPath | string | `"argo.json"` | | +| volumes[0].configMap.items[0].key | string | `"argo.json"` | | +| volumes[0].configMap.items[0].path | string | `"argo.json"` | | +| volumes[0].configMap.name | string | `"manifest-argo"` | | +| volumes[0].name | string | `"argo-config"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/argo-wrapper/values.yaml b/helm/argo-wrapper/values.yaml index 113e23d5..a0b9271b 100644 --- a/helm/argo-wrapper/values.yaml +++ b/helm/argo-wrapper/values.yaml @@ -2,9 +2,7 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. - - -#Deployment +# Deployment podAnnotations: {"gen3.io/network-ingress": "argo-wrapper"} autoscaling: @@ -27,7 +25,7 @@ dataDog: enabled: false env: dev -affinity: +affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 @@ -78,14 +76,12 @@ resources: memory: 128Mi -#Service and Pod +# Service and Pod service: type: ClusterIP port: 8000 - - -#Configmap +# Configmap scalingGroups: - user1: "workflow1" - user2: "workflow2" @@ -94,4 +90,4 @@ s3Bucket: "argo-artifact-downloadable" internalS3Bucket: "argo-internal-bucket" indexdAdminUser: "fence" environment: "default" -pvc: "test-pvc" \ No newline at end of file +pvc: "test-pvc" diff --git a/helm/audit/Chart.lock b/helm/audit/Chart.lock index 5722364c..3631fd76 100644 --- a/helm/audit/Chart.lock +++ b/helm/audit/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: common repository: file://../common - version: 0.0.1 -digest: sha256:9447ea9a4ddee41221215f9d511d904829f457523bc78ddaa817c161e934f27f -generated: "2022-10-20T21:34:34.028897-05:00" + version: 0.1.0 +digest: sha256:8e96d9e4e8522837b307a10e8683e8b21330a984d519e9ed2867ea759da7207e +generated: "2022-12-07T10:38:58.713242+01:00" diff --git a/helm/audit/Chart.yaml b/helm/audit/Chart.yaml index 636f2c95..bfdd2f5f 100644 --- a/helm/audit/Chart.yaml +++ b/helm/audit/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -24,8 +24,6 @@ appVersion: "2022.10" dependencies: - name: common - version: 0.0.1 + version: 0.1.0 repository: file://../common condition: db_creation.enabled - - diff --git a/helm/audit/README.md b/helm/audit/README.md new file mode 100644 index 00000000..93bc6df6 --- /dev/null +++ b/helm/audit/README.md @@ -0,0 +1,104 @@ +# audit + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for Kubernetes + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../common | common | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key | string | `"app"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator | string | `"In"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0] | string | `"audit"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey | string | `"kubernetes.io/hostname"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight | int | `100` | | +| autoscaling.enabled | string | `"enabled"` | | +| autoscaling.maxReplicas | int | `4` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| env[0].name | string | `"DEBUG"` | | +| env[0].value | string | `"false"` | | +| env[1].name | string | `"ARBORIST_URL"` | | +| env[1].valueFrom.configMapKeyRef.key | string | `"arborist_url"` | | +| env[1].valueFrom.configMapKeyRef.name | string | `"manifest-global"` | | +| env[1].valueFrom.configMapKeyRef.optional | bool | `true` | | +| fullnameOverride | string | `""` | | +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/cdis/audit-service"` | | +| image.tag | string | `"master"` | | +| imagePullSecrets | list | `[]` | | +| initEnv | object | `{}` | | +| initVolumeMounts[0].mountPath | string | `"/src/audit-service-config.yaml"` | | +| initVolumeMounts[0].name | string | `"config-volume"` | | +| initVolumeMounts[0].readOnly | bool | `true` | | +| initVolumeMounts[0].subPath | string | `"audit-service-config.yaml"` | | +| labels."tags.datadoghq.com/service" | string | `"audit"` | | +| labels.app | string | `"audit"` | | +| labels.authprovider | string | `"yes"` | | +| labels.netnolimit | string | `"yes"` | | +| labels.public | string | `"yes"` | | +| labels.release | string | `"production"` | | +| labels.userhelper | string | `"yes"` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | | +| podSecurityContext | object | `{}` | | +| postgres.database | string | `"audit"` | | +| postgres.db_create | string | `nil` | | +| postgres.host | string | `nil` | | +| postgres.password | string | `nil` | | +| postgres.port | string | `"5432"` | | +| postgres.username | string | `"audit"` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | string | `"500m"` | | +| resources.limits.memory | string | `"1024Mi"` | | +| resources.requests.cpu | string | `"100m"` | | +| resources.requests.memory | string | `"128Mi"` | | +| secrets.sqs.region | string | `"us-east-1"` | | +| secrets.sqs.url | string | `"http://sqs.com"` | | +| securityContext | object | `{}` | | +| selectorLabels.app | string | `"audit"` | | +| server.debug | bool | `false` | | +| server.pull_from_queue | bool | `false` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations."eks.amazonaws.com/role-arn" | string | `"arn:aws:iam::707767160287:role/gen3_service/emalinowskiv1--default--audit-sqs-sender"` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `"audit-service-sa"` | | +| tolerations | list | `[]` | | +| volumeMounts[0].mountPath | string | `"/src/audit-service-config.yaml"` | | +| volumeMounts[0].name | string | `"config-volume"` | | +| volumeMounts[0].readOnly | bool | `true` | | +| volumeMounts[0].subPath | string | `"audit-service-config.yaml"` | | +| volumes[0].name | string | `"config-volume"` | | +| volumes[0].secret.secretName | string | `"audit-g3auto"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/audit/templates/db-init.yaml b/helm/audit/templates/db-init.yaml index e53cb144..a197f530 100644 --- a/helm/audit/templates/db-init.yaml +++ b/helm/audit/templates/db-init.yaml @@ -1,3 +1,3 @@ -{{- include "common.db-setup-job" . }} +{{ include "common.db-setup-job" . }} --- -{{- include "common.db-secret" . }} +{{ include "common.db-secret" . }} diff --git a/helm/audit/templates/deployment.yaml b/helm/audit/templates/deployment.yaml index 62e5e8d4..201ca370 100644 --- a/helm/audit/templates/deployment.yaml +++ b/helm/audit/templates/deployment.yaml @@ -1,7 +1,7 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: audit + name: audit-deployment labels: {{- include "audit.labels" . | nindent 4 }} spec: @@ -26,7 +26,7 @@ spec: containers: - name: audit image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: Always + imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - containerPort: 80 name: http @@ -45,6 +45,30 @@ spec: resources: {{- toYaml .Values.resources | nindent 12 }} env: + - name: DB_HOST + valueFrom: + secretKeyRef: + name: audit-dbcreds + key: host + optional: false + - name: DB_USER + valueFrom: + secretKeyRef: + name: audit-dbcreds + key: username + optional: false + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: audit-dbcreds + key: password + optional: false + - name: DB_DATABASE + valueFrom: + secretKeyRef: + name: audit-dbcreds + key: database + optional: false {{- toYaml .Values.env | nindent 12 }} volumeMounts: {{- toYaml .Values.volumeMounts | nindent 12 }} @@ -52,16 +76,31 @@ spec: - name: audit-init image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: http - containerPort: 80 - protocol: TCP - - name: https - containerPort: 443 - protocol: TCP - - name: container - containerPort: 6567 - protocol: TCP + env: + - name: DB_HOST + valueFrom: + secretKeyRef: + name: audit-dbcreds + key: host + optional: false + - name: DB_USER + valueFrom: + secretKeyRef: + name: audit-dbcreds + key: username + optional: false + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: audit-dbcreds + key: password + optional: false + - name: DB_DATABASE + valueFrom: + secretKeyRef: + name: audit-dbcreds + key: database + optional: false resources: {{- toYaml .Values.resources | nindent 12 }} command: ["/bin/bash"] diff --git a/helm/audit/templates/secrets.yaml b/helm/audit/templates/secrets.yaml index 97e193ec..add33135 100644 --- a/helm/audit/templates/secrets.yaml +++ b/helm/audit/templates/secrets.yaml @@ -16,11 +16,4 @@ stringData: type: aws_sqs aws_sqs_config: sqs_url: {{ .Values.secrets.sqs.url }} - region: {{ .Values.secrets.sqs.region }} - #################### - # DATABASE # - #################### - DB_HOST: {{ include "gen3.service-postgres" (dict "key" "host" "service" $.Chart.Name "context" $) | quote }} - DB_USER: {{include "gen3.service-postgres" (dict "key" "username" "service" $.Chart.Name "context" $) | quote}} - DB_PASSWORD: {{include "gen3.service-postgres" (dict "key" "password" "service" $.Chart.Name "context" $) | quote }} - DB_DATABASE: {{include "gen3.service-postgres" (dict "key" "database" "service" $.Chart.Name "context" $)| quote }} + region: {{ .Values.secrets.sqs.region }} \ No newline at end of file diff --git a/helm/audit/values.yaml b/helm/audit/values.yaml index f9cbec28..3efc88d0 100644 --- a/helm/audit/values.yaml +++ b/helm/audit/values.yaml @@ -2,25 +2,38 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. global: - # Default values are for postgres deployed as a helm chart + dev: true postgres: - host: postgres-postgresql.postgres.svc.cluster.local + db_create: true master: + host: username: postgres - password: - port: 5432 + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false -db_create: true postgres: - # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you + db_create: + # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you database: audit username: audit host: - port: 5432 + port: "5432" # If left empty password will be auto-generated - password: - - + password: replicaCount: 1 @@ -38,7 +51,7 @@ serviceAccount: # Specifies whether a service account should be created create: true # Annotations to add to the service account - annotations: + annotations: eks.amazonaws.com/role-arn: arn:aws:iam::707767160287:role/gen3_service/emalinowskiv1--default--audit-sqs-sender # The name of the service account to use. # If not set and create is true, a name is generated using the fullname template @@ -46,7 +59,7 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +podSecurityContext: {} securityContext: {} @@ -62,8 +75,8 @@ service: port: 80 -resources: - requests: +resources: + requests: cpu: 100m memory: 128Mi limits: @@ -92,7 +105,7 @@ nodeSelector: {} tolerations: [] -labels: +labels: app: audit release: production # for network policy selectors @@ -102,7 +115,7 @@ labels: public: "yes" userhelper: "yes" tags.datadoghq.com/service: "audit" -affinity: +affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 @@ -115,7 +128,7 @@ affinity: - audit topologyKey: "kubernetes.io/hostname" -env: +env: - name: DEBUG value: "false" - name: ARBORIST_URL @@ -130,21 +143,21 @@ volumes: secret: secretName: "audit-g3auto" -volumeMounts: +volumeMounts: - name: "config-volume" readOnly: true mountPath: "/src/audit-service-config.yaml" - subPath: "audit-service-config.yaml" + subPath: "audit-service-config.yaml" -initVolumeMounts: +initVolumeMounts: - name: "config-volume" readOnly: true mountPath: "/src/audit-service-config.yaml" - subPath: "audit-service-config.yaml" + subPath: "audit-service-config.yaml" initEnv: {} -selectorLabels: +selectorLabels: app: audit server: diff --git a/helm/aws-es-proxy/Chart.yaml b/helm/aws-es-proxy/Chart.yaml index bb8dc186..7c2fa6cb 100644 --- a/helm/aws-es-proxy/Chart.yaml +++ b/helm/aws-es-proxy/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/aws-es-proxy/README.md b/helm/aws-es-proxy/README.md new file mode 100644 index 00000000..c49ea603 --- /dev/null +++ b/helm/aws-es-proxy/README.md @@ -0,0 +1,42 @@ +# aws-es-proxy + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) + +A Helm chart for AWS ES Proxy Service for gen3 + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| automountServiceAccountToken | bool | `false` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| esEndpoint | string | `"test.us-east-1.es.amazonaws.com"` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/cdis/aws-es-proxy"` | | +| image.tag | string | `""` | | +| podAnnotations."gen3.io/network-ingress" | string | `"guppy,metadata,spark,tube"` | | +| ports[0].containerPort | int | `9200` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | int | `1` | | +| resources.limits.memory | string | `"2Gi"` | | +| resources.requests.cpu | string | `"250m"` | | +| resources.requests.memory | string | `"256Mi"` | | +| revisionHistoryLimit | int | `2` | | +| secrets.awsAccessKeyId | string | `"asdpofasdokj"` | | +| secrets.awsSecretAccessKey | string | `"asdfjkljklj"` | | +| service.port | int | `9200` | | +| service.type | string | `"ClusterIP"` | | +| strategy.rollingUpdate.maxSurge | int | `1` | | +| strategy.rollingUpdate.maxUnavailable | int | `0` | | +| strategy.type | string | `"RollingUpdate"` | | +| volumeMounts[0].mountPath | string | `"/root/.aws"` | | +| volumeMounts[0].name | string | `"credentials"` | | +| volumeMounts[0].readOnly | bool | `true` | | +| volumes[0].name | string | `"credentials"` | | +| volumes[0].secret.secretName | string | `"aws-es-proxy"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/aws-es-proxy/values.yaml b/helm/aws-es-proxy/values.yaml index 959f2bab..b7b3cda4 100644 --- a/helm/aws-es-proxy/values.yaml +++ b/helm/aws-es-proxy/values.yaml @@ -2,9 +2,7 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. - - -#Deployment +# Deployment podAnnotations: {"gen3.io/network-ingress": "guppy,metadata,spark,tube"} autoscaling: @@ -29,7 +27,7 @@ volumes: - name: credentials secret: secretName: aws-es-proxy - + image: repository: quay.io/cdis/aws-es-proxy pullPolicy: Always @@ -57,14 +55,12 @@ resources: memory: 2Gi -#Service and Pod +# Service and Pod service: type: ClusterIP port: 9200 - - -#Secret +# Secret secrets: awsAccessKeyId: "asdpofasdokj" - awsSecretAccessKey: "asdfjkljklj" \ No newline at end of file + awsSecretAccessKey: "asdfjkljklj" diff --git a/helm/common/Chart.yaml b/helm/common/Chart.yaml index d6f450ed..93d4fa88 100644 --- a/helm/common/Chart.yaml +++ b/helm/common/Chart.yaml @@ -15,7 +15,7 @@ type: library # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/common/README.md b/helm/common/README.md new file mode 100644 index 00000000..d444f8aa --- /dev/null +++ b/helm/common/README.md @@ -0,0 +1,34 @@ +# common + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: library](https://img.shields.io/badge/Type-library-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) + +A Helm chart for provisioning databases in gen3 + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| postgres.db_create | string | `nil` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/common/templates/_db_setup_job.tpl b/helm/common/templates/_db_setup_job.tpl index cc45f329..06e8f5a0 100644 --- a/helm/common/templates/_db_setup_job.tpl +++ b/helm/common/templates/_db_setup_job.tpl @@ -4,29 +4,41 @@ apiVersion: batch/v1 kind: Job metadata: name: {{ .Chart.Name }}-dbcreate - annotations: - "helm.sh/hook": "pre-install" #,pre-upgrade" spec: template: metadata: labels: + # TODO : READ FROM CENTRAL FUNCTION TOO? app: gen3job spec: restartPolicy: OnFailure containers: - name: db-setup + # TODO: READ THIS IMAGE FROM GLOBAL VALUES? image: quay.io/cdis/awshelper:master imagePullPolicy: Always command: ["/bin/bash", "-c"] env: - name: PGPASSWORD - value: "{{ include "gen3.master-postgres" (dict "key" "password" "context" $) }}" + {{- if $.Values.global.dev }} + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-postgresql + key: postgres-password + optional: false + {{- else }} + value: {{ .Values.global.postgres.master.password | quote}} + {{- end }} - name: PGUSER - value: "{{ include "gen3.master-postgres" (dict "key" "username" "context" $) }}" + value: {{ .Values.global.postgres.master.username | quote }} - name: PGPORT - value: "{{ include "gen3.master-postgres" (dict "key" "port" "context" $) }}" + value: {{ .Values.global.postgres.master.port | quote }} - name: PGHOST - value: "{{ include "gen3.master-postgres" (dict "key" "host" "context" $) }}" + {{- if $.Values.global.dev }} + value: "{{ .Release.Name }}-postgresql" + {{- else }} + value: {{ .Values.global.postgres.master.host | quote }} + {{- end }} - name: SERVICE_PGUSER valueFrom: secretKeyRef: @@ -47,7 +59,8 @@ spec: optional: false args: - | - env + #!/bin/bash + set -e echo "SERVICE_PGDB=$SERVICE_PGDB" echo "SERVICE_PGUSER=$SERVICE_PGUSER" if psql -lqt | cut -d \| -f 1 | grep -qw $SERVICE_PGDB; then @@ -69,20 +82,18 @@ Create k8s secrets for connecting to postgres */}} # DB Secrets {{- define "common.db-secret" -}} -{{- if not (lookup "v1" "Secret" .Release.Namespace (printf "%s-%s" .Chart.Name "dbcreds")) }} apiVersion: v1 kind: Secret metadata: name: {{ $.Chart.Name }}-dbcreds - annotations: - "helm.sh/hook": "pre-install,pre-upgrade" - "helm.sh/resource-policy": "keep" - "helm.sh/hook-weight": "-10" -stringData: - host: {{ include "gen3.service-postgres" (dict "key" "host" "service" $.Chart.Name "context" $) }} - database: "{{ include "gen3.service-postgres" (dict "key" "database" "service" $.Chart.Name "context" $) }}" - username: "{{ include "gen3.service-postgres" (dict "key" "username" "service" $.Chart.Name "context" $) }}" - password: "{{ include "gen3.service-postgres" (dict "key" "password" "service" $.Chart.Name "context" $) }}" - port: "{{ include "gen3.service-postgres" (dict "key" "port" "service" $.Chart.Name "context" $) }}" -{{- end -}} +data: + database: {{ $.Values.postgres.database | b64enc | quote}} + username: {{ $.Values.postgres.username | b64enc | quote }} + port: {{ $.Values.postgres.port | b64enc | quote }} + password: {{ include "gen3.service-postgres" (dict "key" "password" "service" $.Chart.Name "context" $) | b64enc | quote }} + {{- if $.Values.global.dev }} + host: {{ (printf "%s-%s" $.Release.Name "postgresql" ) | b64enc | quote }} + {{- else }} + host: {{ include "gen3.service-postgres" (dict "key" "host" "service" $.Chart.Name "context" $) | b64enc | quote }} + {{- end }} {{- end }} \ No newline at end of file diff --git a/helm/common/templates/_postgres_secrets.tpl b/helm/common/templates/_postgres_secrets.tpl index 4cf5c8f1..c256b10f 100644 --- a/helm/common/templates/_postgres_secrets.tpl +++ b/helm/common/templates/_postgres_secrets.tpl @@ -18,17 +18,24 @@ */}} {{- define "gen3.service-postgres" -}} {{- $chartName := default "" .context.Chart.Name }} - {{- $valuesPostgres := get .context.Values.postgres .key}} - {{- $localSecretPass := get ((lookup "v1" "Secret" .context.Release.Namespace (cat .service "-dbcreds")).data) .key }} - + {{- $valuesPostgres := get .context.Values.postgres .key }} + {{- $localSecretPass := "" }} + {{- $secretData := (lookup "v1" "Secret" $.context.Release.Namespace (printf "%s-%s" $chartName "dbcreds")).data }} + {{- if $secretData }} + {{- if hasKey $secretData .key }} + {{- $localSecretPass = index $secretData .key | b64dec }} + {{- else }} + {{- printf "\nERROR: The secret \"%s\" does not contain the key \"%s\"\n" (printf "%s-%s" $chartName "dbcreds") .key | fail -}} + {{- end }} + {{- end }} {{- $randomPassword := "" }} {{- $valuesGlobalPostgres := get .context.Values.global.postgres.master .key}} {{- if eq .key "password" }} {{- $randomPassword = randAlphaNum 20 }} {{- $valuesGlobalPostgres = "" }} {{- end }} - {{- $password := coalesce $valuesPostgres $localSecretPass $randomPassword $valuesGlobalPostgres}} - {{- printf "%v" $password -}} + {{- $value := coalesce $valuesPostgres $localSecretPass $randomPassword $valuesGlobalPostgres}} + {{- printf "%v" $value -}} {{- end }} @@ -46,49 +53,16 @@ Usage: # https://helm.sh/docs/chart_template_guide/function_list/#coalesce */}} {{- define "gen3.master-postgres" }} - {{- $chartName := default "" .context.Chart.Name }} + {{- $chartName := .context.Chart.Name }} {{- $valuesPostgres := get .context.Values.global.postgres.master .key}} - {{- $secret := (lookup "v1" "Secret" "postgres" "postgres-postgresql" )}} + {{- $secret := (lookup "v1" "Secret" "default" "gen3-postgresql" )}} {{- $devPostgresSecret := "" }} {{- if $secret }} - {{- $devPostgresSecret = (index $secret.data "postgres-password") | b64dec }} + {{- $devPostgresSecret = (index $secret "data" "postgres-password") | b64dec }} {{- end }} {{- $value := coalesce $valuesPostgres $devPostgresSecret }} {{- printf "%v" $value -}} {{- end }} - - - - -{{/* - Postgres User lookup -*/}} -{{- define "peregrine.postgres.user" -}} -{{- $localpass := (lookup "v1" "Secret" "postgres" "postgres-postgresql" ) -}} -{{- if $localpass }} -{{- default (index $localpass.data "postgres-password" | b64dec) }} -{{- else }} -{{- default .Values.postgres.password }} -{{- end }} -{{- end }} - - -{{- if not (lookup "v1" "Secret" .Release.Namespace (printf "%s-%s" .Chart.Name "dbcreds")) }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Chart.Name }}-dbcreds - annotations: - "helm.sh/hook": "pre-install,pre-upgrade" - "helm.sh/resource-policy": "keep" - "helm.sh/hook-weight": "-10" -stringData: - host: {{ default .Values.global.postgres.host .Values.postgres.host }} - database: "{{ default .Chart.Name .Values.postgres.dbname }}" - username: "{{ default .Chart.Name .Values.postgres.user }}" - password: "{{ default (randAlphaNum 24 | nospace) .Values.postgres.password }}" - port: "{{ default 5432 .Values.postgres.port }}" -{{- end -}} \ No newline at end of file diff --git a/helm/common/templates/_secrets.tpl b/helm/common/templates/_secrets.tpl deleted file mode 100644 index 837aa104..00000000 --- a/helm/common/templates/_secrets.tpl +++ /dev/null @@ -1,140 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Generate secret name. - -Usage: -{{ include "common.secrets.name" (dict "existingSecret" .Values.path.to.the.existingSecret "defaultNameSuffix" "mySuffix" "context" $) }} - -Params: - - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user - to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. - +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret - - defaultNameSuffix - String - Optional. It is used only if we have several secrets in the same deployment. - - context - Dict - Required. The context for the template evaluation. -*/}} -{{- define "common.secrets.name" -}} -{{- $name := (include "common.names.fullname" .context) -}} - -{{- if .defaultNameSuffix -}} -{{- $name = printf "%s-%s" $name .defaultNameSuffix | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{- with .existingSecret -}} -{{- if not (typeIs "string" .) -}} -{{- with .name -}} -{{- $name = . -}} -{{- end -}} -{{- else -}} -{{- $name = . -}} -{{- end -}} -{{- end -}} - -{{- printf "%s" $name -}} -{{- end -}} - -{{/* -Generate secret key. - -Usage: -{{ include "common.secrets.key" (dict "existingSecret" .Values.path.to.the.existingSecret "key" "keyName") }} - -Params: - - existingSecret - ExistingSecret/String - Optional. The path to the existing secrets in the values.yaml given by the user - to be used instead of the default one. Allows for it to be of type String (just the secret name) for backwards compatibility. - +info: https://github.com/bitnami/charts/tree/main/bitnami/common#existingsecret - - key - String - Required. Name of the key in the secret. -*/}} -{{- define "common.secrets.key" -}} -{{- $key := .key -}} - -{{- if .existingSecret -}} - {{- if not (typeIs "string" .existingSecret) -}} - {{- if .existingSecret.keyMapping -}} - {{- $key = index .existingSecret.keyMapping $.key -}} - {{- end -}} - {{- end }} -{{- end -}} - -{{- printf "%s" $key -}} -{{- end -}} - -{{/* -Generate secret password or retrieve one if already created. - -Usage: -{{ include "common.secrets.passwords.manage" (dict "secret" "secret-name" "key" "keyName" "providedValues" (list "path.to.password1" "path.to.password2") "length" 10 "strong" false "chartName" "chartName" "context" $) }} - -Params: - - secret - String - Required - Name of the 'Secret' resource where the password is stored. - - key - String - Required - Name of the key in the secret. - - providedValues - List - Required - The path to the validating value in the values.yaml, e.g: "mysql.password". Will pick first parameter with a defined value. - - length - int - Optional - Length of the generated random password. - - strong - Boolean - Optional - Whether to add symbols to the generated random password. - - chartName - String - Optional - Name of the chart used when said chart is deployed as a subchart. - - context - Context - Required - Parent context. - -The order in which this function returns a secret password: - 1. Already existing 'Secret' resource - (If a 'Secret' resource is found under the name provided to the 'secret' parameter to this function and that 'Secret' resource contains a key with the name passed as the 'key' parameter to this function then the value of this existing secret password will be returned) - 2. Password provided via the values.yaml - (If one of the keys passed to the 'providedValues' parameter to this function is a valid path to a key in the values.yaml and has a value, the value of the first key with a value will be returned) - 3. Randomly generated secret password - (A new random secret password with the length specified in the 'length' parameter will be generated and returned) - -*/}} -{{- define "common.secrets.passwords.manage" -}} - -{{- $password := "" }} -{{- $subchart := "" }} -{{- $chartName := default "" .chartName }} -{{- $passwordLength := default 10 .length }} -{{- $providedPasswordKey := include "common.utils.getKeyFromList" (dict "keys" .providedValues "context" $.context) }} -{{- $providedPasswordValue := include "common.utils.getValueFromKey" (dict "key" $providedPasswordKey "context" $.context) }} -{{- $secretData := (lookup "v1" "Secret" $.context.Release.Namespace .secret).data }} -{{- if $secretData }} - {{- if hasKey $secretData .key }} - {{- $password = index $secretData .key | quote }} - {{- else }} - {{- printf "\nPASSWORDS ERROR: The secret \"%s\" does not contain the key \"%s\"\n" .secret .key | fail -}} - {{- end -}} -{{- else if $providedPasswordValue }} - {{- $password = $providedPasswordValue | toString | b64enc | quote }} -{{- else }} - - {{- if .context.Values.enabled }} - {{- $subchart = $chartName }} - {{- end -}} - - {{- $requiredPassword := dict "valueKey" $providedPasswordKey "secret" .secret "field" .key "subchart" $subchart "context" $.context -}} - {{- $requiredPasswordError := include "common.validations.values.single.empty" $requiredPassword -}} - {{- $passwordValidationErrors := list $requiredPasswordError -}} - {{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" $passwordValidationErrors "context" $.context) -}} - - {{- if .strong }} - {{- $subStr := list (lower (randAlpha 1)) (randNumeric 1) (upper (randAlpha 1)) | join "_" }} - {{- $password = randAscii $passwordLength }} - {{- $password = regexReplaceAllLiteral "\\W" $password "@" | substr 5 $passwordLength }} - {{- $password = printf "%s%s" $subStr $password | toString | shuffle | b64enc | quote }} - {{- else }} - {{- $password = randAlphaNum $passwordLength | b64enc | quote }} - {{- end }} -{{- end -}} -{{- printf "%s" $password -}} -{{- end -}} - -{{/* -Returns whether a previous generated secret already exists - -Usage: -{{ include "common.secrets.exists" (dict "secret" "secret-name" "context" $) }} - -Params: - - secret - String - Required - Name of the 'Secret' resource where the password is stored. - - context - Context - Required - Parent context. -*/}} -{{- define "common.secrets.exists" -}} -{{- $secret := (lookup "v1" "Secret" $.context.Release.Namespace .secret) }} -{{- if $secret }} - {{- true -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/helm/common/values.yaml b/helm/common/values.yaml new file mode 100644 index 00000000..f3ba6086 --- /dev/null +++ b/helm/common/values.yaml @@ -0,0 +1,26 @@ +global: + dev: true + postgres: + db_create: true + master: + host: + username: postgres + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false + +postgres: + db_create: diff --git a/helm/dicom-server/Chart.yaml b/helm/dicom-server/Chart.yaml index f5014981..060d9bea 100644 --- a/helm/dicom-server/Chart.yaml +++ b/helm/dicom-server/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 +version: 0.1.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/dicom-server/README.md b/helm/dicom-server/README.md new file mode 100644 index 00000000..889bb680 --- /dev/null +++ b/helm/dicom-server/README.md @@ -0,0 +1,50 @@ +# dicom-server + +![Version: 0.1.1](https://img.shields.io/badge/Version-0.1.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) + +A Helm chart for gen3 Dicom Server + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/cdis/gen3-orthanc"` | | +| image.tag | string | `"master"` | | +| livenessProbe.httpGet.path | string | `"/system"` | | +| livenessProbe.httpGet.port | int | `8042` | | +| livenessProbe.initialDelaySeconds | int | `5` | | +| livenessProbe.periodSeconds | int | `60` | | +| livenessProbe.timeoutSeconds | int | `30` | | +| ports[0].containerPort | int | `8042` | | +| readinessProbe.httpGet.path | string | `"/system"` | | +| readinessProbe.httpGet.port | int | `8042` | | +| readinessProbe.initialDelaySeconds | int | `5` | | +| readinessProbe.periodSeconds | int | `20` | | +| readinessProbe.timeoutSeconds | int | `30` | | +| replicaCount | int | `1` | | +| secrets.authenticationEnabled | bool | `false` | | +| secrets.dataBase | string | `"postgres"` | | +| secrets.enableIndex | bool | `true` | | +| secrets.enableStorage | bool | `true` | | +| secrets.host | string | `"postgres-postgresql.postgres.svc.cluster.local"` | | +| secrets.indexConnectionsCount | int | `5` | | +| secrets.lock | bool | `false` | | +| secrets.password | string | `"postgres"` | | +| secrets.port | string | `"5432"` | | +| secrets.userName | string | `"postgres"` | | +| service.port | int | `80` | | +| service.targetport | int | `8042` | | +| volumeMounts[0].mountPath | string | `"/etc/orthanc/orthanc_config_overwrites.json"` | | +| volumeMounts[0].name | string | `"config-volume-g3auto"` | | +| volumeMounts[0].readOnly | bool | `true` | | +| volumeMounts[0].subPath | string | `"orthanc_config_overwrites.json"` | | +| volumes[0].name | string | `"config-volume-g3auto"` | | +| volumes[0].secret.secretName | string | `"orthanc-g3auto"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/dicom-server/values.yaml b/helm/dicom-server/values.yaml index 97d366ad..1457059e 100644 --- a/helm/dicom-server/values.yaml +++ b/helm/dicom-server/values.yaml @@ -2,9 +2,7 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. - - -#Deployment +# Deployment autoscaling: enabled: false minReplicas: 1 @@ -38,7 +36,7 @@ livenessProbe: port: 8042 initialDelaySeconds: 5 periodSeconds: 60 - timeoutSeconds: 30 + timeoutSeconds: 30 ports: - containerPort: 8042 @@ -50,22 +48,20 @@ volumeMounts: subPath: orthanc_config_overwrites.json -#Service and Pod +# Service and Pod service: port: 80 targetport: 8042 - - -#Secret +# Secret secrets: authenticationEnabled: false enableIndex: true enableStorage: true - port: 5432 + port: "5432" host: postgres-postgresql.postgres.svc.cluster.local dataBase: postgres userName: postgres password: postgres indexConnectionsCount: 5 - lock: false \ No newline at end of file + lock: false diff --git a/helm/dicom-viewer/Chart.yaml b/helm/dicom-viewer/Chart.yaml index 7f8012b9..94bd9e48 100644 --- a/helm/dicom-viewer/Chart.yaml +++ b/helm/dicom-viewer/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 +version: 0.1.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/dicom-viewer/README.md b/helm/dicom-viewer/README.md new file mode 100644 index 00000000..5289bcdb --- /dev/null +++ b/helm/dicom-viewer/README.md @@ -0,0 +1,34 @@ +# dicom-viewer + +![Version: 0.1.1](https://img.shields.io/badge/Version-0.1.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) + +A Helm chart for gen3 Dicom Viewer + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/cdis/ohif-viewer"` | | +| image.tag | string | `"master"` | | +| livenessProbe.httpGet.path | string | `"/"` | | +| livenessProbe.httpGet.port | int | `80` | | +| livenessProbe.initialDelaySeconds | int | `5` | | +| livenessProbe.periodSeconds | int | `60` | | +| livenessProbe.timeoutSeconds | int | `30` | | +| ports[0].containerPort | int | `80` | | +| readinessProbe.httpGet.path | string | `"/"` | | +| readinessProbe.httpGet.port | int | `80` | | +| readinessProbe.initialDelaySeconds | int | `5` | | +| readinessProbe.periodSeconds | int | `20` | | +| readinessProbe.timeoutSeconds | int | `30` | | +| replicaCount | int | `1` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/dicom-viewer/values.yaml b/helm/dicom-viewer/values.yaml index a81a6eff..f38d8997 100644 --- a/helm/dicom-viewer/values.yaml +++ b/helm/dicom-viewer/values.yaml @@ -2,9 +2,7 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. - - -#Deployment +# Deployment autoscaling: enabled: false minReplicas: 1 @@ -26,7 +24,7 @@ readinessProbe: initialDelaySeconds: 5 periodSeconds: 20 timeoutSeconds: 30 - + livenessProbe: httpGet: path: / @@ -39,7 +37,7 @@ ports: - containerPort: 80 -#Service and Pod +# Service and Pod service: type: ClusterIP - port: 80 \ No newline at end of file + port: 80 diff --git a/helm/fence/Chart.lock b/helm/fence/Chart.lock index 0d7b33f1..d824b0da 100644 --- a/helm/fence/Chart.lock +++ b/helm/fence/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: common repository: file://../common - version: 0.0.1 -digest: sha256:9447ea9a4ddee41221215f9d511d904829f457523bc78ddaa817c161e934f27f -generated: "2022-10-20T21:34:35.742578-05:00" + version: 0.1.0 +digest: sha256:8e96d9e4e8522837b307a10e8683e8b21330a984d519e9ed2867ea759da7207e +generated: "2022-12-07T10:38:58.734502+01:00" diff --git a/helm/fence/Chart.yaml b/helm/fence/Chart.yaml index 75e40506..81fb061a 100644 --- a/helm/fence/Chart.yaml +++ b/helm/fence/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -24,6 +24,6 @@ appVersion: "2022.10" dependencies: - name: common - version: 0.0.1 + version: 0.1.0 repository: file://../common - condition: db_creation.enabled \ No newline at end of file + condition: db_creation.enabled diff --git a/helm/fence/README.md b/helm/fence/README.md new file mode 100644 index 00000000..228c3cc7 --- /dev/null +++ b/helm/fence/README.md @@ -0,0 +1,1105 @@ +# fence + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 Fence + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../common | common | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| FENCE_CONFIG.ACCESS_TOKEN_COOKIE_NAME | string | `"access_token"` | | +| FENCE_CONFIG.ACCESS_TOKEN_EXPIRES_IN | int | `1200` | | +| FENCE_CONFIG.ALLOWED_USER_SERVICE_ACCOUNT_DOMAINS[0] | string | `"developer.gserviceaccount.com"` | | +| FENCE_CONFIG.ALLOWED_USER_SERVICE_ACCOUNT_DOMAINS[1] | string | `"appspot.gserviceaccount.com"` | | +| FENCE_CONFIG.ALLOWED_USER_SERVICE_ACCOUNT_DOMAINS[2] | string | `"iam.gserviceaccount.com"` | | +| FENCE_CONFIG.ALLOW_GOOGLE_LINKING | bool | `true` | | +| FENCE_CONFIG.APPLICATION_ROOT | string | `"/user"` | | +| FENCE_CONFIG.APP_NAME | string | `"Gen3 Data Commons"` | | +| FENCE_CONFIG.ARBORIST | string | `nil` | | +| FENCE_CONFIG.ASSUME_ROLE_CACHE_SECONDS | int | `1800` | | +| FENCE_CONFIG.AUDIT_SERVICE | string | `"http://audit-service"` | | +| FENCE_CONFIG.AUTHLIB_INSECURE_TRANSPORT | bool | `true` | | +| FENCE_CONFIG.AWS_CREDENTIALS | object | `{}` | | +| FENCE_CONFIG.AZ_BLOB_CONTAINER_URL | string | `"https://myfakeblob.blob.core.windows.net/my-fake-container/"` | | +| FENCE_CONFIG.AZ_BLOB_CREDENTIALS | string | `nil` | | +| FENCE_CONFIG.BILLING_PROJECT_FOR_SA_CREDS | string | `nil` | | +| FENCE_CONFIG.BILLING_PROJECT_FOR_SIGNED_URLS | string | `nil` | | +| FENCE_CONFIG.CIRRUS_CFG.GOOGLE_ADMIN_EMAIL | string | `""` | | +| FENCE_CONFIG.CIRRUS_CFG.GOOGLE_API_KEY | string | `""` | | +| FENCE_CONFIG.CIRRUS_CFG.GOOGLE_APPLICATION_CREDENTIALS | string | `""` | | +| FENCE_CONFIG.CIRRUS_CFG.GOOGLE_CLOUD_IDENTITY_ADMIN_EMAIL | string | `""` | | +| FENCE_CONFIG.CIRRUS_CFG.GOOGLE_IDENTITY_DOMAIN | string | `""` | | +| FENCE_CONFIG.CIRRUS_CFG.GOOGLE_PROJECT_ID | string | `""` | | +| FENCE_CONFIG.CIRRUS_CFG.GOOGLE_STORAGE_CREDS | string | `""` | | +| FENCE_CONFIG.CLIENT_ALLOWED_SCOPES[0] | string | `"openid"` | | +| FENCE_CONFIG.CLIENT_ALLOWED_SCOPES[1] | string | `"user"` | | +| FENCE_CONFIG.CLIENT_ALLOWED_SCOPES[2] | string | `"data"` | | +| FENCE_CONFIG.CLIENT_ALLOWED_SCOPES[3] | string | `"google_credentials"` | | +| FENCE_CONFIG.CLIENT_ALLOWED_SCOPES[4] | string | `"google_service_account"` | | +| FENCE_CONFIG.CLIENT_ALLOWED_SCOPES[5] | string | `"google_link"` | | +| FENCE_CONFIG.CLIENT_ALLOWED_SCOPES[6] | string | `"ga4gh_passport_v1"` | | +| FENCE_CONFIG.DATA_UPLOAD_BUCKET | string | `"bucket1"` | | +| FENCE_CONFIG.DBGAP_ACCESSION_WITH_CONSENT_REGEX | string | `"(?Pphs[0-9]+)(.(?Pv[0-9]+)){0,1}(.(?Pp[0-9]+)){0,1}.(?Pc[0-9]+)"` | | +| FENCE_CONFIG.DEBUG | bool | `false` | | +| FENCE_CONFIG.DEFAULT_LOGIN_IDP | string | `"google"` | | +| FENCE_CONFIG.DEFAULT_LOGIN_URL | string | `"{{BASE_URL}}/login/google"` | | +| FENCE_CONFIG.DEV_LOGIN_COOKIE_NAME | string | `"dev_login"` | | +| FENCE_CONFIG.DREAM_CHALLENGE_GROUP | string | `"DREAM"` | | +| FENCE_CONFIG.DREAM_CHALLENGE_TEAM | string | `"DREAM"` | | +| FENCE_CONFIG.EMAIL_SERVER | string | `"localhost"` | | +| FENCE_CONFIG.ENABLED_IDENTITY_PROVIDERS | object | `{}` | | +| FENCE_CONFIG.ENABLE_AUDIT_LOGS.login | bool | `false` | | +| FENCE_CONFIG.ENABLE_AUDIT_LOGS.presigned_url | bool | `false` | | +| FENCE_CONFIG.ENABLE_AUTOMATIC_BILLING_PERMISSION_SA_CREDS | bool | `false` | | +| FENCE_CONFIG.ENABLE_AUTOMATIC_BILLING_PERMISSION_SIGNED_URLS | bool | `false` | | +| FENCE_CONFIG.ENABLE_CSRF_PROTECTION | bool | `true` | | +| FENCE_CONFIG.ENABLE_DB_MIGRATION | bool | `true` | | +| FENCE_CONFIG.ENABLE_PROMETHEUS_METRICS | bool | `false` | | +| FENCE_CONFIG.ENCRYPTION_KEY | string | `"REPLACEME"` | | +| FENCE_CONFIG.GA4GH_VISA_ISSUER_ALLOWLIST[0] | string | `"{{BASE_URL}}"` | | +| FENCE_CONFIG.GA4GH_VISA_ISSUER_ALLOWLIST[1] | string | `"https://sts.nih.gov"` | | +| FENCE_CONFIG.GA4GH_VISA_ISSUER_ALLOWLIST[2] | string | `"https://stsstg.nih.gov"` | | +| FENCE_CONFIG.GEN3_PASSPORT_EXPIRES_IN | int | `43200` | | +| FENCE_CONFIG.GLOBAL_PARSE_VISAS_ON_LOGIN | string | `nil` | | +| FENCE_CONFIG.GOOGLE_ACCOUNT_ACCESS_EXPIRES_IN | int | `86400` | | +| FENCE_CONFIG.GOOGLE_BULK_UPDATES | bool | `false` | | +| FENCE_CONFIG.GOOGLE_GROUP_PREFIX | string | `""` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[0] | string | `"dataflow-service-producer-prod.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[10] | string | `"container-analysis.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[11] | string | `"cloudservices.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[12] | string | `"stackdriver-service.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[13] | string | `"appspot.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[14] | string | `"partnercontent.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[15] | string | `"trifacta-gcloud-prod.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[16] | string | `"gcf-admin-robot.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[17] | string | `"compute-system.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[18] | string | `"gcp-sa-websecurityscanner.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[19] | string | `"storage-transfer-service.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[1] | string | `"cloudbuild.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[20] | string | `"firebase-sa-management.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[21] | string | `"firebase-rules.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[22] | string | `"gcp-sa-cloudbuild.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[23] | string | `"gcp-sa-automl.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[24] | string | `"gcp-sa-datalabeling.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[25] | string | `"gcp-sa-cloudscheduler.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[2] | string | `"cloud-ml.google.com.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[3] | string | `"container-engine-robot.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[4] | string | `"dataflow-service-producer-prod.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[5] | string | `"sourcerepo-service-accounts.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[6] | string | `"dataproc-accounts.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[7] | string | `"gae-api-prod.google.com.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[8] | string | `"genomics-api.google.com.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_MANAGED_SERVICE_ACCOUNT_DOMAINS[9] | string | `"containerregistry.iam.gserviceaccount.com"` | | +| FENCE_CONFIG.GOOGLE_SERVICE_ACCOUNT_KEY_FOR_URL_SIGNING_EXPIRES_IN | int | `2592000` | | +| FENCE_CONFIG.GOOGLE_SERVICE_ACCOUNT_PREFIX | string | `""` | | +| FENCE_CONFIG.GOOGLE_USER_SERVICE_ACCOUNT_ACCESS_EXPIRES_IN | int | `604800` | | +| FENCE_CONFIG.GUN_MAIL."datacommons.io".api_key | string | `""` | | +| FENCE_CONFIG.GUN_MAIL."datacommons.io".api_url | string | `"https://api.mailgun.net/v3/mailgun.example.com"` | | +| FENCE_CONFIG.GUN_MAIL."datacommons.io".default_login | string | `"postmaster@mailgun.example.com"` | | +| FENCE_CONFIG.GUN_MAIL."datacommons.io".smtp_hostname | string | `"smtp.mailgun.org"` | | +| FENCE_CONFIG.GUN_MAIL."datacommons.io".smtp_password | string | `""` | | +| FENCE_CONFIG.HTTP_PROXY.host | string | `nil` | | +| FENCE_CONFIG.HTTP_PROXY.port | int | `3128` | | +| FENCE_CONFIG.INDEXD | string | `nil` | | +| FENCE_CONFIG.INDEXD_PASSWORD | string | `""` | | +| FENCE_CONFIG.INDEXD_USERNAME | string | `"fence"` | | +| FENCE_CONFIG.ITRUST_GLOBAL_LOGOUT | string | `"https://auth.nih.gov/siteminderagent/smlogout.asp?mode=nih&AppReturnUrl="` | | +| FENCE_CONFIG.LOGIN_OPTIONS[0].desc | string | `"description"` | | +| FENCE_CONFIG.LOGIN_OPTIONS[0].idp | string | `"google"` | | +| FENCE_CONFIG.LOGIN_OPTIONS[0].name | string | `"Login from Google"` | | +| FENCE_CONFIG.LOGIN_REDIRECT_WHITELIST | list | `[]` | | +| FENCE_CONFIG.MAX_ACCESS_TOKEN_TTL | int | `3600` | | +| FENCE_CONFIG.MAX_API_KEY_TTL | int | `2592000` | | +| FENCE_CONFIG.MAX_PRESIGNED_URL_TTL | int | `3600` | | +| FENCE_CONFIG.MAX_ROLE_SESSION_INCREASE | bool | `false` | | +| FENCE_CONFIG.MOCK_AUTH | bool | `false` | | +| FENCE_CONFIG.MOCK_GOOGLE_AUTH | bool | `false` | | +| FENCE_CONFIG.MOCK_STORAGE | bool | `false` | | +| FENCE_CONFIG.OAUTH2_JWT_ALG | string | `"RS256"` | | +| FENCE_CONFIG.OAUTH2_JWT_ENABLED | bool | `true` | | +| FENCE_CONFIG.OAUTH2_JWT_ISS | string | `"{{BASE_URL}}"` | | +| FENCE_CONFIG.OAUTH2_PROVIDER_ERROR_URI | string | `"/api/oauth2/errors"` | | +| FENCE_CONFIG.OAUTH2_TOKEN_EXPIRES_IN.authorization_code | int | `1200` | | +| FENCE_CONFIG.OAUTH2_TOKEN_EXPIRES_IN.implicit | int | `1200` | | +| FENCE_CONFIG.OPENID_CONNECT.cilogon.client_id | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.cilogon.client_secret | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.cilogon.discovery_url | string | `"https://cilogon.org/.well-known/openid-configuration"` | | +| FENCE_CONFIG.OPENID_CONNECT.cilogon.mock | bool | `false` | | +| FENCE_CONFIG.OPENID_CONNECT.cilogon.mock_default_user | string | `"http://cilogon.org/serverT/users/64703"` | | +| FENCE_CONFIG.OPENID_CONNECT.cilogon.redirect_url | string | `"{{BASE_URL}}/login/cilogon/login/"` | | +| FENCE_CONFIG.OPENID_CONNECT.cilogon.scope | string | `"openid email profile"` | | +| FENCE_CONFIG.OPENID_CONNECT.cognito.client_id | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.cognito.client_secret | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.cognito.discovery_url | string | `"https://cognito-idp.{REGION}.amazonaws.com/{USER-POOL-ID}/.well-known/openid-configuration"` | | +| FENCE_CONFIG.OPENID_CONNECT.cognito.redirect_url | string | `"{{BASE_URL}}/login/cognito/login/"` | | +| FENCE_CONFIG.OPENID_CONNECT.cognito.scope | string | `"openid email"` | | +| FENCE_CONFIG.OPENID_CONNECT.fence.access_token_url | string | `"{{api_base_url}}/oauth2/token"` | | +| FENCE_CONFIG.OPENID_CONNECT.fence.api_base_url | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.fence.authorize_url | string | `"{{api_base_url}}/oauth2/authorize"` | | +| FENCE_CONFIG.OPENID_CONNECT.fence.client_id | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.fence.client_kwargs.redirect_uri | string | `"{{BASE_URL}}/login/fence/login"` | | +| FENCE_CONFIG.OPENID_CONNECT.fence.client_kwargs.scope | string | `"openid"` | | +| FENCE_CONFIG.OPENID_CONNECT.fence.client_secret | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.fence.mock | bool | `false` | | +| FENCE_CONFIG.OPENID_CONNECT.fence.mock_default_user | string | `"test@example.com"` | | +| FENCE_CONFIG.OPENID_CONNECT.fence.name | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.fence.refresh_token_url | string | `"{{api_base_url}}/oauth2/token"` | | +| FENCE_CONFIG.OPENID_CONNECT.fence.shibboleth_discovery_url | string | `"https://login.bionimbus.org/Shibboleth.sso/DiscoFeed"` | | +| FENCE_CONFIG.OPENID_CONNECT.generic_oidc_idp.client_id | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.generic_oidc_idp.client_secret | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.generic_oidc_idp.discovery.authorization_endpoint | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.generic_oidc_idp.discovery.jwks_uri | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.generic_oidc_idp.discovery.token_endpoint | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.generic_oidc_idp.discovery_url | string | `"https://server.com/.well-known/openid-configuration"` | | +| FENCE_CONFIG.OPENID_CONNECT.generic_oidc_idp.email_field | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.generic_oidc_idp.name | string | `"some_idp"` | | +| FENCE_CONFIG.OPENID_CONNECT.generic_oidc_idp.redirect_url | string | `"{{BASE_URL}}/login/some_idp/login"` | | +| FENCE_CONFIG.OPENID_CONNECT.generic_oidc_idp.scope | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.generic_oidc_idp.user_id_field | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.google.client_id | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.google.client_secret | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.google.discovery_url | string | `"https://accounts.google.com/.well-known/openid-configuration"` | | +| FENCE_CONFIG.OPENID_CONNECT.google.mock | string | `"{{MOCK_GOOGLE_AUTH}}"` | | +| FENCE_CONFIG.OPENID_CONNECT.google.mock_default_user | string | `"test@example.com"` | | +| FENCE_CONFIG.OPENID_CONNECT.google.redirect_url | string | `"{{BASE_URL}}/login/google/login/"` | | +| FENCE_CONFIG.OPENID_CONNECT.google.scope | string | `"openid email"` | | +| FENCE_CONFIG.OPENID_CONNECT.microsoft.client_id | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.microsoft.client_secret | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.microsoft.discovery_url | string | `"https://login.microsoftonline.com/organizations/v2.0/.well-known/openid-configuration"` | | +| FENCE_CONFIG.OPENID_CONNECT.microsoft.mock | bool | `false` | | +| FENCE_CONFIG.OPENID_CONNECT.microsoft.mock_default_user | string | `"test@example.com"` | | +| FENCE_CONFIG.OPENID_CONNECT.microsoft.redirect_url | string | `"{{BASE_URL}}/login/microsoft/login/"` | | +| FENCE_CONFIG.OPENID_CONNECT.microsoft.scope | string | `"openid email"` | | +| FENCE_CONFIG.OPENID_CONNECT.okta.client_id | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.okta.client_secret | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.okta.discovery_url | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.okta.redirect_url | string | `"{{BASE_URL}}/login/okta/login/"` | | +| FENCE_CONFIG.OPENID_CONNECT.okta.scope | string | `"openid email"` | | +| FENCE_CONFIG.OPENID_CONNECT.orcid.client_id | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.orcid.client_secret | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.orcid.discovery_url | string | `"https://orcid.org/.well-known/openid-configuration"` | | +| FENCE_CONFIG.OPENID_CONNECT.orcid.mock | bool | `false` | | +| FENCE_CONFIG.OPENID_CONNECT.orcid.mock_default_user | string | `"0000-0002-2601-8132"` | | +| FENCE_CONFIG.OPENID_CONNECT.orcid.redirect_url | string | `"{{BASE_URL}}/login/orcid/login/"` | | +| FENCE_CONFIG.OPENID_CONNECT.orcid.scope | string | `"openid"` | | +| FENCE_CONFIG.OPENID_CONNECT.ras.client_id | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.ras.client_secret | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.ras.discovery_url | string | `"https://sts.nih.gov/.well-known/openid-configuration"` | | +| FENCE_CONFIG.OPENID_CONNECT.ras.mock | bool | `false` | | +| FENCE_CONFIG.OPENID_CONNECT.ras.mock_default_user | string | `"test@example.com"` | | +| FENCE_CONFIG.OPENID_CONNECT.ras.redirect_url | string | `"{{BASE_URL}}/login/ras/callback"` | | +| FENCE_CONFIG.OPENID_CONNECT.ras.scope | string | `"openid email profile ga4gh_passport_v1"` | | +| FENCE_CONFIG.OPENID_CONNECT.shibboleth.client_id | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.shibboleth.client_secret | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.shibboleth.redirect_url | string | `"{{BASE_URL}}/login/shib/login"` | | +| FENCE_CONFIG.OPENID_CONNECT.synapse.client_id | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.synapse.client_secret | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.synapse.discovery_url | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.synapse.redirect_url | string | `""` | | +| FENCE_CONFIG.OPENID_CONNECT.synapse.scope | string | `"openid"` | | +| FENCE_CONFIG.OVERRIDE_NGINX_RATE_LIMIT | int | `18` | | +| FENCE_CONFIG.PRIVACY_POLICY_URL | string | `nil` | | +| FENCE_CONFIG.PROBLEM_USER_EMAIL_NOTIFICATION.admin[0] | string | `"admin@example.edu"` | | +| FENCE_CONFIG.PROBLEM_USER_EMAIL_NOTIFICATION.content | string | `"The Data Commons Framework utilizes dbGaP for data access authorization. Another member of a Google project you belong to ({}) is attempting to register a service account to the following additional datasets ({}). Please contact dbGaP to request access.\n"` | | +| FENCE_CONFIG.PROBLEM_USER_EMAIL_NOTIFICATION.domain | string | `"example.com"` | | +| FENCE_CONFIG.PROBLEM_USER_EMAIL_NOTIFICATION.from | string | `"do-not-reply@example.com"` | | +| FENCE_CONFIG.PROBLEM_USER_EMAIL_NOTIFICATION.subject | string | `"Account access error notification"` | | +| FENCE_CONFIG.PUSH_AUDIT_LOGS_CONFIG.aws_sqs_config.aws_cred | string | `nil` | | +| FENCE_CONFIG.PUSH_AUDIT_LOGS_CONFIG.aws_sqs_config.region | string | `nil` | | +| FENCE_CONFIG.PUSH_AUDIT_LOGS_CONFIG.aws_sqs_config.sqs_url | string | `nil` | | +| FENCE_CONFIG.PUSH_AUDIT_LOGS_CONFIG.type | string | `"aws_sqs"` | | +| FENCE_CONFIG.RAS_REFRESH_EXPIRATION | int | `1296000` | | +| FENCE_CONFIG.RAS_USERINFO_ENDPOINT | string | `"/openid/connect/v1.1/userinfo"` | | +| FENCE_CONFIG.REFRESH_TOKEN_EXPIRES_IN | int | `2592000` | | +| FENCE_CONFIG.REGISTERED_USERS_GROUP | string | `""` | | +| FENCE_CONFIG.REGISTER_USERS_ON | bool | `false` | | +| FENCE_CONFIG.REMOVE_SERVICE_ACCOUNT_EMAIL_NOTIFICATION.admin[0] | string | `"admin@example.edu"` | | +| FENCE_CONFIG.REMOVE_SERVICE_ACCOUNT_EMAIL_NOTIFICATION.content | string | `"Service accounts were removed from access control data because some users or service accounts of GCP Project {} are not authorized to access the data sets associated to the service accounts, or do not adhere to the security policies.\n"` | | +| FENCE_CONFIG.REMOVE_SERVICE_ACCOUNT_EMAIL_NOTIFICATION.domain | string | `"example.com"` | | +| FENCE_CONFIG.REMOVE_SERVICE_ACCOUNT_EMAIL_NOTIFICATION.enable | bool | `false` | | +| FENCE_CONFIG.REMOVE_SERVICE_ACCOUNT_EMAIL_NOTIFICATION.from | string | `"do-not-reply@example.com"` | | +| FENCE_CONFIG.REMOVE_SERVICE_ACCOUNT_EMAIL_NOTIFICATION.subject | string | `"User service account removal notification"` | | +| FENCE_CONFIG.RENEW_ACCESS_TOKEN_BEFORE_EXPIRATION | bool | `false` | | +| FENCE_CONFIG.S3_BUCKETS | object | `{}` | | +| FENCE_CONFIG.SEND_FROM | string | `"example@gmail.com"` | | +| FENCE_CONFIG.SEND_TO | string | `"example@gmail.com"` | | +| FENCE_CONFIG.SERVICE_ACCOUNT_LIMIT | int | `6` | | +| FENCE_CONFIG.SESSION_ALLOWED_SCOPES[0] | string | `"openid"` | | +| FENCE_CONFIG.SESSION_ALLOWED_SCOPES[1] | string | `"user"` | | +| FENCE_CONFIG.SESSION_ALLOWED_SCOPES[2] | string | `"credentials"` | | +| FENCE_CONFIG.SESSION_ALLOWED_SCOPES[3] | string | `"data"` | | +| FENCE_CONFIG.SESSION_ALLOWED_SCOPES[4] | string | `"admin"` | | +| FENCE_CONFIG.SESSION_ALLOWED_SCOPES[5] | string | `"google_credentials"` | | +| FENCE_CONFIG.SESSION_ALLOWED_SCOPES[6] | string | `"google_service_account"` | | +| FENCE_CONFIG.SESSION_ALLOWED_SCOPES[7] | string | `"google_link"` | | +| FENCE_CONFIG.SESSION_ALLOWED_SCOPES[8] | string | `"ga4gh_passport_v1"` | | +| FENCE_CONFIG.SESSION_COOKIE_DOMAIN | string | `nil` | | +| FENCE_CONFIG.SESSION_COOKIE_NAME | string | `"fence"` | | +| FENCE_CONFIG.SESSION_COOKIE_SECURE | bool | `true` | | +| FENCE_CONFIG.SESSION_LIFETIME | int | `28800` | | +| FENCE_CONFIG.SESSION_TIMEOUT | int | `1800` | | +| FENCE_CONFIG.SHIBBOLETH_HEADER | string | `"persistent_id"` | | +| FENCE_CONFIG.SSO_URL | string | `"https://auth.nih.gov/affwebservices/public/saml2sso?SPID={{BASE_URL}}/shibboleth&RelayState="` | | +| FENCE_CONFIG.STORAGE_CREDENTIALS | object | `{}` | | +| FENCE_CONFIG.SUPPORT_EMAIL_FOR_ERRORS | string | `nil` | | +| FENCE_CONFIG.SYNAPSE_AUTHZ_TTL | int | `86400` | | +| FENCE_CONFIG.SYNAPSE_DISCOVERY_URL | string | `nil` | | +| FENCE_CONFIG.SYNAPSE_JWKS_URI | string | `nil` | | +| FENCE_CONFIG.SYNAPSE_URI | string | `"https://repo-prod.prod.sagebase.org/auth/v1"` | | +| FENCE_CONFIG.TOKEN_PROJECTS_CUTOFF | int | `10` | | +| FENCE_CONFIG.USERSYNC.fallback_to_dbgap_sftp | bool | `false` | | +| FENCE_CONFIG.USERSYNC.sync_from_visas | bool | `false` | | +| FENCE_CONFIG.USERSYNC.visa_types.ras[0] | string | `"https://ras.nih.gov/visas/v1"` | | +| FENCE_CONFIG.USERSYNC.visa_types.ras[1] | string | `"https://ras.nih.gov/visas/v1.1"` | | +| FENCE_CONFIG.USER_ALLOWED_SCOPES[0] | string | `"fence"` | | +| FENCE_CONFIG.USER_ALLOWED_SCOPES[1] | string | `"openid"` | | +| FENCE_CONFIG.USER_ALLOWED_SCOPES[2] | string | `"user"` | | +| FENCE_CONFIG.USER_ALLOWED_SCOPES[3] | string | `"data"` | | +| FENCE_CONFIG.USER_ALLOWED_SCOPES[4] | string | `"admin"` | | +| FENCE_CONFIG.USER_ALLOWED_SCOPES[5] | string | `"google_credentials"` | | +| FENCE_CONFIG.USER_ALLOWED_SCOPES[6] | string | `"google_service_account"` | | +| FENCE_CONFIG.USER_ALLOWED_SCOPES[7] | string | `"google_link"` | | +| FENCE_CONFIG.USER_ALLOWED_SCOPES[8] | string | `"ga4gh_passport_v1"` | | +| FENCE_CONFIG.WHITE_LISTED_GOOGLE_PARENT_ORGS | list | `[]` | | +| FENCE_CONFIG.WHITE_LISTED_SERVICE_ACCOUNT_EMAILS | list | `[]` | | +| FENCE_CONFIG.WTF_CSRF_SECRET_KEY | string | `"{{ENCRYPTION_KEY}}"` | | +| FENCE_CONFIG.dbGaP[0].decrypt_key | string | `""` | | +| FENCE_CONFIG.dbGaP[0].enable_common_exchange_area_access | bool | `false` | | +| FENCE_CONFIG.dbGaP[0].info.host | string | `""` | | +| FENCE_CONFIG.dbGaP[0].info.password | string | `""` | | +| FENCE_CONFIG.dbGaP[0].info.port | int | `22` | | +| FENCE_CONFIG.dbGaP[0].info.proxy | string | `""` | | +| FENCE_CONFIG.dbGaP[0].info.proxy_user | string | `""` | | +| FENCE_CONFIG.dbGaP[0].info.username | string | `""` | | +| FENCE_CONFIG.dbGaP[0].parse_consent_code | bool | `true` | | +| FENCE_CONFIG.dbGaP[0].protocol | string | `"sftp"` | | +| FENCE_CONFIG.dbGaP[0].study_common_exchange_areas.example | string | `"test_common_exchange_area"` | | +| FENCE_CONFIG.dbGaP[0].study_to_resource_namespaces._default[0] | string | `"/"` | | +| FENCE_CONFIG.dbGaP[0].study_to_resource_namespaces.test_common_exchange_area[0] | string | `"/dbgap/"` | | +| USER_YAML.authz.all_users_policies[0] | string | `"open_data_reader"` | | +| USER_YAML.authz.all_users_policies[1] | string | `"authn_open_access"` | | +| USER_YAML.authz.anonymous_policies[0] | string | `"open_data_reader"` | | +| USER_YAML.authz.anonymous_policies[1] | string | `"full_open_access"` | | +| USER_YAML.authz.policies[0].description | string | `"be able to use workspace"` | | +| USER_YAML.authz.policies[0].id | string | `"workspace"` | | +| USER_YAML.authz.policies[0].resource_paths[0] | string | `"/workspace"` | | +| USER_YAML.authz.policies[0].role_ids[0] | string | `"workspace_user"` | | +| USER_YAML.authz.policies[10].id | string | `"audit_presigned_url_reader"` | | +| USER_YAML.authz.policies[10].resource_paths[0] | string | `"/services/audit/presigned_url"` | | +| USER_YAML.authz.policies[10].role_ids[0] | string | `"audit_reader"` | | +| USER_YAML.authz.policies[11].id | string | `"requestor_admin"` | | +| USER_YAML.authz.policies[11].resource_paths[0] | string | `"/programs"` | | +| USER_YAML.authz.policies[11].role_ids[0] | string | `"requestor_admin"` | | +| USER_YAML.authz.policies[12].id | string | `"requestor_reader"` | | +| USER_YAML.authz.policies[12].resource_paths[0] | string | `"/programs"` | | +| USER_YAML.authz.policies[12].role_ids[0] | string | `"requestor_reader"` | | +| USER_YAML.authz.policies[13].id | string | `"requestor_creator"` | | +| USER_YAML.authz.policies[13].resource_paths[0] | string | `"/programs"` | | +| USER_YAML.authz.policies[13].role_ids[0] | string | `"requestor_creator"` | | +| USER_YAML.authz.policies[14].id | string | `"requestor_updater"` | | +| USER_YAML.authz.policies[14].resource_paths[0] | string | `"/programs"` | | +| USER_YAML.authz.policies[14].role_ids[0] | string | `"requestor_updater"` | | +| USER_YAML.authz.policies[15].id | string | `"requestor_deleter"` | | +| USER_YAML.authz.policies[15].resource_paths[0] | string | `"/programs"` | | +| USER_YAML.authz.policies[15].role_ids[0] | string | `"requestor_deleter"` | | +| USER_YAML.authz.policies[16].description | string | `""` | | +| USER_YAML.authz.policies[16].id | string | `"all_programs_reader"` | | +| USER_YAML.authz.policies[16].resource_paths[0] | string | `"/programs"` | | +| USER_YAML.authz.policies[16].role_ids[0] | string | `"reader"` | | +| USER_YAML.authz.policies[16].role_ids[1] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[17].description | string | `""` | | +| USER_YAML.authz.policies[17].id | string | `"programs.jnkns-admin"` | | +| USER_YAML.authz.policies[17].resource_paths[0] | string | `"/programs/jnkns"` | | +| USER_YAML.authz.policies[17].resource_paths[1] | string | `"/gen3/programs/jnkns"` | | +| USER_YAML.authz.policies[17].role_ids[0] | string | `"creator"` | | +| USER_YAML.authz.policies[17].role_ids[1] | string | `"reader"` | | +| USER_YAML.authz.policies[17].role_ids[2] | string | `"updater"` | | +| USER_YAML.authz.policies[17].role_ids[3] | string | `"deleter"` | | +| USER_YAML.authz.policies[17].role_ids[4] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[18].description | string | `""` | | +| USER_YAML.authz.policies[18].id | string | `"programs.jnkns-viewer"` | | +| USER_YAML.authz.policies[18].resource_paths[0] | string | `"/programs/jnkns"` | | +| USER_YAML.authz.policies[18].resource_paths[1] | string | `"/gen3/programs/jnkns"` | | +| USER_YAML.authz.policies[18].role_ids[0] | string | `"reader"` | | +| USER_YAML.authz.policies[18].role_ids[1] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[19].description | string | `""` | | +| USER_YAML.authz.policies[19].id | string | `"programs.QA-admin"` | | +| USER_YAML.authz.policies[19].resource_paths[0] | string | `"/programs/QA"` | | +| USER_YAML.authz.policies[19].resource_paths[1] | string | `"/gen3/programs/QA"` | | +| USER_YAML.authz.policies[19].role_ids[0] | string | `"creator"` | | +| USER_YAML.authz.policies[19].role_ids[1] | string | `"reader"` | | +| USER_YAML.authz.policies[19].role_ids[2] | string | `"updater"` | | +| USER_YAML.authz.policies[19].role_ids[3] | string | `"deleter"` | | +| USER_YAML.authz.policies[19].role_ids[4] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[1].description | string | `"be able to use the commons dashboard"` | | +| USER_YAML.authz.policies[1].id | string | `"dashboard"` | | +| USER_YAML.authz.policies[1].resource_paths[0] | string | `"/dashboard"` | | +| USER_YAML.authz.policies[1].role_ids[0] | string | `"dashboard_user"` | | +| USER_YAML.authz.policies[20].description | string | `""` | | +| USER_YAML.authz.policies[20].id | string | `"programs.QA-admin-no-storage"` | | +| USER_YAML.authz.policies[20].resource_paths[0] | string | `"/programs/QA"` | | +| USER_YAML.authz.policies[20].resource_paths[1] | string | `"/gen3/programs/QA"` | | +| USER_YAML.authz.policies[20].role_ids[0] | string | `"creator"` | | +| USER_YAML.authz.policies[20].role_ids[1] | string | `"reader"` | | +| USER_YAML.authz.policies[20].role_ids[2] | string | `"updater"` | | +| USER_YAML.authz.policies[20].role_ids[3] | string | `"deleter"` | | +| USER_YAML.authz.policies[21].description | string | `""` | | +| USER_YAML.authz.policies[21].id | string | `"programs.QA-viewer"` | | +| USER_YAML.authz.policies[21].resource_paths[0] | string | `"/programs/QA"` | | +| USER_YAML.authz.policies[21].resource_paths[1] | string | `"/gen3/programs/QA"` | | +| USER_YAML.authz.policies[21].role_ids[0] | string | `"reader"` | | +| USER_YAML.authz.policies[21].role_ids[1] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[22].description | string | `""` | | +| USER_YAML.authz.policies[22].id | string | `"programs.DEV-admin"` | | +| USER_YAML.authz.policies[22].resource_paths[0] | string | `"/programs/DEV"` | | +| USER_YAML.authz.policies[22].resource_paths[1] | string | `"/gen3/programs/DEV"` | | +| USER_YAML.authz.policies[22].role_ids[0] | string | `"creator"` | | +| USER_YAML.authz.policies[22].role_ids[1] | string | `"reader"` | | +| USER_YAML.authz.policies[22].role_ids[2] | string | `"updater"` | | +| USER_YAML.authz.policies[22].role_ids[3] | string | `"deleter"` | | +| USER_YAML.authz.policies[22].role_ids[4] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[22].role_ids[5] | string | `"storage_writer"` | | +| USER_YAML.authz.policies[23].description | string | `""` | | +| USER_YAML.authz.policies[23].id | string | `"programs.DEV-storage_writer"` | | +| USER_YAML.authz.policies[23].resource_paths[0] | string | `"/programs/DEV"` | | +| USER_YAML.authz.policies[23].role_ids[0] | string | `"storage_writer"` | | +| USER_YAML.authz.policies[24].description | string | `""` | | +| USER_YAML.authz.policies[24].id | string | `"programs.DEV-viewer"` | | +| USER_YAML.authz.policies[24].resource_paths[0] | string | `"/programs/DEV"` | | +| USER_YAML.authz.policies[24].resource_paths[1] | string | `"/gen3/programs/DEV"` | | +| USER_YAML.authz.policies[24].role_ids[0] | string | `"reader"` | | +| USER_YAML.authz.policies[24].role_ids[1] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[25].description | string | `""` | | +| USER_YAML.authz.policies[25].id | string | `"programs.test-admin"` | | +| USER_YAML.authz.policies[25].resource_paths[0] | string | `"/programs/test"` | | +| USER_YAML.authz.policies[25].resource_paths[1] | string | `"/gen3/programs/test"` | | +| USER_YAML.authz.policies[25].role_ids[0] | string | `"creator"` | | +| USER_YAML.authz.policies[25].role_ids[1] | string | `"reader"` | | +| USER_YAML.authz.policies[25].role_ids[2] | string | `"updater"` | | +| USER_YAML.authz.policies[25].role_ids[3] | string | `"deleter"` | | +| USER_YAML.authz.policies[25].role_ids[4] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[26].description | string | `""` | | +| USER_YAML.authz.policies[26].id | string | `"programs.test-viewer"` | | +| USER_YAML.authz.policies[26].resource_paths[0] | string | `"/programs/test"` | | +| USER_YAML.authz.policies[26].resource_paths[1] | string | `"/gen3/programs/test"` | | +| USER_YAML.authz.policies[26].role_ids[0] | string | `"reader"` | | +| USER_YAML.authz.policies[26].role_ids[1] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[27].description | string | `""` | | +| USER_YAML.authz.policies[27].id | string | `"abc-admin"` | | +| USER_YAML.authz.policies[27].resource_paths[0] | string | `"/abc"` | | +| USER_YAML.authz.policies[27].role_ids[0] | string | `"creator"` | | +| USER_YAML.authz.policies[27].role_ids[1] | string | `"reader"` | | +| USER_YAML.authz.policies[27].role_ids[2] | string | `"updater"` | | +| USER_YAML.authz.policies[27].role_ids[3] | string | `"deleter"` | | +| USER_YAML.authz.policies[27].role_ids[4] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[28].description | string | `""` | | +| USER_YAML.authz.policies[28].id | string | `"gen3-admin"` | | +| USER_YAML.authz.policies[28].resource_paths[0] | string | `"/gen3"` | | +| USER_YAML.authz.policies[28].role_ids[0] | string | `"creator"` | | +| USER_YAML.authz.policies[28].role_ids[1] | string | `"reader"` | | +| USER_YAML.authz.policies[28].role_ids[2] | string | `"updater"` | | +| USER_YAML.authz.policies[28].role_ids[3] | string | `"deleter"` | | +| USER_YAML.authz.policies[28].role_ids[4] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[29].description | string | `""` | | +| USER_YAML.authz.policies[29].id | string | `"gen3-hmb-researcher"` | | +| USER_YAML.authz.policies[29].resource_paths[0] | string | `"/consents/NRES"` | | +| USER_YAML.authz.policies[29].resource_paths[1] | string | `"/consents/GRU"` | | +| USER_YAML.authz.policies[29].resource_paths[2] | string | `"/consents/GRU_CC"` | | +| USER_YAML.authz.policies[29].resource_paths[3] | string | `"/consents/HMB"` | | +| USER_YAML.authz.policies[29].resource_paths[4] | string | `"/gen3"` | | +| USER_YAML.authz.policies[29].role_ids[0] | string | `"creator"` | | +| USER_YAML.authz.policies[29].role_ids[1] | string | `"reader"` | | +| USER_YAML.authz.policies[29].role_ids[2] | string | `"updater"` | | +| USER_YAML.authz.policies[29].role_ids[3] | string | `"deleter"` | | +| USER_YAML.authz.policies[29].role_ids[4] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[2].description | string | `"be able to use prometheus"` | | +| USER_YAML.authz.policies[2].id | string | `"prometheus"` | | +| USER_YAML.authz.policies[2].resource_paths[0] | string | `"/prometheus"` | | +| USER_YAML.authz.policies[2].role_ids[0] | string | `"prometheus_user"` | | +| USER_YAML.authz.policies[30].description | string | `""` | | +| USER_YAML.authz.policies[30].id | string | `"abc.programs.test_program.projects.test_project1-viewer"` | | +| USER_YAML.authz.policies[30].resource_paths[0] | string | `"/abc/programs/test_program/projects/test_project1"` | | +| USER_YAML.authz.policies[30].role_ids[0] | string | `"reader"` | | +| USER_YAML.authz.policies[30].role_ids[1] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[31].description | string | `""` | | +| USER_YAML.authz.policies[31].id | string | `"abc.programs.test_program.projects.test_project2-viewer"` | | +| USER_YAML.authz.policies[31].resource_paths[0] | string | `"/abc/programs/test_program/projects/test_project2"` | | +| USER_YAML.authz.policies[31].role_ids[0] | string | `"reader"` | | +| USER_YAML.authz.policies[31].role_ids[1] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[32].description | string | `""` | | +| USER_YAML.authz.policies[32].id | string | `"abc.programs.test_program2.projects.test_project3-viewer"` | | +| USER_YAML.authz.policies[32].resource_paths[0] | string | `"/abc/programs/test_program2/projects/test_project3"` | | +| USER_YAML.authz.policies[32].role_ids[0] | string | `"reader"` | | +| USER_YAML.authz.policies[32].role_ids[1] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[33].description | string | `""` | | +| USER_YAML.authz.policies[33].id | string | `"authn_open_access"` | | +| USER_YAML.authz.policies[33].resource_paths[0] | string | `"/programs/open/projects/authnRequired"` | | +| USER_YAML.authz.policies[33].role_ids[0] | string | `"reader"` | | +| USER_YAML.authz.policies[33].role_ids[1] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[34].description | string | `""` | | +| USER_YAML.authz.policies[34].id | string | `"full_open_access"` | | +| USER_YAML.authz.policies[34].resource_paths[0] | string | `"/programs/open/projects/1000G"` | | +| USER_YAML.authz.policies[34].role_ids[0] | string | `"reader"` | | +| USER_YAML.authz.policies[34].role_ids[1] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[35].description | string | `""` | | +| USER_YAML.authz.policies[35].id | string | `"open_data_reader"` | | +| USER_YAML.authz.policies[35].resource_paths[0] | string | `"/open"` | | +| USER_YAML.authz.policies[35].role_ids[0] | string | `"reader"` | | +| USER_YAML.authz.policies[35].role_ids[1] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[36].description | string | `""` | | +| USER_YAML.authz.policies[36].id | string | `"open_data_admin"` | | +| USER_YAML.authz.policies[36].resource_paths[0] | string | `"/open"` | | +| USER_YAML.authz.policies[36].role_ids[0] | string | `"creator"` | | +| USER_YAML.authz.policies[36].role_ids[1] | string | `"reader"` | | +| USER_YAML.authz.policies[36].role_ids[2] | string | `"updater"` | | +| USER_YAML.authz.policies[36].role_ids[3] | string | `"deleter"` | | +| USER_YAML.authz.policies[36].role_ids[4] | string | `"storage_writer"` | | +| USER_YAML.authz.policies[36].role_ids[5] | string | `"storage_reader"` | | +| USER_YAML.authz.policies[37].description | string | `""` | | +| USER_YAML.authz.policies[37].id | string | `"not-for-profit-researcher"` | | +| USER_YAML.authz.policies[37].resource_paths[0] | string | `"/consents/NPU"` | | +| USER_YAML.authz.policies[37].role_ids[0] | string | `"admin"` | | +| USER_YAML.authz.policies[38].description | string | `""` | | +| USER_YAML.authz.policies[38].id | string | `"publication-required-researcher"` | | +| USER_YAML.authz.policies[38].resource_paths[0] | string | `"/consents/PUB"` | | +| USER_YAML.authz.policies[38].role_ids[0] | string | `"admin"` | | +| USER_YAML.authz.policies[39].description | string | `""` | | +| USER_YAML.authz.policies[39].id | string | `"gru-researcher"` | | +| USER_YAML.authz.policies[39].resource_paths[0] | string | `"/consents/NRES"` | | +| USER_YAML.authz.policies[39].resource_paths[1] | string | `"/consents/GRU"` | | +| USER_YAML.authz.policies[39].role_ids[0] | string | `"admin"` | | +| USER_YAML.authz.policies[3].description | string | `"be able to use the admin tty"` | | +| USER_YAML.authz.policies[3].id | string | `"ttyadmin"` | | +| USER_YAML.authz.policies[3].resource_paths[0] | string | `"/ttyadmin"` | | +| USER_YAML.authz.policies[3].role_ids[0] | string | `"ttyadmin_user"` | | +| USER_YAML.authz.policies[40].description | string | `""` | | +| USER_YAML.authz.policies[40].id | string | `"gru-cc-researcher"` | | +| USER_YAML.authz.policies[40].resource_paths[0] | string | `"/consents/NRES"` | | +| USER_YAML.authz.policies[40].resource_paths[1] | string | `"/consents/GRU"` | | +| USER_YAML.authz.policies[40].resource_paths[2] | string | `"/consents/GRU_CC"` | | +| USER_YAML.authz.policies[40].role_ids[0] | string | `"admin"` | | +| USER_YAML.authz.policies[41].description | string | `""` | | +| USER_YAML.authz.policies[41].id | string | `"hmb-researcher"` | | +| USER_YAML.authz.policies[41].resource_paths[0] | string | `"/consents/NRES"` | | +| USER_YAML.authz.policies[41].resource_paths[1] | string | `"/consents/GRU"` | | +| USER_YAML.authz.policies[41].resource_paths[2] | string | `"/consents/GRU_CC"` | | +| USER_YAML.authz.policies[41].resource_paths[3] | string | `"/consents/HMB"` | | +| USER_YAML.authz.policies[41].role_ids[0] | string | `"admin"` | | +| USER_YAML.authz.policies[42].description | string | `""` | | +| USER_YAML.authz.policies[42].id | string | `"poa-researcher"` | | +| USER_YAML.authz.policies[42].resource_paths[0] | string | `"/consents/NRES"` | | +| USER_YAML.authz.policies[42].resource_paths[1] | string | `"/consents/GRU"` | | +| USER_YAML.authz.policies[42].resource_paths[2] | string | `"/consents/GRU_CC"` | | +| USER_YAML.authz.policies[42].resource_paths[3] | string | `"/consents/POA"` | | +| USER_YAML.authz.policies[42].role_ids[0] | string | `"admin"` | | +| USER_YAML.authz.policies[43].description | string | `""` | | +| USER_YAML.authz.policies[43].id | string | `"ds-lung-researcher"` | | +| USER_YAML.authz.policies[43].resource_paths[0] | string | `"/consents/NRES"` | | +| USER_YAML.authz.policies[43].resource_paths[1] | string | `"/consents/GRU"` | | +| USER_YAML.authz.policies[43].resource_paths[2] | string | `"/consents/GRU_CC"` | | +| USER_YAML.authz.policies[43].resource_paths[3] | string | `"/consents/HMB"` | | +| USER_YAML.authz.policies[43].resource_paths[4] | string | `"/consents/DS_LungDisease"` | | +| USER_YAML.authz.policies[43].role_ids[0] | string | `"admin"` | | +| USER_YAML.authz.policies[44].description | string | `""` | | +| USER_YAML.authz.policies[44].id | string | `"ds-chronic-obstructive-pulmonary-disease-researcher"` | | +| USER_YAML.authz.policies[44].resource_paths[0] | string | `"/consents/NRES"` | | +| USER_YAML.authz.policies[44].resource_paths[1] | string | `"/consents/GRU"` | | +| USER_YAML.authz.policies[44].resource_paths[2] | string | `"/consents/GRU_CC"` | | +| USER_YAML.authz.policies[44].resource_paths[3] | string | `"/consents/HMB"` | | +| USER_YAML.authz.policies[44].resource_paths[4] | string | `"/consents/DS_ChronicObstructivePulmonaryDisease"` | | +| USER_YAML.authz.policies[44].role_ids[0] | string | `"admin"` | | +| USER_YAML.authz.policies[45].description | string | `"CRUD access to programs and projects"` | | +| USER_YAML.authz.policies[45].id | string | `"services.sheepdog-admin"` | | +| USER_YAML.authz.policies[45].resource_paths[0] | string | `"/services/sheepdog/submission/program"` | | +| USER_YAML.authz.policies[45].resource_paths[1] | string | `"/services/sheepdog/submission/project"` | | +| USER_YAML.authz.policies[45].role_ids[0] | string | `"sheepdog_admin"` | | +| USER_YAML.authz.policies[46].description | string | `"full access to indexd API"` | | +| USER_YAML.authz.policies[46].id | string | `"indexd_admin"` | | +| USER_YAML.authz.policies[46].resource_paths[0] | string | `"/programs"` | | +| USER_YAML.authz.policies[46].resource_paths[1] | string | `"/services/indexd/admin"` | | +| USER_YAML.authz.policies[46].role_ids[0] | string | `"indexd_admin"` | | +| USER_YAML.authz.policies[47].description | string | `"be able to use argo"` | | +| USER_YAML.authz.policies[47].id | string | `"argo"` | | +| USER_YAML.authz.policies[47].resource_paths[0] | string | `"/argo"` | | +| USER_YAML.authz.policies[47].role_ids[0] | string | `"argo_user"` | | +| USER_YAML.authz.policies[4].description | string | `"be able to use metadata service"` | | +| USER_YAML.authz.policies[4].id | string | `"mds_admin"` | | +| USER_YAML.authz.policies[4].resource_paths[0] | string | `"/mds_gateway"` | | +| USER_YAML.authz.policies[4].role_ids[0] | string | `"mds_user"` | | +| USER_YAML.authz.policies[5].description | string | `"upload raw data files to S3"` | | +| USER_YAML.authz.policies[5].id | string | `"data_upload"` | | +| USER_YAML.authz.policies[5].resource_paths[0] | string | `"/data_file"` | | +| USER_YAML.authz.policies[5].role_ids[0] | string | `"file_uploader"` | | +| USER_YAML.authz.policies[6].description | string | `"be able to use sower job"` | | +| USER_YAML.authz.policies[6].id | string | `"sower"` | | +| USER_YAML.authz.policies[6].resource_paths[0] | string | `"/sower"` | | +| USER_YAML.authz.policies[6].role_ids[0] | string | `"sower_user"` | | +| USER_YAML.authz.policies[7].description | string | `"full access to mariner API"` | | +| USER_YAML.authz.policies[7].id | string | `"mariner_admin"` | | +| USER_YAML.authz.policies[7].resource_paths[0] | string | `"/mariner"` | | +| USER_YAML.authz.policies[7].role_ids[0] | string | `"mariner_admin"` | | +| USER_YAML.authz.policies[8].id | string | `"audit_reader"` | | +| USER_YAML.authz.policies[8].resource_paths[0] | string | `"/services/audit"` | | +| USER_YAML.authz.policies[8].role_ids[0] | string | `"audit_reader"` | | +| USER_YAML.authz.policies[9].id | string | `"audit_login_reader"` | | +| USER_YAML.authz.policies[9].resource_paths[0] | string | `"/services/audit/login"` | | +| USER_YAML.authz.policies[9].role_ids[0] | string | `"audit_reader"` | | +| USER_YAML.authz.resources[0].description | string | `"data files, stored in S3"` | | +| USER_YAML.authz.resources[0].name | string | `"data_file"` | | +| USER_YAML.authz.resources[10].name | string | `"gen3"` | | +| USER_YAML.authz.resources[10].subresources[0].name | string | `"programs"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[0].name | string | `"QA"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[0].subresources[0].name | string | `"projects"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[0].subresources[0].subresources[0].name | string | `"test"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[1].name | string | `"DEV"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[1].subresources[0].name | string | `"projects"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[1].subresources[0].subresources[0].name | string | `"test"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[2].name | string | `"jnkns"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[2].subresources[0].name | string | `"projects"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[2].subresources[0].subresources[0].name | string | `"jenkins"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[2].subresources[0].subresources[1].name | string | `"jenkins2"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[3].name | string | `"test"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[3].subresources[0].name | string | `"projects"` | | +| USER_YAML.authz.resources[10].subresources[0].subresources[3].subresources[0].subresources[0].name | string | `"test"` | | +| USER_YAML.authz.resources[11].name | string | `"consents"` | | +| USER_YAML.authz.resources[11].subresources[0].description | string | `"no restriction"` | | +| USER_YAML.authz.resources[11].subresources[0].name | string | `"NRES"` | | +| USER_YAML.authz.resources[11].subresources[1].description | string | `"general research use"` | | +| USER_YAML.authz.resources[11].subresources[1].name | string | `"GRU"` | | +| USER_YAML.authz.resources[11].subresources[2].description | string | `"general research use and clinical care"` | | +| USER_YAML.authz.resources[11].subresources[2].name | string | `"GRU_CC"` | | +| USER_YAML.authz.resources[11].subresources[3].description | string | `"health/medical/biomedical research"` | | +| USER_YAML.authz.resources[11].subresources[3].name | string | `"HMB"` | | +| USER_YAML.authz.resources[11].subresources[4].description | string | `"population origins or ancestry research"` | | +| USER_YAML.authz.resources[11].subresources[4].name | string | `"POA"` | | +| USER_YAML.authz.resources[11].subresources[5].description | string | `"no general methods research"` | | +| USER_YAML.authz.resources[11].subresources[5].name | string | `"NMDS"` | | +| USER_YAML.authz.resources[11].subresources[6].description | string | `"not-for-profit use only"` | | +| USER_YAML.authz.resources[11].subresources[6].name | string | `"NPU"` | | +| USER_YAML.authz.resources[11].subresources[7].description | string | `"publication required"` | | +| USER_YAML.authz.resources[11].subresources[7].name | string | `"PUB"` | | +| USER_YAML.authz.resources[11].subresources[8].description | string | `"disease-specific research for lung disease"` | | +| USER_YAML.authz.resources[11].subresources[8].name | string | `"DS_LungDisease"` | | +| USER_YAML.authz.resources[11].subresources[9].description | string | `"disease-specific research for chronic obstructive pulmonary disease"` | | +| USER_YAML.authz.resources[11].subresources[9].name | string | `"DS_ChronicObstructivePulmonaryDisease"` | | +| USER_YAML.authz.resources[12].name | string | `"abc"` | | +| USER_YAML.authz.resources[12].subresources[0].name | string | `"programs"` | | +| USER_YAML.authz.resources[12].subresources[0].subresources[0].name | string | `"foo"` | | +| USER_YAML.authz.resources[12].subresources[0].subresources[0].subresources[0].name | string | `"projects"` | | +| USER_YAML.authz.resources[12].subresources[0].subresources[0].subresources[0].subresources[0].name | string | `"bar"` | | +| USER_YAML.authz.resources[12].subresources[0].subresources[1].name | string | `"test_program"` | | +| USER_YAML.authz.resources[12].subresources[0].subresources[1].subresources[0].name | string | `"projects"` | | +| USER_YAML.authz.resources[12].subresources[0].subresources[1].subresources[0].subresources[0].name | string | `"test_project1"` | | +| USER_YAML.authz.resources[12].subresources[0].subresources[1].subresources[0].subresources[1].name | string | `"test_project2"` | | +| USER_YAML.authz.resources[12].subresources[0].subresources[2].name | string | `"test_program2"` | | +| USER_YAML.authz.resources[12].subresources[0].subresources[2].subresources[0].name | string | `"projects"` | | +| USER_YAML.authz.resources[12].subresources[0].subresources[2].subresources[0].subresources[0].name | string | `"test_project3"` | | +| USER_YAML.authz.resources[13].name | string | `"services"` | | +| USER_YAML.authz.resources[13].subresources[0].name | string | `"sheepdog"` | | +| USER_YAML.authz.resources[13].subresources[0].subresources[0].name | string | `"submission"` | | +| USER_YAML.authz.resources[13].subresources[0].subresources[0].subresources[0].name | string | `"program"` | | +| USER_YAML.authz.resources[13].subresources[0].subresources[0].subresources[1].name | string | `"project"` | | +| USER_YAML.authz.resources[13].subresources[1].name | string | `"indexd"` | | +| USER_YAML.authz.resources[13].subresources[1].subresources[0].name | string | `"admin"` | | +| USER_YAML.authz.resources[13].subresources[1].subresources[1].name | string | `"bundles"` | | +| USER_YAML.authz.resources[13].subresources[2].name | string | `"audit"` | | +| USER_YAML.authz.resources[13].subresources[2].subresources[0].name | string | `"presigned_url"` | | +| USER_YAML.authz.resources[13].subresources[2].subresources[1].name | string | `"login"` | | +| USER_YAML.authz.resources[14].name | string | `"open"` | | +| USER_YAML.authz.resources[1].description | string | `"commons /dashboard"` | | +| USER_YAML.authz.resources[1].name | string | `"dashboard"` | | +| USER_YAML.authz.resources[2].description | string | `"commons /mds-admin"` | | +| USER_YAML.authz.resources[2].name | string | `"mds_gateway"` | | +| USER_YAML.authz.resources[3].description | string | `"commons /prometheus and /grafana"` | | +| USER_YAML.authz.resources[3].name | string | `"prometheus"` | | +| USER_YAML.authz.resources[4].description | string | `"commons /ttyadmin"` | | +| USER_YAML.authz.resources[4].name | string | `"ttyadmin"` | | +| USER_YAML.authz.resources[5].name | string | `"workspace"` | | +| USER_YAML.authz.resources[6].name | string | `"sower"` | | +| USER_YAML.authz.resources[7].description | string | `"workflow execution service"` | | +| USER_YAML.authz.resources[7].name | string | `"mariner"` | | +| USER_YAML.authz.resources[8].name | string | `"argo"` | | +| USER_YAML.authz.resources[9].name | string | `"programs"` | | +| USER_YAML.authz.resources[9].subresources[0].name | string | `"open"` | | +| USER_YAML.authz.resources[9].subresources[0].subresources[0].name | string | `"projects"` | | +| USER_YAML.authz.resources[9].subresources[0].subresources[0].subresources[0].name | string | `"1000G"` | | +| USER_YAML.authz.resources[9].subresources[0].subresources[0].subresources[1].name | string | `"authnRequired"` | | +| USER_YAML.authz.resources[9].subresources[1].name | string | `"QA"` | | +| USER_YAML.authz.resources[9].subresources[1].subresources[0].name | string | `"projects"` | | +| USER_YAML.authz.resources[9].subresources[1].subresources[0].subresources[0].name | string | `"test"` | | +| USER_YAML.authz.resources[9].subresources[2].name | string | `"DEV"` | | +| USER_YAML.authz.resources[9].subresources[2].subresources[0].name | string | `"projects"` | | +| USER_YAML.authz.resources[9].subresources[2].subresources[0].subresources[0].name | string | `"test"` | | +| USER_YAML.authz.resources[9].subresources[3].name | string | `"jnkns"` | | +| USER_YAML.authz.resources[9].subresources[3].subresources[0].name | string | `"projects"` | | +| USER_YAML.authz.resources[9].subresources[3].subresources[0].subresources[0].name | string | `"jenkins"` | | +| USER_YAML.authz.resources[9].subresources[3].subresources[0].subresources[1].name | string | `"jenkins2"` | | +| USER_YAML.authz.resources[9].subresources[4].name | string | `"test"` | | +| USER_YAML.authz.resources[9].subresources[4].subresources[0].name | string | `"projects"` | | +| USER_YAML.authz.resources[9].subresources[4].subresources[0].subresources[0].name | string | `"test"` | | +| USER_YAML.authz.roles[0].description | string | `"can upload data files"` | | +| USER_YAML.authz.roles[0].id | string | `"file_uploader"` | | +| USER_YAML.authz.roles[0].permissions[0].action.method | string | `"file_upload"` | | +| USER_YAML.authz.roles[0].permissions[0].action.service | string | `"*"` | | +| USER_YAML.authz.roles[0].permissions[0].id | string | `"file_upload"` | | +| USER_YAML.authz.roles[10].description | string | `""` | | +| USER_YAML.authz.roles[10].id | string | `"creator"` | | +| USER_YAML.authz.roles[10].permissions[0].action.method | string | `"create"` | | +| USER_YAML.authz.roles[10].permissions[0].action.service | string | `"*"` | | +| USER_YAML.authz.roles[10].permissions[0].id | string | `"creator"` | | +| USER_YAML.authz.roles[11].description | string | `""` | | +| USER_YAML.authz.roles[11].id | string | `"reader"` | | +| USER_YAML.authz.roles[11].permissions[0].action.method | string | `"read"` | | +| USER_YAML.authz.roles[11].permissions[0].action.service | string | `"*"` | | +| USER_YAML.authz.roles[11].permissions[0].id | string | `"reader"` | | +| USER_YAML.authz.roles[12].description | string | `""` | | +| USER_YAML.authz.roles[12].id | string | `"updater"` | | +| USER_YAML.authz.roles[12].permissions[0].action.method | string | `"update"` | | +| USER_YAML.authz.roles[12].permissions[0].action.service | string | `"*"` | | +| USER_YAML.authz.roles[12].permissions[0].id | string | `"updater"` | | +| USER_YAML.authz.roles[13].description | string | `""` | | +| USER_YAML.authz.roles[13].id | string | `"deleter"` | | +| USER_YAML.authz.roles[13].permissions[0].action.method | string | `"delete"` | | +| USER_YAML.authz.roles[13].permissions[0].action.service | string | `"*"` | | +| USER_YAML.authz.roles[13].permissions[0].id | string | `"deleter"` | | +| USER_YAML.authz.roles[14].description | string | `""` | | +| USER_YAML.authz.roles[14].id | string | `"storage_writer"` | | +| USER_YAML.authz.roles[14].permissions[0].action.method | string | `"write-storage"` | | +| USER_YAML.authz.roles[14].permissions[0].action.service | string | `"*"` | | +| USER_YAML.authz.roles[14].permissions[0].id | string | `"storage_writer"` | | +| USER_YAML.authz.roles[15].description | string | `""` | | +| USER_YAML.authz.roles[15].id | string | `"storage_reader"` | | +| USER_YAML.authz.roles[15].permissions[0].action.method | string | `"read-storage"` | | +| USER_YAML.authz.roles[15].permissions[0].action.service | string | `"*"` | | +| USER_YAML.authz.roles[15].permissions[0].id | string | `"storage_reader"` | | +| USER_YAML.authz.roles[16].description | string | `"sheepdog admin role for program project crud"` | | +| USER_YAML.authz.roles[16].id | string | `"sheepdog_admin"` | | +| USER_YAML.authz.roles[16].permissions[0].action.method | string | `"*"` | | +| USER_YAML.authz.roles[16].permissions[0].action.service | string | `"sheepdog"` | | +| USER_YAML.authz.roles[16].permissions[0].id | string | `"sheepdog_admin_action"` | | +| USER_YAML.authz.roles[17].description | string | `"full access to indexd API"` | | +| USER_YAML.authz.roles[17].id | string | `"indexd_admin"` | | +| USER_YAML.authz.roles[17].permissions[0].action.method | string | `"*"` | | +| USER_YAML.authz.roles[17].permissions[0].action.service | string | `"indexd"` | | +| USER_YAML.authz.roles[17].permissions[0].id | string | `"indexd_admin"` | | +| USER_YAML.authz.roles[18].description | string | `""` | | +| USER_YAML.authz.roles[18].id | string | `"indexd_record_creator"` | | +| USER_YAML.authz.roles[18].permissions[0].action.method | string | `"create"` | | +| USER_YAML.authz.roles[18].permissions[0].action.service | string | `"indexd"` | | +| USER_YAML.authz.roles[18].permissions[0].id | string | `"indexd_record_creator"` | | +| USER_YAML.authz.roles[19].description | string | `""` | | +| USER_YAML.authz.roles[19].id | string | `"indexd_record_reader"` | | +| USER_YAML.authz.roles[19].permissions[0].action.method | string | `"read"` | | +| USER_YAML.authz.roles[19].permissions[0].action.service | string | `"indexd"` | | +| USER_YAML.authz.roles[19].permissions[0].id | string | `"indexd_record_reader"` | | +| USER_YAML.authz.roles[1].id | string | `"workspace_user"` | | +| USER_YAML.authz.roles[1].permissions[0].action.method | string | `"access"` | | +| USER_YAML.authz.roles[1].permissions[0].action.service | string | `"jupyterhub"` | | +| USER_YAML.authz.roles[1].permissions[0].id | string | `"workspace_access"` | | +| USER_YAML.authz.roles[20].description | string | `""` | | +| USER_YAML.authz.roles[20].id | string | `"indexd_record_updater"` | | +| USER_YAML.authz.roles[20].permissions[0].action.method | string | `"update"` | | +| USER_YAML.authz.roles[20].permissions[0].action.service | string | `"indexd"` | | +| USER_YAML.authz.roles[20].permissions[0].id | string | `"indexd_record_updater"` | | +| USER_YAML.authz.roles[21].description | string | `""` | | +| USER_YAML.authz.roles[21].id | string | `"indexd_delete_record"` | | +| USER_YAML.authz.roles[21].permissions[0].action.method | string | `"delete"` | | +| USER_YAML.authz.roles[21].permissions[0].action.service | string | `"indexd"` | | +| USER_YAML.authz.roles[21].permissions[0].id | string | `"indexd_delete_record"` | | +| USER_YAML.authz.roles[22].description | string | `""` | | +| USER_YAML.authz.roles[22].id | string | `"indexd_storage_reader"` | | +| USER_YAML.authz.roles[22].permissions[0].action.method | string | `"read-storage"` | | +| USER_YAML.authz.roles[22].permissions[0].action.service | string | `"indexd"` | | +| USER_YAML.authz.roles[22].permissions[0].id | string | `"indexd_storage_reader"` | | +| USER_YAML.authz.roles[23].description | string | `""` | | +| USER_YAML.authz.roles[23].id | string | `"indexd_storage_writer"` | | +| USER_YAML.authz.roles[23].permissions[0].action.method | string | `"write-storage"` | | +| USER_YAML.authz.roles[23].permissions[0].action.service | string | `"indexd"` | | +| USER_YAML.authz.roles[23].permissions[0].id | string | `"indexd_storage_writer"` | | +| USER_YAML.authz.roles[24].description | string | `""` | | +| USER_YAML.authz.roles[24].id | string | `"arborist_creator"` | | +| USER_YAML.authz.roles[24].permissions[0].action.method | string | `"create"` | | +| USER_YAML.authz.roles[24].permissions[0].action.service | string | `"arborist"` | | +| USER_YAML.authz.roles[24].permissions[0].id | string | `"arborist_creator"` | | +| USER_YAML.authz.roles[25].description | string | `""` | | +| USER_YAML.authz.roles[25].id | string | `"arborist_reader"` | | +| USER_YAML.authz.roles[25].permissions[0].action.method | string | `"read"` | | +| USER_YAML.authz.roles[25].permissions[0].action.service | string | `"arborist"` | | +| USER_YAML.authz.roles[25].permissions[0].id | string | `"arborist_reader"` | | +| USER_YAML.authz.roles[26].description | string | `""` | | +| USER_YAML.authz.roles[26].id | string | `"arborist_updater"` | | +| USER_YAML.authz.roles[26].permissions[0].action.method | string | `"update"` | | +| USER_YAML.authz.roles[26].permissions[0].action.service | string | `"arborist"` | | +| USER_YAML.authz.roles[26].permissions[0].id | string | `"arborist_updater"` | | +| USER_YAML.authz.roles[27].description | string | `""` | | +| USER_YAML.authz.roles[27].id | string | `"arborist_deleter"` | | +| USER_YAML.authz.roles[27].permissions[0].action.method | string | `"delete"` | | +| USER_YAML.authz.roles[27].permissions[0].action.service | string | `"arborist"` | | +| USER_YAML.authz.roles[27].permissions[0].id | string | `"arborist_deleter"` | | +| USER_YAML.authz.roles[28].id | string | `"requestor_admin"` | | +| USER_YAML.authz.roles[28].permissions[0].action.method | string | `"*"` | | +| USER_YAML.authz.roles[28].permissions[0].action.service | string | `"requestor"` | | +| USER_YAML.authz.roles[28].permissions[0].id | string | `"requestor_admin_action"` | | +| USER_YAML.authz.roles[29].id | string | `"requestor_reader"` | | +| USER_YAML.authz.roles[29].permissions[0].action.method | string | `"read"` | | +| USER_YAML.authz.roles[29].permissions[0].action.service | string | `"requestor"` | | +| USER_YAML.authz.roles[29].permissions[0].id | string | `"requestor_reader_action"` | | +| USER_YAML.authz.roles[2].id | string | `"dashboard_user"` | | +| USER_YAML.authz.roles[2].permissions[0].action.method | string | `"access"` | | +| USER_YAML.authz.roles[2].permissions[0].action.service | string | `"dashboard"` | | +| USER_YAML.authz.roles[2].permissions[0].id | string | `"dashboard_access"` | | +| USER_YAML.authz.roles[30].id | string | `"requestor_creator"` | | +| USER_YAML.authz.roles[30].permissions[0].action.method | string | `"create"` | | +| USER_YAML.authz.roles[30].permissions[0].action.service | string | `"requestor"` | | +| USER_YAML.authz.roles[30].permissions[0].id | string | `"requestor_creator_action"` | | +| USER_YAML.authz.roles[31].id | string | `"requestor_updater"` | | +| USER_YAML.authz.roles[31].permissions[0].action.method | string | `"update"` | | +| USER_YAML.authz.roles[31].permissions[0].action.service | string | `"requestor"` | | +| USER_YAML.authz.roles[31].permissions[0].id | string | `"requestor_updater_action"` | | +| USER_YAML.authz.roles[32].id | string | `"requestor_deleter"` | | +| USER_YAML.authz.roles[32].permissions[0].action.method | string | `"delete"` | | +| USER_YAML.authz.roles[32].permissions[0].action.service | string | `"requestor"` | | +| USER_YAML.authz.roles[32].permissions[0].id | string | `"requestor_deleter_action"` | | +| USER_YAML.authz.roles[33].id | string | `"argo_user"` | | +| USER_YAML.authz.roles[33].permissions[0].action.method | string | `"access"` | | +| USER_YAML.authz.roles[33].permissions[0].action.service | string | `"argo"` | | +| USER_YAML.authz.roles[33].permissions[0].id | string | `"argo_access"` | | +| USER_YAML.authz.roles[3].id | string | `"mds_user"` | | +| USER_YAML.authz.roles[3].permissions[0].action.method | string | `"access"` | | +| USER_YAML.authz.roles[3].permissions[0].action.service | string | `"mds_gateway"` | | +| USER_YAML.authz.roles[3].permissions[0].id | string | `"mds_access"` | | +| USER_YAML.authz.roles[4].id | string | `"prometheus_user"` | | +| USER_YAML.authz.roles[4].permissions[0].action.method | string | `"access"` | | +| USER_YAML.authz.roles[4].permissions[0].action.service | string | `"prometheus"` | | +| USER_YAML.authz.roles[4].permissions[0].id | string | `"prometheus_access"` | | +| USER_YAML.authz.roles[5].id | string | `"ttyadmin_user"` | | +| USER_YAML.authz.roles[5].permissions[0].action.method | string | `"access"` | | +| USER_YAML.authz.roles[5].permissions[0].action.service | string | `"ttyadmin"` | | +| USER_YAML.authz.roles[5].permissions[0].id | string | `"ttyadmin_access"` | | +| USER_YAML.authz.roles[6].id | string | `"sower_user"` | | +| USER_YAML.authz.roles[6].permissions[0].action.method | string | `"access"` | | +| USER_YAML.authz.roles[6].permissions[0].action.service | string | `"job"` | | +| USER_YAML.authz.roles[6].permissions[0].id | string | `"sower_access"` | | +| USER_YAML.authz.roles[7].id | string | `"mariner_admin"` | | +| USER_YAML.authz.roles[7].permissions[0].action.method | string | `"access"` | | +| USER_YAML.authz.roles[7].permissions[0].action.service | string | `"mariner"` | | +| USER_YAML.authz.roles[7].permissions[0].id | string | `"mariner_access"` | | +| USER_YAML.authz.roles[8].id | string | `"audit_reader"` | | +| USER_YAML.authz.roles[8].permissions[0].action.method | string | `"read"` | | +| USER_YAML.authz.roles[8].permissions[0].action.service | string | `"audit"` | | +| USER_YAML.authz.roles[8].permissions[0].id | string | `"audit_reader_action"` | | +| USER_YAML.authz.roles[9].description | string | `""` | | +| USER_YAML.authz.roles[9].id | string | `"admin"` | | +| USER_YAML.authz.roles[9].permissions[0].action.method | string | `"*"` | | +| USER_YAML.authz.roles[9].permissions[0].action.service | string | `"*"` | | +| USER_YAML.authz.roles[9].permissions[0].id | string | `"admin"` | | +| USER_YAML.authz.user_project_to_resource.DEV | string | `"/programs/DEV"` | | +| USER_YAML.authz.user_project_to_resource.QA | string | `"/programs/QA"` | | +| USER_YAML.authz.user_project_to_resource.jenkins | string | `"/programs/jnkns/projects/jenkins"` | | +| USER_YAML.authz.user_project_to_resource.jenkins2 | string | `"/programs/jnkns/projects/jenkins2"` | | +| USER_YAML.authz.user_project_to_resource.jnkns | string | `"/programs/jnkns"` | | +| USER_YAML.authz.user_project_to_resource.test | string | `"/programs/QA/projects/test"` | | +| USER_YAML.clients.basic-test-abc-client.policies[0] | string | `"abc-admin"` | | +| USER_YAML.clients.basic-test-client.policies[0] | string | `"abc-admin"` | | +| USER_YAML.clients.basic-test-client.policies[1] | string | `"gen3-admin"` | | +| USER_YAML.clients.wts.policies[0] | string | `"all_programs_reader"` | | +| USER_YAML.clients.wts.policies[1] | string | `"workspace"` | | +| USER_YAML.cloud_providers | object | `{}` | | +| USER_YAML.groups | object | `{}` | | +| USER_YAML.users."qureshi@uchicago.edu".admin | bool | `true` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[0] | string | `"data_upload"` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[10] | string | `"programs.jnkns-admin"` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[11] | string | `"indexd_admin"` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[12] | string | `"ttyadmin"` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[1] | string | `"workspace"` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[2] | string | `"dashboard"` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[3] | string | `"mds_admin"` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[4] | string | `"prometheus"` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[5] | string | `"sower"` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[6] | string | `"services.sheepdog-admin"` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[7] | string | `"programs.QA-admin"` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[8] | string | `"programs.test-admin"` | | +| USER_YAML.users."qureshi@uchicago.edu".policies[9] | string | `"programs.DEV-admin"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[0].auth_id | string | `"QA"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[0].privilege[0] | string | `"create"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[0].privilege[1] | string | `"read"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[0].privilege[2] | string | `"update"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[0].privilege[3] | string | `"delete"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[0].privilege[4] | string | `"upload"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[0].privilege[5] | string | `"read-storage"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[1].auth_id | string | `"test"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[1].privilege[0] | string | `"create"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[1].privilege[1] | string | `"read"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[1].privilege[2] | string | `"update"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[1].privilege[3] | string | `"delete"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[1].privilege[4] | string | `"upload"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[1].privilege[5] | string | `"read-storage"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[2].auth_id | string | `"DEV"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[2].privilege[0] | string | `"create"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[2].privilege[1] | string | `"read"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[2].privilege[2] | string | `"update"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[2].privilege[3] | string | `"delete"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[2].privilege[4] | string | `"upload"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[2].privilege[5] | string | `"read-storage"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[3].auth_id | string | `"jenkins"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[3].privilege[0] | string | `"create"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[3].privilege[1] | string | `"read"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[3].privilege[2] | string | `"update"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[3].privilege[3] | string | `"delete"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[3].privilege[4] | string | `"upload"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[3].privilege[5] | string | `"read-storage"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[4].auth_id | string | `"jenkins2"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[4].privilege[0] | string | `"create"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[4].privilege[1] | string | `"read"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[4].privilege[2] | string | `"update"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[4].privilege[3] | string | `"delete"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[4].privilege[4] | string | `"upload"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[4].privilege[5] | string | `"read-storage"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[5].auth_id | string | `"jnkns"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[5].privilege[0] | string | `"create"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[5].privilege[1] | string | `"read"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[5].privilege[2] | string | `"update"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[5].privilege[3] | string | `"delete"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[5].privilege[4] | string | `"upload"` | | +| USER_YAML.users."qureshi@uchicago.edu".projects[5].privilege[5] | string | `"read-storage"` | | +| USER_YAML_CRON.LOCATION."github.com" | string | `nil` | | +| USER_YAML_CRON.LOCATION.S3 | string | `nil` | | +| USER_YAML_CRON.LOCATION.TYPE | string | `nil` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key | string | `"app"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator | string | `"In"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0] | string | `"fence"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey | string | `"kubernetes.io/hostname"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight | int | `100` | | +| autoscaling.enabled | string | `"enabled"` | | +| autoscaling.maxReplicas | int | `4` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| env[0].name | string | `"DD_ENABLED"` | | +| env[0].valueFrom.configMapKeyRef.key | string | `"dd_enabled"` | | +| env[0].valueFrom.configMapKeyRef.name | string | `"manifest-global"` | | +| env[0].valueFrom.configMapKeyRef.optional | bool | `true` | | +| env[10].name | string | `"PYTHONPATH"` | | +| env[10].value | string | `"/var/www/fence"` | | +| env[11].name | string | `"GEN3_DEBUG"` | | +| env[11].value | string | `"False"` | | +| env[12].name | string | `"FENCE_PUBLIC_CONFIG"` | | +| env[12].valueFrom.configMapKeyRef.key | string | `"fence-config-public.yaml"` | | +| env[12].valueFrom.configMapKeyRef.name | string | `"manifest-fence"` | | +| env[12].valueFrom.configMapKeyRef.optional | bool | `true` | | +| env[13].name | string | `"PGHOST"` | | +| env[13].valueFrom.secretKeyRef.key | string | `"host"` | | +| env[13].valueFrom.secretKeyRef.name | string | `"fence-dbcreds"` | | +| env[13].valueFrom.secretKeyRef.optional | bool | `false` | | +| env[14].name | string | `"PGUSER"` | | +| env[14].valueFrom.secretKeyRef.key | string | `"username"` | | +| env[14].valueFrom.secretKeyRef.name | string | `"fence-dbcreds"` | | +| env[14].valueFrom.secretKeyRef.optional | bool | `false` | | +| env[15].name | string | `"PGPASSWORD"` | | +| env[15].valueFrom.secretKeyRef.key | string | `"password"` | | +| env[15].valueFrom.secretKeyRef.name | string | `"fence-dbcreds"` | | +| env[15].valueFrom.secretKeyRef.optional | bool | `false` | | +| env[16].name | string | `"PGDB"` | | +| env[16].valueFrom.secretKeyRef.key | string | `"database"` | | +| env[16].valueFrom.secretKeyRef.name | string | `"fence-dbcreds"` | | +| env[16].valueFrom.secretKeyRef.optional | bool | `false` | | +| env[17].name | string | `"DB"` | | +| env[17].value | string | `"postgresql://$(PGUSER):$(PGPASSWORD)@$(PGHOST):5432/$(PGDB)"` | | +| env[1].name | string | `"DD_ENV"` | | +| env[1].valueFrom.fieldRef.fieldPath | string | `"metadata.labels['tags.datadoghq.com/env']"` | | +| env[2].name | string | `"DD_SERVICE"` | | +| env[2].valueFrom.fieldRef.fieldPath | string | `"metadata.labels['tags.datadoghq.com/service']"` | | +| env[3].name | string | `"DD_VERSION"` | | +| env[3].valueFrom.fieldRef.fieldPath | string | `"metadata.labels['tags.datadoghq.com/version']"` | | +| env[4].name | string | `"DD_LOGS_INJECTION"` | | +| env[4].value | string | `"true"` | | +| env[5].name | string | `"DD_PROFILING_ENABLED"` | | +| env[5].value | string | `"true"` | | +| env[6].name | string | `"DD_TRACE_SAMPLE_RATE"` | | +| env[6].value | string | `"1"` | | +| env[7].name | string | `"GEN3_UWSGI_TIMEOUT"` | | +| env[7].valueFrom.configMapKeyRef.key | string | `"uwsgi-timeout"` | | +| env[7].valueFrom.configMapKeyRef.name | string | `"manifest-global"` | | +| env[7].valueFrom.configMapKeyRef.optional | bool | `true` | | +| env[8].name | string | `"DD_AGENT_HOST"` | | +| env[8].valueFrom.fieldRef.fieldPath | string | `"status.hostIP"` | | +| env[9].name | string | `"AWS_STS_REGIONAL_ENDPOINTS"` | | +| env[9].value | string | `"regional"` | | +| fullnameOverride | string | `""` | | +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/cdis/fence"` | | +| image.tag | string | `"master"` | | +| imagePullSecrets | list | `[]` | | +| initEnv[0].name | string | `"PGHOST"` | | +| initEnv[0].valueFrom.secretKeyRef.key | string | `"host"` | | +| initEnv[0].valueFrom.secretKeyRef.name | string | `"fence-dbcreds"` | | +| initEnv[0].valueFrom.secretKeyRef.optional | bool | `false` | | +| initEnv[1].name | string | `"PGUSER"` | | +| initEnv[1].valueFrom.secretKeyRef.key | string | `"username"` | | +| initEnv[1].valueFrom.secretKeyRef.name | string | `"fence-dbcreds"` | | +| initEnv[1].valueFrom.secretKeyRef.optional | bool | `false` | | +| initEnv[2].name | string | `"PGPASSWORD"` | | +| initEnv[2].valueFrom.secretKeyRef.key | string | `"password"` | | +| initEnv[2].valueFrom.secretKeyRef.name | string | `"fence-dbcreds"` | | +| initEnv[2].valueFrom.secretKeyRef.optional | bool | `false` | | +| initEnv[3].name | string | `"PGDB"` | | +| initEnv[3].valueFrom.secretKeyRef.key | string | `"database"` | | +| initEnv[3].valueFrom.secretKeyRef.name | string | `"fence-dbcreds"` | | +| initEnv[3].valueFrom.secretKeyRef.optional | bool | `false` | | +| initEnv[4].name | string | `"DB"` | | +| initEnv[4].value | string | `"postgresql://$(PGUSER):$(PGPASSWORD)@$(PGHOST):5432/$(PGDB)"` | | +| initEnv[5].name | string | `"PYTHONPATH"` | | +| initEnv[5].value | string | `"/var/www/fence"` | | +| initEnv[6].name | string | `"FENCE_PUBLIC_CONFIG"` | | +| initEnv[6].valueFrom.configMapKeyRef.key | string | `"fence-config-public.yaml"` | | +| initEnv[6].valueFrom.configMapKeyRef.name | string | `"manifest-fence"` | | +| initEnv[6].valueFrom.configMapKeyRef.optional | bool | `true` | | +| initVolumeMounts[0].mountPath | string | `"/var/www/fence/fence-config.yaml"` | | +| initVolumeMounts[0].name | string | `"config-volume"` | | +| initVolumeMounts[0].readOnly | bool | `true` | | +| initVolumeMounts[0].subPath | string | `"fence-config.yaml"` | | +| initVolumeMounts[1].mountPath | string | `"/var/www/fence/yaml_merge.py"` | | +| initVolumeMounts[1].name | string | `"yaml-merge"` | | +| initVolumeMounts[1].readOnly | bool | `true` | | +| initVolumeMounts[1].subPath | string | `"yaml_merge.py"` | | +| initVolumeMounts[2].mountPath | string | `"/var/www/fence/fence_google_app_creds_secret.json"` | | +| initVolumeMounts[2].name | string | `"fence-google-app-creds-secret-volume"` | | +| initVolumeMounts[2].readOnly | bool | `true` | | +| initVolumeMounts[2].subPath | string | `"fence_google_app_creds_secret.json"` | | +| initVolumeMounts[3].mountPath | string | `"/var/www/fence/fence_google_storage_creds_secret.json"` | | +| initVolumeMounts[3].name | string | `"fence-google-storage-creds-secret-volume"` | | +| initVolumeMounts[3].readOnly | bool | `true` | | +| initVolumeMounts[3].subPath | string | `"fence_google_storage_creds_secret.json"` | | +| labels."tags.datadoghq.com/env" | string | `"anvilstaging"` | | +| labels."tags.datadoghq.com/service" | string | `"fence"` | | +| labels."tags.datadoghq.com/version" | float | `2021.12` | | +| labels.app | string | `"fence"` | | +| labels.authprovider | string | `"yes"` | | +| labels.netnolimit | string | `"yes"` | | +| labels.public | string | `"yes"` | | +| labels.release | string | `"production"` | | +| labels.userhelper | string | `"yes"` | | +| logo | string | `nil` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | | +| podSecurityContext.fsGroup | int | `101` | | +| postgres.database | string | `"fence"` | | +| postgres.db_create | string | `nil` | | +| postgres.host | string | `nil` | | +| postgres.password | string | `nil` | | +| postgres.port | string | `"5432"` | | +| postgres.username | string | `"fence"` | | +| privacy_policy | string | `nil` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | float | `1` | | +| resources.limits.memory | string | `"2400Mi"` | | +| resources.requests.cpu | string | `"100m"` | | +| resources.requests.memory | string | `"128Mi"` | | +| securityContext | object | `{}` | | +| selectorLabels.app | string | `"fence"` | | +| selectorLabels.release | string | `"production"` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations."eks.amazonaws.com/role-arn" | string | `""` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `"fence-sa"` | | +| tolerations | list | `[]` | | +| volumeMounts[0].mountPath | string | `"/var/www/fence/local_settings.py"` | | +| volumeMounts[0].name | string | `"old-config-volume"` | | +| volumeMounts[0].readOnly | bool | `true` | | +| volumeMounts[0].subPath | string | `"local_settings.py"` | | +| volumeMounts[10].mountPath | string | `"/fence/keys/key/jwt_private_key.pem"` | | +| volumeMounts[10].name | string | `"fence-jwt-keys"` | | +| volumeMounts[10].readOnly | bool | `true` | | +| volumeMounts[10].subPath | string | `"jwt_private_key.pem"` | | +| volumeMounts[1].mountPath | string | `"/var/www/fence/fence_credentials.json"` | | +| volumeMounts[1].name | string | `"json-secret-volume"` | | +| volumeMounts[1].readOnly | bool | `true` | | +| volumeMounts[1].subPath | string | `"fence_credentials.json"` | | +| volumeMounts[2].mountPath | string | `"/var/www/fence/creds.json"` | | +| volumeMounts[2].name | string | `"creds-volume"` | | +| volumeMounts[2].readOnly | bool | `true` | | +| volumeMounts[2].subPath | string | `"creds.json"` | | +| volumeMounts[3].mountPath | string | `"/var/www/fence/config_helper.py"` | | +| volumeMounts[3].name | string | `"config-helper"` | | +| volumeMounts[3].readOnly | bool | `true` | | +| volumeMounts[3].subPath | string | `"config_helper.py"` | | +| volumeMounts[4].mountPath | string | `"/fence/fence/static/img/logo.svg"` | | +| volumeMounts[4].name | string | `"logo-volume"` | | +| volumeMounts[4].readOnly | bool | `true` | | +| volumeMounts[4].subPath | string | `"logo.svg"` | | +| volumeMounts[5].mountPath | string | `"/fence/fence/static/privacy_policy.md"` | | +| volumeMounts[5].name | string | `"privacy-policy"` | | +| volumeMounts[5].readOnly | bool | `true` | | +| volumeMounts[5].subPath | string | `"privacy_policy.md"` | | +| volumeMounts[6].mountPath | string | `"/var/www/fence/fence-config.yaml"` | | +| volumeMounts[6].name | string | `"config-volume"` | | +| volumeMounts[6].readOnly | bool | `true` | | +| volumeMounts[6].subPath | string | `"fence-config.yaml"` | | +| volumeMounts[7].mountPath | string | `"/var/www/fence/yaml_merge.py"` | | +| volumeMounts[7].name | string | `"yaml-merge"` | | +| volumeMounts[7].readOnly | bool | `true` | | +| volumeMounts[7].subPath | string | `"yaml_merge.py"` | | +| volumeMounts[8].mountPath | string | `"/var/www/fence/fence_google_app_creds_secret.json"` | | +| volumeMounts[8].name | string | `"fence-google-app-creds-secret-volume"` | | +| volumeMounts[8].readOnly | bool | `true` | | +| volumeMounts[8].subPath | string | `"fence_google_app_creds_secret.json"` | | +| volumeMounts[9].mountPath | string | `"/var/www/fence/fence_google_storage_creds_secret.json"` | | +| volumeMounts[9].name | string | `"fence-google-storage-creds-secret-volume"` | | +| volumeMounts[9].readOnly | bool | `true` | | +| volumeMounts[9].subPath | string | `"fence_google_storage_creds_secret.json"` | | +| volumes[0].name | string | `"old-config-volume"` | | +| volumes[0].secret.secretName | string | `"fence-secret"` | | +| volumes[10].configMap.name | string | `"fence-yaml-merge"` | | +| volumes[10].configMap.optional | bool | `true` | | +| volumes[10].name | string | `"yaml-merge"` | | +| volumes[1].name | string | `"json-secret-volume"` | | +| volumes[1].secret.optional | bool | `true` | | +| volumes[1].secret.secretName | string | `"fence-json-secret"` | | +| volumes[2].name | string | `"creds-volume"` | | +| volumes[2].secret.secretName | string | `"fence-creds"` | | +| volumes[3].configMap.name | string | `"config-helper"` | | +| volumes[3].configMap.optional | bool | `true` | | +| volumes[3].name | string | `"config-helper"` | | +| volumes[4].configMap.name | string | `"logo-config"` | | +| volumes[4].name | string | `"logo-volume"` | | +| volumes[5].name | string | `"config-volume"` | | +| volumes[5].secret.secretName | string | `"fence-config"` | | +| volumes[6].name | string | `"fence-google-app-creds-secret-volume"` | | +| volumes[6].secret.secretName | string | `"fence-google-app-creds-secret"` | | +| volumes[7].name | string | `"fence-google-storage-creds-secret-volume"` | | +| volumes[7].secret.secretName | string | `"fence-google-storage-creds-secret"` | | +| volumes[8].name | string | `"fence-jwt-keys"` | | +| volumes[8].secret.secretName | string | `"fence-jwt-keys"` | | +| volumes[9].configMap.name | string | `"privacy-policy"` | | +| volumes[9].name | string | `"privacy-policy"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/fence/templates/db-init.yaml b/helm/fence/templates/db-init.yaml index e53cb144..a197f530 100644 --- a/helm/fence/templates/db-init.yaml +++ b/helm/fence/templates/db-init.yaml @@ -1,3 +1,3 @@ -{{- include "common.db-setup-job" . }} +{{ include "common.db-setup-job" . }} --- -{{- include "common.db-secret" . }} +{{ include "common.db-secret" . }} diff --git a/helm/fence/templates/fence-config.yaml b/helm/fence/templates/fence-config.yaml index 291a3802..2ff0eadc 100644 --- a/helm/fence/templates/fence-config.yaml +++ b/helm/fence/templates/fence-config.yaml @@ -4,13 +4,7 @@ metadata: name: fence-config stringData: fence-config.yaml: | - {{- $username := include "gen3.service-postgres" (dict "key" "username" "service" $.Chart.Name "context" $) }} - {{- $password := include "gen3.service-postgres" (dict "key" "password" "service" $.Chart.Name "context" $) }} - {{- $host := include "gen3.service-postgres" (dict "key" "host" "service" $.Chart.Name "context" $) }} - {{- $port := include "gen3.service-postgres" (dict "key" "port" "service" $.Chart.Name "context" $) }} - {{- $database := include "gen3.service-postgres" (dict "key" "database" "service" $.Chart.Name "context" $) }} - BASE_URL: '{{ .Values.FENCE_CONFIG.BASE_URL }}' - DB: 'postgresql://{{ $username }}:{{ $password }}@{{ $host }}:{{ $port }}/{{ $database }}' + BASE_URL: https://{{ .Values.global.hostname }}/user {{- with .Values.FENCE_CONFIG }} {{- toYaml . | nindent 4 }} {{ end }} diff --git a/helm/fence/templates/fence-creds.yaml b/helm/fence/templates/fence-creds.yaml index 75687b92..24cfb7ad 100644 --- a/helm/fence/templates/fence-creds.yaml +++ b/helm/fence/templates/fence-creds.yaml @@ -10,7 +10,7 @@ stringData: "db_username": "{{include "gen3.service-postgres" (dict "key" "username" "service" $.Chart.Name "context" $) }}", "db_password": "{{include "gen3.service-postgres" (dict "key" "password" "service" $.Chart.Name "context" $) }}", "db_database": "{{ include "gen3.service-postgres" (dict "key" "database" "service" $.Chart.Name "context" $)}}", - "hostname": "{{ .Values.hostname }}", + "hostname": "{{ .Values.global.hostname }}", "indexd_password": "", "google_client_secret": "YOUR.GOOGLE.SECRET", "google_client_id": "YOUR.GOOGLE.CLIENT", diff --git a/helm/fence/templates/usersync-cron.yaml b/helm/fence/templates/usersync-cron.yaml new file mode 100644 index 00000000..e69de29b diff --git a/helm/fence/templates/useryaml-job.yaml b/helm/fence/templates/useryaml-job.yaml new file mode 100644 index 00000000..3ae257eb --- /dev/null +++ b/helm/fence/templates/useryaml-job.yaml @@ -0,0 +1,49 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: useryaml +data: + useryaml: | {{ .Values.USER_YAML | toYaml | nindent 4}} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: useryaml +spec: + backoffLimit: 10 + template: + metadata: + labels: + app: gen3job + spec: + automountServiceAccountToken: false + volumes: + - name: fence-config + secret: + secretName: "fence-config" + - name: useryaml + configMap: + name: useryaml + containers: + - name: fence + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: Always + env: + {{- toYaml .Values.env | nindent 10 }} + - name: PYTHONPATH + value: /var/www/fence + volumeMounts: + - name: "fence-config" + readOnly: true + mountPath: "/var/www/fence/fence-config.yaml" + subPath: fence-config.yaml + - name: "useryaml" + mountPath: "/var/www/fence/user.yaml" + subPath: useryaml + command: ["/bin/bash" ] + args: + - "-c" + # Script always succeeds if it runs (echo exits with 0) + - | + fence-create sync --arborist http://arborist-service --yaml /var/www/fence/user.yaml + restartPolicy: OnFailure \ No newline at end of file diff --git a/helm/fence/values.yaml b/helm/fence/values.yaml index 11a0865f..e4c4185d 100644 --- a/helm/fence/values.yaml +++ b/helm/fence/values.yaml @@ -2,22 +2,38 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. global: - # Default values are for postgres deployed as a helm chart + dev: true postgres: - host: postgres-postgresql.postgres.svc.cluster.local + db_create: true master: + host: username: postgres - password: - port: 5432 + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false -db_create: true postgres: - # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you + db_create: + # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you database: fence username: fence - port: 5432 + host: + port: "5432" # If left empty password will be auto-generated - password: + password: replicaCount: 1 @@ -25,21 +41,18 @@ image: repository: quay.io/cdis/fence pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. - tag: "" + tag: "master" imagePullSecrets: [] nameOverride: "" fullnameOverride: "" -hostname: localhost - - serviceAccount: # Specifies whether a service account should be created create: true # Annotations to add to the service account - annotations: + annotations: # TODO: Make this dynamic eks.amazonaws.com/role-arn: "" # The name of the service account to use. @@ -48,7 +61,7 @@ serviceAccount: podAnnotations: {} -podSecurityContext: +podSecurityContext: fsGroup: 101 securityContext: {} @@ -64,26 +77,9 @@ service: type: ClusterIP port: 80 -# ingress: -# enabled: true -# annotations: { -# nginx.ingress.kubernetes.io/rewrite-target: /$2, -# kubernetes.io/ingress.class: "nginx" -# } -# # kubernetes.io/ingress.class: nginx -# # kubernetes.io/tls-acme: "true" -# hosts: -# - host: ingress.local -# paths: -# - path: "/user(/|$)(.*)" -# pathType: Prefix -# tls: [] -# # - secretName: chart-example-tls -# # hosts: -# # - chart-example.local - -resources: - requests: + +resources: + requests: cpu: 100m memory: 128Mi limits: @@ -112,7 +108,7 @@ nodeSelector: {} tolerations: [] -labels: +labels: app: fence release: production # for network policy selectors @@ -124,7 +120,8 @@ labels: tags.datadoghq.com/service: "fence" tags.datadoghq.com/env: anvilstaging tags.datadoghq.com/version: 2021.12 -affinity: + +affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 @@ -137,7 +134,7 @@ affinity: - fence topologyKey: "kubernetes.io/hostname" -env: +env: - name: DD_ENABLED valueFrom: configMapKeyRef: @@ -184,9 +181,34 @@ env: name: manifest-fence key: fence-config-public.yaml optional: true - - -volumes: + - name: PGHOST + valueFrom: + secretKeyRef: + name: fence-dbcreds + key: host + optional: false + - name: PGUSER + valueFrom: + secretKeyRef: + name: fence-dbcreds + key: username + optional: false + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: fence-dbcreds + key: password + optional: false + - name: PGDB + valueFrom: + secretKeyRef: + name: fence-dbcreds + key: database + optional: false + - name: DB + value: postgresql://$(PGUSER):$(PGPASSWORD)@$(PGHOST):5432/$(PGDB) + +volumes: - name: old-config-volume secret: secretName: "fence-secret" @@ -224,7 +246,7 @@ volumes: name: "fence-yaml-merge" optional: true -volumeMounts: +volumeMounts: - name: "old-config-volume" readOnly: true mountPath: "/var/www/fence/local_settings.py" @@ -268,9 +290,9 @@ volumeMounts: - name: "fence-jwt-keys" readOnly: true mountPath: "/fence/keys/key/jwt_private_key.pem" - subPath: "jwt_private_key.pem" + subPath: "jwt_private_key.pem" -initVolumeMounts: +initVolumeMounts: - name: "config-volume" readOnly: true mountPath: "/var/www/fence/fence-config.yaml" @@ -288,7 +310,33 @@ initVolumeMounts: mountPath: "/var/www/fence/fence_google_storage_creds_secret.json" subPath: fence_google_storage_creds_secret.json -initEnv: +initEnv: + - name: PGHOST + valueFrom: + secretKeyRef: + name: fence-dbcreds + key: host + optional: false + - name: PGUSER + valueFrom: + secretKeyRef: + name: fence-dbcreds + key: username + optional: false + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: fence-dbcreds + key: password + optional: false + - name: PGDB + valueFrom: + secretKeyRef: + name: fence-dbcreds + key: database + optional: false + - name: DB + value: postgresql://$(PGUSER):$(PGPASSWORD)@$(PGHOST):5432/$(PGDB) - name: PYTHONPATH value: /var/www/fence - name: FENCE_PUBLIC_CONFIG @@ -298,20 +346,898 @@ initEnv: key: fence-config-public.yaml optional: true -selectorLabels: +selectorLabels: app: fence release: production -logo: -privacy_policy: +logo: +privacy_policy: + + +USER_YAML_CRON: + LOCATION: + TYPE: + S3: + github.com: + +### USER YAML +USER_YAML: + cloud_providers: {} + groups: {} + authz: + # policies automatically given to anyone, even if they haven't authenticated + anonymous_policies: ['open_data_reader', 'full_open_access'] + + # policies automatically given to authenticated users (in addition to their other + # policies) + all_users_policies: ['open_data_reader', 'authn_open_access'] + + user_project_to_resource: + QA: /programs/QA + DEV: /programs/DEV + test: /programs/QA/projects/test + jenkins: /programs/jnkns/projects/jenkins + jenkins2: /programs/jnkns/projects/jenkins2 + jnkns: /programs/jnkns + + policies: + # General Access + - id: 'workspace' + description: 'be able to use workspace' + resource_paths: ['/workspace'] + role_ids: ['workspace_user'] + - id: 'dashboard' + description: 'be able to use the commons dashboard' + resource_paths: ['/dashboard'] + role_ids: ['dashboard_user'] + - id: 'prometheus' + description: 'be able to use prometheus' + resource_paths: ['/prometheus'] + role_ids: ['prometheus_user'] + - id: 'ttyadmin' + description: 'be able to use the admin tty' + resource_paths: ['/ttyadmin'] + role_ids: ['ttyadmin_user'] + - id: 'mds_admin' + description: 'be able to use metadata service' + resource_paths: ['/mds_gateway'] + role_ids: ['mds_user'] + - id: 'data_upload' + description: 'upload raw data files to S3' + role_ids: ['file_uploader'] + resource_paths: ['/data_file'] + - description: be able to use sower job + id: sower + resource_paths: [/sower] + role_ids: [sower_user] + - id: 'mariner_admin' + description: 'full access to mariner API' + resource_paths: ['/mariner'] + role_ids: ['mariner_admin'] + - id: audit_reader + role_ids: + - audit_reader + resource_paths: + - /services/audit + - id: audit_login_reader + role_ids: + - audit_reader + resource_paths: + - /services/audit/login + - id: audit_presigned_url_reader + role_ids: + - audit_reader + resource_paths: + - /services/audit/presigned_url + - id: requestor_admin + role_ids: + - requestor_admin + resource_paths: + - /programs + - id: requestor_reader + role_ids: + - requestor_reader + resource_paths: + - /programs + - id: requestor_creator + role_ids: + - requestor_creator + resource_paths: + - /programs + - id: requestor_updater + role_ids: + - requestor_updater + resource_paths: + - /programs + - id: requestor_deleter + role_ids: + - requestor_deleter + resource_paths: + - /programs + # Data Access + + # All programs policy + - id: 'all_programs_reader' + description: '' + role_ids: + - 'reader' + - 'storage_reader' + resource_paths: ['/programs'] + + # # example if need access to write to storage + # - id: 'programs.jnkns-storage_writer' + # description: '' + # role_ids: + # - 'storage_writer' + # resource_paths: ['/programs/jnkns'] + + - id: 'programs.jnkns-admin' + description: '' + role_ids: + - 'creator' + - 'reader' + - 'updater' + - 'deleter' + - 'storage_reader' + resource_paths: + - '/programs/jnkns' + - '/gen3/programs/jnkns' + + - id: 'programs.jnkns-viewer' + description: '' + role_ids: + - 'reader' + - 'storage_reader' + resource_paths: + - '/programs/jnkns' + - '/gen3/programs/jnkns' + + + - id: 'programs.QA-admin' + description: '' + role_ids: + - 'creator' + - 'reader' + - 'updater' + - 'deleter' + - 'storage_reader' + resource_paths: + - '/programs/QA' + - '/gen3/programs/QA' + + - id: 'programs.QA-admin-no-storage' + description: '' + role_ids: + - 'creator' + - 'reader' + - 'updater' + - 'deleter' + resource_paths: + - '/programs/QA' + - '/gen3/programs/QA' + + - id: 'programs.QA-viewer' + description: '' + role_ids: + - 'reader' + - 'storage_reader' + resource_paths: + - '/programs/QA' + - '/gen3/programs/QA' + + - id: 'programs.DEV-admin' + description: '' + role_ids: + - 'creator' + - 'reader' + - 'updater' + - 'deleter' + - 'storage_reader' + - 'storage_writer' + resource_paths: + - '/programs/DEV' + - '/gen3/programs/DEV' + + - id: 'programs.DEV-storage_writer' + description: '' + role_ids: + - 'storage_writer' + resource_paths: ['/programs/DEV'] + + - id: 'programs.DEV-viewer' + description: '' + role_ids: + - 'reader' + - 'storage_reader' + resource_paths: + - '/programs/DEV' + - '/gen3/programs/DEV' + + - id: 'programs.test-admin' + description: '' + role_ids: + - 'creator' + - 'reader' + - 'updater' + - 'deleter' + - 'storage_reader' + resource_paths: + - '/programs/test' + - '/gen3/programs/test' + + - id: 'programs.test-viewer' + description: '' + role_ids: + - 'reader' + - 'storage_reader' + resource_paths: + - '/programs/test' + - '/gen3/programs/test' + + - id: 'abc-admin' + description: '' + role_ids: + - 'creator' + - 'reader' + - 'updater' + - 'deleter' + - 'storage_reader' + resource_paths: + - '/abc' + + - id: 'gen3-admin' + description: '' + role_ids: + - 'creator' + - 'reader' + - 'updater' + - 'deleter' + - 'storage_reader' + resource_paths: + - '/gen3' + + - id: 'gen3-hmb-researcher' + description: '' + role_ids: + - 'creator' + - 'reader' + - 'updater' + - 'deleter' + - 'storage_reader' + resource_paths: + - '/consents/NRES' + - '/consents/GRU' + - '/consents/GRU_CC' + - '/consents/HMB' + - '/gen3' + + - id: 'abc.programs.test_program.projects.test_project1-viewer' + description: '' + role_ids: + - 'reader' + - 'storage_reader' + resource_paths: + - '/abc/programs/test_program/projects/test_project1' + + - id: 'abc.programs.test_program.projects.test_project2-viewer' + description: '' + role_ids: + - 'reader' + - 'storage_reader' + resource_paths: + - '/abc/programs/test_program/projects/test_project2' + + - id: 'abc.programs.test_program2.projects.test_project3-viewer' + description: '' + role_ids: + - 'reader' + - 'storage_reader' + resource_paths: + - '/abc/programs/test_program2/projects/test_project3' + + # Open data policies + - id: 'authn_open_access' + resource_paths: ['/programs/open/projects/authnRequired'] + description: '' + role_ids: + - 'reader' + - 'storage_reader' + - id: 'full_open_access' + resource_paths: ['/programs/open/projects/1000G'] + description: '' + role_ids: + - 'reader' + - 'storage_reader' + - id: 'open_data_reader' + description: '' + role_ids: + - 'reader' + - 'storage_reader' + resource_paths: ['/open'] + - id: 'open_data_admin' + description: '' + role_ids: + - 'creator' + - 'reader' + - 'updater' + - 'deleter' + - 'storage_writer' + - 'storage_reader' + resource_paths: ['/open'] + + # Consent Code Policies + - id: 'not-for-profit-researcher' + description: '' + role_ids: + - 'admin' + resource_paths: + - '/consents/NPU' + + - id: 'publication-required-researcher' + description: '' + role_ids: + - 'admin' + resource_paths: + - '/consents/PUB' + + - id: 'gru-researcher' + description: '' + role_ids: + - 'admin' + resource_paths: + - '/consents/NRES' + - '/consents/GRU' + + - id: 'gru-cc-researcher' + description: '' + role_ids: + - 'admin' + resource_paths: + - '/consents/NRES' + - '/consents/GRU' + - '/consents/GRU_CC' + + - id: 'hmb-researcher' + description: '' + role_ids: + - 'admin' + resource_paths: + - '/consents/NRES' + - '/consents/GRU' + - '/consents/GRU_CC' + - '/consents/HMB' + + - id: 'poa-researcher' + description: '' + role_ids: + - 'admin' + resource_paths: + - '/consents/NRES' + - '/consents/GRU' + - '/consents/GRU_CC' + - '/consents/POA' + + - id: 'ds-lung-researcher' + description: '' + role_ids: + - 'admin' + resource_paths: + - '/consents/NRES' + - '/consents/GRU' + - '/consents/GRU_CC' + - '/consents/HMB' + - '/consents/DS_LungDisease' + + - id: 'ds-chronic-obstructive-pulmonary-disease-researcher' + description: '' + role_ids: + - 'admin' + resource_paths: + - '/consents/NRES' + - '/consents/GRU' + - '/consents/GRU_CC' + - '/consents/HMB' + - '/consents/DS_ChronicObstructivePulmonaryDisease' + + - id: 'services.sheepdog-admin' + description: 'CRUD access to programs and projects' + role_ids: + - 'sheepdog_admin' + resource_paths: + - '/services/sheepdog/submission/program' + - '/services/sheepdog/submission/project' + + # indexd + - id: 'indexd_admin' + description: 'full access to indexd API' + role_ids: + - 'indexd_admin' + resource_paths: + - '/programs' + - '/services/indexd/admin' + # # TODO resource path '/' is not valid right now in arborist, trying to decide + # # how to handle all resources + # - id: 'indexd_admin' + # description: '' + # role_ids: + # - 'indexd_record_creator' + # - 'indexd_record_reader' + # - 'indexd_record_updater' + # - 'indexd_delete_record' + # - 'indexd_storage_reader' + # - 'indexd_storage_writer' + # resource_paths: ['/'] + # - id: 'indexd_record_reader' + # description: '' + # role_ids: + # - 'indexd_record_reader' + # resource_paths: ['/'] + # - id: 'indexd_record_editor' + # description: '' + # role_ids: + # - 'indexd_record_creator' + # - 'indexd_record_reader' + # - 'indexd_record_updater' + # - 'indexd_delete_record' + # resource_paths: ['/'] + # - id: 'indexd_storage_reader' + # description: '' + # role_ids: + # - 'indexd_storage_reader' + # resource_paths: ['/'] + # - id: 'indexd_storage_editor' + # description: '' + # role_ids: + # - 'indexd_storage_reader' + # - 'indexd_storage_writer' + # resource_paths: ['/'] + + # argo + - id: argo + description: be able to use argo + resource_paths: [/argo] + role_ids: [argo_user] + + resources: + # General Access + - name: 'data_file' + description: 'data files, stored in S3' + - name: 'dashboard' + description: 'commons /dashboard' + - name: 'mds_gateway' + description: 'commons /mds-admin' + - name: 'prometheus' + description: 'commons /prometheus and /grafana' + - name: 'ttyadmin' + description: 'commons /ttyadmin' + - name: 'workspace' + - name: "sower" + - name: 'mariner' + description: 'workflow execution service' + - name: argo + + # OLD Data + - name: 'programs' + subresources: + - name: 'open' + subresources: + - name: 'projects' + subresources: + - name: '1000G' + - name: 'authnRequired' + - name: 'QA' + subresources: + - name: 'projects' + subresources: + - name: 'test' + - name: 'DEV' + subresources: + - name: 'projects' + subresources: + - name: 'test' + - name: 'jnkns' + subresources: + - name: 'projects' + subresources: + - name: 'jenkins' + - name: 'jenkins2' + - name: 'test' + subresources: + - name: 'projects' + subresources: + - name: 'test' + + # NEW Data WITH PREFIX + - name: 'gen3' + subresources: + - name: 'programs' + subresources: + - name: 'QA' + subresources: + - name: 'projects' + subresources: + - name: 'test' + - name: 'DEV' + subresources: + - name: 'projects' + subresources: + - name: 'test' + - name: 'jnkns' + subresources: + - name: 'projects' + subresources: + - name: 'jenkins' + - name: 'jenkins2' + - name: 'test' + subresources: + - name: 'projects' + subresources: + - name: 'test' + + # consents obtained from DUO and NIH + # https://github.com/EBISPOT/DUO + # https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4721915/ + - name: 'consents' + subresources: + - name: 'NRES' + description: 'no restriction' + - name: 'GRU' + description: 'general research use' + - name: 'GRU_CC' + description: 'general research use and clinical care' + - name: 'HMB' + description: 'health/medical/biomedical research' + - name: 'POA' + description: 'population origins or ancestry research' + - name: 'NMDS' + description: 'no general methods research' + - name: 'NPU' + description: 'not-for-profit use only' + - name: 'PUB' + description: 'publication required' + - name: 'DS_LungDisease' + description: 'disease-specific research for lung disease' + - name: 'DS_ChronicObstructivePulmonaryDisease' + description: 'disease-specific research for chronic obstructive pulmonary disease' + + - name: 'abc' + subresources: + - name: 'programs' + subresources: + - name: 'foo' + subresources: + - name: 'projects' + subresources: + - name: 'bar' + - name: 'test_program' + subresources: + - name: 'projects' + subresources: + - name: 'test_project1' + - name: 'test_project2' + - name: 'test_program2' + subresources: + - name: 'projects' + subresources: + - name: 'test_project3' + + + # "Sheepdog admin" resources + - name: 'services' + subresources: + - name: 'sheepdog' + subresources: + - name: 'submission' + subresources: + - name: 'program' + - name: 'project' + - name: 'indexd' + subresources: + - name: 'admin' + - name: 'bundles' + - name: audit + subresources: + - name: presigned_url + - name: login + + + - name: 'open' + + # action/methods: + # create, read, update, delete, read-storage, write-storage, + # file_upload, access + roles: + # General Access + - id: 'file_uploader' + description: 'can upload data files' + permissions: + - id: 'file_upload' + action: + service: '*' + method: 'file_upload' + - id: 'workspace_user' + permissions: + - id: 'workspace_access' + action: + service: 'jupyterhub' + method: 'access' + - id: 'dashboard_user' + permissions: + - id: 'dashboard_access' + action: + service: 'dashboard' + method: 'access' + - id: 'mds_user' + permissions: + - id: 'mds_access' + action: + service: 'mds_gateway' + method: 'access' + - id: 'prometheus_user' + permissions: + - id: 'prometheus_access' + action: + service: 'prometheus' + method: 'access' + - id: 'ttyadmin_user' + permissions: + - id: 'ttyadmin_access' + action: + service: 'ttyadmin' + method: 'access' + - id: 'sower_user' + permissions: + - id: 'sower_access' + action: + service: 'job' + method: 'access' + - id: 'mariner_admin' + permissions: + - id: 'mariner_access' + action: + service: 'mariner' + method: 'access' + - id: audit_reader + permissions: + - id: audit_reader_action + action: + service: audit + method: read + + # All services + - id: 'admin' + description: '' + permissions: + - id: 'admin' + action: + service: '*' + method: '*' + - id: 'creator' + description: '' + permissions: + - id: 'creator' + action: + service: '*' + method: 'create' + - id: 'reader' + description: '' + permissions: + - id: 'reader' + action: + service: '*' + method: 'read' + - id: 'updater' + description: '' + permissions: + - id: 'updater' + action: + service: '*' + method: 'update' + - id: 'deleter' + description: '' + permissions: + - id: 'deleter' + action: + service: '*' + method: 'delete' + - id: 'storage_writer' + description: '' + permissions: + - id: 'storage_writer' + action: + service: '*' + method: 'write-storage' + - id: 'storage_reader' + description: '' + permissions: + - id: 'storage_reader' + action: + service: '*' + method: 'read-storage' + + + # Sheepdog admin role + - id: 'sheepdog_admin' + description: 'sheepdog admin role for program project crud' + permissions: + - id: 'sheepdog_admin_action' + action: + service: 'sheepdog' + method: '*' + + + # indexd + - id: 'indexd_admin' + # this only works if indexd.arborist is enabled in manifest! + description: 'full access to indexd API' + permissions: + - id: 'indexd_admin' + action: + service: 'indexd' + method: '*' + - id: 'indexd_record_creator' + description: '' + permissions: + - id: 'indexd_record_creator' + action: + service: 'indexd' + method: 'create' + - id: 'indexd_record_reader' + description: '' + permissions: + - id: 'indexd_record_reader' + action: + service: 'indexd' + method: 'read' + - id: 'indexd_record_updater' + description: '' + permissions: + - id: 'indexd_record_updater' + action: + service: 'indexd' + method: 'update' + - id: 'indexd_delete_record' + description: '' + permissions: + - id: 'indexd_delete_record' + action: + service: 'indexd' + method: 'delete' + - id: 'indexd_storage_reader' + description: '' + permissions: + - id: 'indexd_storage_reader' + action: + service: 'indexd' + method: 'read-storage' + - id: 'indexd_storage_writer' + description: '' + permissions: + - id: 'indexd_storage_writer' + action: + service: 'indexd' + method: 'write-storage' + + # arborist + - id: 'arborist_creator' + description: '' + permissions: + - id: 'arborist_creator' + action: + service: 'arborist' + method: 'create' + - id: 'arborist_reader' + description: '' + permissions: + - id: 'arborist_reader' + action: + service: 'arborist' + method: 'read' + - id: 'arborist_updater' + description: '' + permissions: + - id: 'arborist_updater' + action: + service: 'arborist' + method: 'update' + - id: 'arborist_deleter' + description: '' + permissions: + - id: 'arborist_deleter' + action: + service: 'arborist' + method: 'delete' + + # requestor + - id: requestor_admin + permissions: + - id: requestor_admin_action + action: + service: requestor + method: '*' + - id: requestor_reader + permissions: + - id: requestor_reader_action + action: + service: requestor + method: read + - id: requestor_creator + permissions: + - id: requestor_creator_action + action: + service: requestor + method: create + - id: requestor_updater + permissions: + - id: requestor_updater_action + action: + service: requestor + method: update + - id: requestor_deleter + permissions: + - id: requestor_deleter_action + action: + service: requestor + method: delete + # argo + - id: argo_user + permissions: + - id: argo_access + action: + service: argo + method: access + + clients: + basic-test-client: + policies: + - abc-admin + - gen3-admin + basic-test-abc-client: + policies: + - abc-admin + wts: + policies: + - all_programs_reader + - workspace + + users: + ### BEGIN INTERNS SECTION ### + ### END INTERNS SECTION ### + qureshi@uchicago.edu: + admin: true + policies: + - data_upload + - workspace + - dashboard + - mds_admin + - prometheus + - sower + - services.sheepdog-admin + - programs.QA-admin + - programs.test-admin + - programs.DEV-admin + - programs.jnkns-admin + - indexd_admin + - ttyadmin + projects: + - auth_id: QA + privilege: [create, read, update, delete, upload, read-storage] + - auth_id: test + privilege: [create, read, update, delete, upload, read-storage] + - auth_id: DEV + privilege: [create, read, update, delete, upload, read-storage] + - auth_id: jenkins + privilege: [create, read, update, delete, upload, read-storage] + - auth_id: jenkins2 + privilege: [create, read, update, delete, upload, read-storage] + - auth_id: jnkns + privilege: [create, read, update, delete, upload, read-storage] -#### FENCE CONFIG #### +#### FENCE CONFIG #### FENCE_CONFIG: APP_NAME: 'Gen3 Data Commons' - BASE_URL: 'https://localhost/user' - # A URL-safe base64-encoded 32-byte key for encrypting keys in db # in python you can use the following script to generate one: @@ -504,7 +1430,7 @@ FENCE_CONFIG: # In the case where Cognito is being used solely as an intermediary to a single IdP, # and that IdP is a SAML IdP with no 'email_verified' outgoing claim, but it is safe # to assume all emails from this SAML IdP are in fact verified, we may set this to True - assume_emails_verified: False + # assume_emails_verified: False # CILogon subscribers can create and manage OIDC clients using COmanage Registry. # Free tier users may request OIDC clients at https://cilogon.org/oauth2/register cilogon: @@ -586,7 +1512,7 @@ FENCE_CONFIG: # default to NIH login. # - Optional parameters: "desc" (description) and "secondary" (boolean - can # be used by the frontend to display secondary buttons differently). - LOGIN_OPTIONS: #[] # !!! remove the empty list to enable login options! + LOGIN_OPTIONS: - name: 'Login from Google' desc: 'description' idp: google @@ -1192,4 +2118,4 @@ FENCE_CONFIG: fallback_to_dbgap_sftp: false visa_types: ras: ["https://ras.nih.gov/visas/v1", "https://ras.nih.gov/visas/v1.1"] - RAS_USERINFO_ENDPOINT: '/openid/connect/v1.1/userinfo' \ No newline at end of file + RAS_USERINFO_ENDPOINT: '/openid/connect/v1.1/userinfo' diff --git a/helm/gen3-test-data-job/Chart.yaml b/helm/gen3-test-data-job/Chart.yaml index feeefb98..d23d05b4 100644 --- a/helm/gen3-test-data-job/Chart.yaml +++ b/helm/gen3-test-data-job/Chart.yaml @@ -10,12 +10,12 @@ description: A Helm chart for generating dummy data in gen3 # Library charts provide useful utilities or functions for the chart developer. They're included as # a dependency of application charts to inject those utilities and functions into the rendering # pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application +type: library # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/gen3-test-data-job/README.md b/helm/gen3-test-data-job/README.md new file mode 100644 index 00000000..befffc8d --- /dev/null +++ b/helm/gen3-test-data-job/README.md @@ -0,0 +1,19 @@ +# gen3-test-data-job + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: library](https://img.shields.io/badge/Type-library-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for generating dummy data in gen3 + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| fence.image | string | `"quay.io/cdis/fence:master"` | | +| gentestdata.max_examples | string | `"10"` | | +| gentestdata.submission_order | string | `"submitted_unaligned_reads"` | | +| gentestdata.submission_user | string | `"cdis.autotest@gmail.com"` | | +| gentestdata.test_program | string | `"DEV"` | | +| gentestdata.test_project | string | `"test"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/gen3-test-data-job/templates/_jobs.tpl b/helm/gen3-test-data-job/templates/_jobs.tpl new file mode 100644 index 00000000..7a5a005c --- /dev/null +++ b/helm/gen3-test-data-job/templates/_jobs.tpl @@ -0,0 +1,356 @@ + +{{/* +Generate Test data +*/}} +{{- define "gen3-test-data-job.gentestdata-job" -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: gentestdata-job-{{ randAlphaNum 6 | lower }} +spec: + backoffLimit: 0 + template: + metadata: + labels: + app: gen3job + spec: + serviceAccountName: useryaml-job + volumes: + - name: yaml-merge + configMap: + name: "fence-yaml-merge" + - name: shared-data + emptyDir: {} +# ----------------------------------------------------------------------------- +# DEPRECATED! Remove when all commons are no longer using local_settings.py +# for fence. +# ----------------------------------------------------------------------------- + - name: old-config-volume + secret: + secretName: "fence-secret" + - name: creds-volume + secret: + secretName: "fence-creds" + - name: config-helper + configMap: + name: config-helper + - name: json-secret-volume + secret: + secretName: "fence-json-secret" +# ----------------------------------------------------------------------------- + - name: config-volume + secret: + secretName: "fence-config" + - name: fence-jwt-keys + secret: + secretName: "fence-jwt-keys" + containers: + - name: auto-qa + image: quay.io/cdis/data-simulator:master + imagePullPolicy: Always + env: + - name: PYTHONPATH + value: /var/www/fence + - name: DICTIONARY_URL + valueFrom: + configMapKeyRef: + name: manifest-global + key: dictionary_url + - name: HOSTNAME + valueFrom: + configMapKeyRef: + name: global + key: hostname + - name: TEST_PROGRAM + value: "{{ .Values.gentestdata.test_program }}" + - name: TEST_PROJECT + value: "{{ .Values.gentestdata.test_project }}" + - name: MAX_EXAMPLES + value: "{{ .Values.gentestdata.max_examples }}" + - name: SUBMISSION_ORDER + value: "{{ .Values.gentestdata.submission_order }}" + volumeMounts: + - name: shared-data + mountPath: /mnt/shared + command: ["/bin/bash" ] + args: + - "-c" + - | + let count=0 + while [[ ! -f /mnt/shared/access_token.txt && $count -lt 50 ]]; do + echo "waiting for /mnt/shared/access_token.txt"; + sleep 2 + let count=$count+1 + done + + mkdir -p /TestData + data-simulator simulate --url $DICTIONARY_URL --path /TestData --program $TEST_PROGRAM --project $TEST_PROJECT --max_samples $MAX_EXAMPLES + + echo "define submission order" + data-simulator submission_order --url $DICTIONARY_URL --path /TestData --node_name $SUBMISSION_ORDER + + echo "Preparing to submit data" + data-simulator submitting_data --host https://$HOSTNAME --dir /TestData/ --project "$TEST_PROGRAM/$TEST_PROJECT" --access_token /mnt/shared/access_token.txt + echo "All Done - always succeed to avoid k8s retries" + - name: fence + image: {{ .Values.fence.image }} + imagePullPolicy: Always + env: + - name: PYTHONPATH + value: /var/www/fence + - name: SUBMISSION_USER + value: "{{ .Values.gentestdata.submission_user }}" + - name: TOKEN_EXPIRATION + value: "3600" + - name: FENCE_PUBLIC_CONFIG + valueFrom: + configMapKeyRef: + name: manifest-fence + key: fence-config-public.yaml + optional: true + volumeMounts: +# ----------------------------------------------------------------------------- +# DEPRECATED! Remove when all commons are no longer using local_settings.py +# for fence. +# ----------------------------------------------------------------------------- + - name: "old-config-volume" + readOnly: true + mountPath: "/var/www/fence/local_settings.py" + subPath: local_settings.py + - name: "creds-volume" + readOnly: true + mountPath: "/var/www/fence/creds.json" + subPath: creds.json + - name: "config-helper" + readOnly: true + mountPath: "/var/www/fence/config_helper.py" + subPath: config_helper.py + - name: "json-secret-volume" + readOnly: true + mountPath: "/var/www/fence/fence_credentials.json" + subPath: fence_credentials.json +# ----------------------------------------------------------------------------- + - name: "config-volume" + readOnly: true + mountPath: "/var/www/fence/fence-config-secret.yaml" + subPath: fence-config.yaml + - name: "yaml-merge" + readOnly: true + mountPath: "/var/www/fence/yaml_merge.py" + subPath: yaml_merge.py + - name: "fence-jwt-keys" + readOnly: true + mountPath: "/fence/jwt-keys.tar" + subPath: "jwt-keys.tar" + - name: shared-data + mountPath: /mnt/shared + command: ["/bin/bash" ] + args: + - "-c" + - | + echo "${FENCE_PUBLIC_CONFIG:-""}" > "/var/www/fence/fence-config-public.yaml" + python /var/www/fence/yaml_merge.py /var/www/fence/fence-config-public.yaml /var/www/fence/fence-config-secret.yaml > /var/www/fence/fence-config.yaml + if [ -f /fence/jwt-keys.tar ]; then + cd /fence + tar xvf jwt-keys.tar + if [ -d jwt-keys ]; then + mkdir -p keys + mv jwt-keys/* keys/ + fi + fi + echo "generate access token" + echo "fence-create --path fence token-create --type access_token --username $SUBMISSION_USER --scopes openid,user,test-client --exp $TOKEN_EXPIRATION" + tempFile="$(mktemp -p /tmp token.txt_XXXXXX)" + success=false + count=0 + sleepTime=10 + # retry loop + while [[ $count -lt 3 && $success == false ]]; do + if fence-create --path fence token-create --type access_token --username $SUBMISSION_USER --scopes openid,user,test-client --exp $TOKEN_EXPIRATION > "$tempFile"; then + echo "fence-create success!" + tail -1 "$tempFile" > /mnt/shared/access_token.txt + # base64 --decode complains about invalid characters - don't know why + awk -F . '{ print $2 }' /mnt/shared/access_token.txt | base64 --decode 2> /dev/null + success=true + else + echo "fence-create failed!" + cat "$tempFile" + echo "sleep for $sleepTime, then retry" + sleep "$sleepTime" + let sleepTime=$sleepTime+$sleepTime + fi + let count=$count+1 + done + if [[ $success != true ]]; then + echo "Giving up on fence-create after $count retries - failed to create valid access token" + fi + echo "" + echo "All Done - always succeed to avoid k8s retries" + restartPolicy: Never +{{- end }} + +{{/* +A job that will create test indices with data for guppy to run upon +deployment since it requires indices to be present. +*/}} +{{ define "gen3-test-data-job.create-test-indices" -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ .Chart.Name }}-create-test-indices +spec: + template: + metadata: + labels: + app: gen3job + spec: + restartPolicy: Never + # serviceAccountName: gitops-sa + # securityContext: + # fsGroup: 1000 + volumes: + - name: cred-volume + secret: + secretName: aws-config + containers: + - name: create-indices + image: quay.io/cdis/awshelper:master + env: + - name: GEN3_HOME + value: /home/ubuntu/cloud-automation + - name: GUPPY_INDICES + value: {{ range $.Values.indices }} {{ .index }} {{ end }} + - name: GUPPY_CONFIGINDEX + value: {{ .Values.configIndex }} + - name: ENVIRONMENT + value: {{ $.Values.global.environment }} + - name: BUCKET + value: {{ $.Values.global.dbRestoreBucket }} + - name: VERSION + value: {{ .Chart.Version }} + volumeMounts: + - name: cred-volume + mountPath: "/home/ubuntu/.aws/credentials" + subPath: credentials + command: [ "/bin/bash" ] + args: + - "-c" + - | + source "${GEN3_HOME}/gen3/lib/utils.sh" + gen3_load "gen3/gen3setup" + export indices="$GUPPY_CONFIGINDEX $GUPPY_INDICES" + export ESHOST="${ESHOST:-"esproxy-service:9200"}" + echo "aws s3 cp s3://$BUCKET/$ENVIRONMENT/$VERSION/elasticsearch/ . --recursive" + aws s3 cp s3://$BUCKET/$ENVIRONMENT/$VERSION/elasticsearch/ . --recursive + for index in $indices + do + gen3 nrun elasticdump --input /home/ubuntu/"$index"__mapping.json --output=http://esproxy-service:9200/$index --type mapping + gen3 nrun elasticdump --input /home/ubuntu/"$index"__data.json --output=http://esproxy-service:9200/$index --type data + done + rm dev* +{{- end }} + + +{{/* +A job that will restore a db using a pgdump file from s3 with bogus data +*/}} +{{ define "gen3-test-data-job.create-test-dbs" -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ .Chart.Name }}-test-pgdump +spec: + template: + metadata: + labels: + app: gen3job + spec: + restartPolicy: OnFailure + # serviceAccountName: gitops-sa + # securityContext: + # fsGroup: 1000 + volumes: + - name: cred-volume + secret: + secretName: aws-config + containers: + - name: restore-dbs + image: quay.io/cdis/awshelper:master + imagePullPolicy: Always + env: + - name: PGPASSWORD + {{- if $.Values.global.dev }} + valueFrom: + secretKeyRef: + name: {{ .Release.Name }}-postgresql + key: postgres-password + optional: false + {{- else }} + value: {{ .Values.global.postgres.master.password | quote}} + {{- end }} + - name: PGUSER + value: {{ .Values.global.postgres.master.username | quote }} + - name: PGPORT + valueFrom: + secretKeyRef: + name: {{ .Chart.Name }}-dbcreds + key: port + optional: false + - name: PGHOST + valueFrom: + secretKeyRef: + name: {{ .Chart.Name }}-dbcreds + key: host + optional: false + - name: SERVICE_PGUSER + valueFrom: + secretKeyRef: + name: {{ .Chart.Name }}-dbcreds + key: username + optional: false + - name: SERVICE_PGDB + valueFrom: + secretKeyRef: + name: {{ .Chart.Name }}-dbcreds + key: database + optional: false + - name: SERVICE_PGPASS + valueFrom: + secretKeyRef: + name: {{ .Chart.Name }}-dbcreds + key: password + optional: false + - name: ENVIRONMENT + value: {{ .Values.global.environment }} + - name: BUCKET + value: {{ .Values.global.dbRestoreBucket }} + - name: VERSION + value: {{ .Chart.Version }} + volumeMounts: + - name: cred-volume + mountPath: "/home/ubuntu/.aws/credentials" + subPath: credentials + command: [ "/bin/bash" ] + args: + - "-c" + - | + sleep 60 + aws s3 cp s3://$BUCKET/$ENVIRONMENT/$VERSION/pgdumps/ . --recursive + echo "PGPASSWORD=$SERVICE_PGPASS psql -d $SERVICE_PGDB -h $PGHOST -p $PGPORT -U $SERVICE_PGUSER -f db$SERVICE_PGDB.backup" + PGPASSWORD=$SERVICE_PGPASS psql -d $SERVICE_PGDB -h $PGHOST -p $PGPORT -U $SERVICE_PGUSER -f db$SERVICE_PGDB.backup + rm db* + livenessProbe: + exec: + command: + - /bin/bash + - -c + - | + echo "PGPASSWORD=$PGPASSWORD psql -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $SERVICE_PGDB" + if PGPASSWORD=$PGPASSWORD psql -U $PGUSER -lqt | cut -d \| -f 1 | grep -qw $SERVICE_PGDB; then + exit 0 + else + exit 1 + fi + initialDelaySeconds: 5 + periodSeconds: 5 +{{- end }} \ No newline at end of file diff --git a/helm/gen3-test-data-job/values.yaml b/helm/gen3-test-data-job/values.yaml index 2262cb0f..39fc9720 100644 --- a/helm/gen3-test-data-job/values.yaml +++ b/helm/gen3-test-data-job/values.yaml @@ -10,4 +10,4 @@ gentestdata: test_program: "DEV" test_project: "test" max_examples: "10" - submission_order: "submitted_unaligned_reads" \ No newline at end of file + submission_order: "submitted_unaligned_reads" diff --git a/helm/gen3/Chart.lock b/helm/gen3/Chart.lock index 597d1273..b4a65350 100644 --- a/helm/gen3/Chart.lock +++ b/helm/gen3/Chart.lock @@ -1,57 +1,66 @@ dependencies: - name: ambassador repository: file://../ambassador - version: 0.0.1 + version: 0.1.0 - name: arborist repository: file://../arborist - version: 0.0.1 + version: 0.1.0 - name: argo-wrapper repository: file://../argo-wrapper - version: 0.0.1 + version: 0.1.0 - name: audit repository: file://../audit - version: 0.0.1 + version: 0.1.0 - name: fence repository: file://../fence - version: 0.0.1 + version: 0.1.0 - name: guppy repository: file://../guppy - version: 0.0.1 + version: 0.1.0 - name: hatchery repository: file://../hatchery - version: 0.0.1 + version: 0.1.0 - name: indexd repository: file://../indexd - version: 0.0.1 + version: 0.1.0 - name: manifestservice repository: file://../manifestservice - version: 0.0.1 + version: 0.1.0 - name: metadata repository: file://../metadata - version: 0.0.1 + version: 0.1.0 - name: peregrine repository: file://../peregrine - version: 0.0.1 + version: 0.1.0 - name: pidgin repository: file://../pidgin - version: 0.0.1 + version: 0.1.0 - name: portal repository: file://../portal - version: 0.0.1 + version: 0.1.0 - name: requestor repository: file://../requestor - version: 0.0.1 + version: 0.1.0 - name: revproxy repository: file://../revproxy - version: 0.0.1 + version: 0.1.0 - name: sheepdog repository: file://../sheepdog - version: 0.0.1 + version: 0.1.0 - name: ssjdispatcher repository: file://../ssjdispatcher - version: 0.0.1 + version: 0.1.0 - name: wts repository: file://../wts - version: 0.0.1 -digest: sha256:94301835cea4dfeb07a462246b7574f9526f0808feb692272f36d0661677cab2 -generated: "2022-10-18T12:52:15.089837-05:00" + version: 0.1.0 +- name: common + repository: file://../common + version: 0.1.0 +- name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 11.9.13 +- name: gen3-test-data-job + repository: file://../gen3-test-data-job + version: 0.1.0 +digest: sha256:330133a1ccfd9678a295c0be86fd23a75344ec10ac2177277cb54020399d3fc1 +generated: "2022-12-07T10:39:13.422735+01:00" diff --git a/helm/gen3/Chart.yaml b/helm/gen3/Chart.yaml index ad52b512..4fd1d5da 100644 --- a/helm/gen3/Chart.yaml +++ b/helm/gen3/Chart.yaml @@ -1,83 +1,95 @@ apiVersion: v2 name: gen3 -description: An Umbrella Chart to conditionally deploy Gen3 Services +description: Helm chart to deploy Gen3 Data Commons -#Dependancies +# Dependancies dependencies: - name: ambassador - version: "0.0.1" + version: "0.1.0" repository: "file://../ambassador" condition: ambassador.enabled - name: arborist - version: "0.0.1" + version: "0.1.0" repository: "file://../arborist" condition: arborist.enabled - name: argo-wrapper - version: "0.0.1" + version: "0.1.0" repository: "file://../argo-wrapper" condition: argo-wrapper.enabled - name: audit - version: "0.0.1" + version: "0.1.0" repository: "file://../audit" condition: audit.enabled - name: fence - version: "0.0.1" + version: "0.1.0" repository: "file://../fence" condition: fence.enabled - name: guppy - version: "0.0.1" + version: "0.1.0" repository: "file://../guppy" condition: guppy.enabled - name: hatchery - version: "0.0.1" + version: "0.1.0" repository: "file://../hatchery" condition: hatchery.enabled - name: indexd - version: "0.0.1" + version: "0.1.0" repository: "file://../indexd" condition: indexd.enabled - name: manifestservice - version: "0.0.1" + version: "0.1.0" repository: "file://../manifestservice" condition: manifestservice.enabled - name: metadata - version: "0.0.1" + version: "0.1.0" repository: "file://../metadata" condition: metadata.enabled - name: peregrine - version: "0.0.1" + version: "0.1.0" repository: "file://../peregrine" condition: peregrine.enabled - name: pidgin - version: "0.0.1" + version: "0.1.0" repository: "file://../pidgin" condition: pidgin.enabled - name: portal - version: "0.0.1" + version: "0.1.0" repository: "file://../portal" condition: portal.enabled - name: requestor - version: "0.0.1" + version: "0.1.0" repository: "file://../requestor" condition: requestor.enabled - name: revproxy - version: "0.0.1" + version: "0.1.0" repository: "file://../revproxy" condition: revproxy.enabled - name: sheepdog - version: "0.0.1" + version: "0.1.0" repository: "file://../sheepdog" condition: sheepdog.enabled - name: ssjdispatcher - version: "0.0.1" + version: "0.1.0" repository: "file://../ssjdispatcher" condition: ssjdispatcher.enabled - name: wts - version: "0.0.1" + version: "0.1.0" repository: "file://../wts" condition: wts.enabled +- name: common + version: 0.1.0 + repository: file://../common + condition: db_creation.enabled +- name: postgresql + version: 11.9.13 + repository: "https://charts.bitnami.com/bitnami" + condition: global.postgres.dev +- name: gen3-test-data-job + version: 0.1.0 + repository: file://../gen3-test-data-job + condition: db_restore.enabled -#A chart can be either an 'application' or a 'library' chart. +# A chart can be either an 'application' or a 'library' chart. # # Application charts are a collection of templates that can be packaged into versioned archives # to be deployed. @@ -90,10 +102,26 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "master" \ No newline at end of file +appVersion: "master" + +maintainers: + - name: ahilt + email: ahilt@uchicago.edu + + - name: ajoaugustine + email: ajoa@uchicago.edu + + - name: emalinowski + email: emalinowski@uchicago.edu + + - name: EliseCastle23 + email: elisemcastle@uchicago.edu + + - name: jawadqur + email: qureshi@uchicago.edu diff --git a/helm/gen3/README.md b/helm/gen3/README.md new file mode 100644 index 00000000..c190cdf6 --- /dev/null +++ b/helm/gen3/README.md @@ -0,0 +1,131 @@ +# gen3 + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: master](https://img.shields.io/badge/AppVersion-master-informational?style=flat-square) + +Helm chart to deploy Gen3 Data Commons + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| ahilt | | | +| ajoaugustine | | | +| emalinowski | | | +| EliseCastle23 | | | +| jawadqur | | | + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../ambassador | ambassador | 0.1.0 | +| file://../arborist | arborist | 0.1.0 | +| file://../argo-wrapper | argo-wrapper | 0.1.0 | +| file://../audit | audit | 0.1.0 | +| file://../common | common | 0.1.0 | +| file://../fence | fence | 0.1.0 | +| file://../gen3-test-data-job | gen3-test-data-job | 0.1.0 | +| file://../guppy | guppy | 0.1.0 | +| file://../hatchery | hatchery | 0.1.0 | +| file://../indexd | indexd | 0.1.0 | +| file://../manifestservice | manifestservice | 0.1.0 | +| file://../metadata | metadata | 0.1.0 | +| file://../peregrine | peregrine | 0.1.0 | +| file://../pidgin | pidgin | 0.1.0 | +| file://../portal | portal | 0.1.0 | +| file://../requestor | requestor | 0.1.0 | +| file://../revproxy | revproxy | 0.1.0 | +| file://../sheepdog | sheepdog | 0.1.0 | +| file://../ssjdispatcher | ssjdispatcher | 0.1.0 | +| file://../wts | wts | 0.1.0 | +| https://charts.bitnami.com/bitnami | postgresql | 11.9.13 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| ambassador.enabled | bool | `true` | | +| ambassador.image.repository | string | `nil` | | +| ambassador.image.tag | string | `nil` | | +| arborist.enabled | bool | `true` | | +| arborist.image.repository | string | `nil` | | +| arborist.image.tag | string | `nil` | | +| argo-wrapper.enabled | bool | `true` | | +| argo-wrapper.image.repository | string | `nil` | | +| argo-wrapper.image.tag | string | `nil` | | +| audit.enabled | bool | `true` | | +| audit.image.repository | string | `nil` | | +| audit.image.tag | string | `nil` | | +| db_create | bool | `true` | | +| db_restore | bool | `false` | | +| fence.enabled | bool | `true` | | +| fence.image.repository | string | `nil` | | +| fence.image.tag | string | `nil` | | +| global.aws.account | string | `nil` | | +| global.aws.enabled | bool | `false` | | +| global.dbRestoreBucket | string | `"gen3-dummy-data"` | | +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| guppy.enabled | bool | `true` | | +| guppy.image.repository | string | `nil` | | +| guppy.image.tag | string | `nil` | | +| hatchery.enabled | bool | `true` | | +| hatchery.image.repository | string | `nil` | | +| hatchery.image.tag | string | `nil` | | +| indexd.enabled | bool | `true` | | +| indexd.image.repository | string | `nil` | | +| indexd.image.tag | string | `nil` | | +| manifestservice.enabled | bool | `true` | | +| manifestservice.image.repository | string | `nil` | | +| manifestservice.image.tag | string | `nil` | | +| metadata.enabled | bool | `true` | | +| metadata.image.repository | string | `nil` | | +| metadata.image.tag | string | `nil` | | +| peregrine.enabled | bool | `true` | | +| peregrine.image.repository | string | `nil` | | +| peregrine.image.tag | string | `nil` | | +| pidgin.enabled | bool | `true` | | +| pidgin.image.repository | string | `nil` | | +| pidgin.image.tag | string | `nil` | | +| portal.enabled | bool | `true` | | +| portal.image.repository | string | `nil` | | +| portal.image.tag | string | `nil` | | +| postgresql.primary.persistence.enabled | bool | `false` | | +| requestor.enabled | bool | `false` | | +| requestor.image.repository | string | `nil` | | +| requestor.image.tag | string | `nil` | | +| revproxy.enabled | bool | `true` | | +| revproxy.image.repository | string | `nil` | | +| revproxy.image.tag | string | `nil` | | +| secrets.awsAccessKeyId | string | `"test"` | | +| secrets.awsSecretAccessKey | string | `"test"` | | +| sheepdog.enabled | bool | `true` | | +| sheepdog.image.repository | string | `nil` | | +| sheepdog.image.tag | string | `nil` | | +| ssjdispatcher.enabled | bool | `true` | | +| ssjdispatcher.image.repository | string | `nil` | | +| ssjdispatcher.image.tag | string | `nil` | | +| wts.enabled | bool | `true` | | +| wts.image.repository | string | `nil` | | +| wts.image.tag | string | `nil` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/gen3/templates/aws_config.yaml b/helm/gen3/templates/aws_config.yaml new file mode 100644 index 00000000..3b51159c --- /dev/null +++ b/helm/gen3/templates/aws_config.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: aws-config +type: Opaque +stringData: + credentials: | + [default] + aws_access_key_id={{.Values.secrets.awsAccessKeyId}} + aws_secret_access_key={{ .Values.secrets.awsSecretAccessKey}} \ No newline at end of file diff --git a/helm/gen3/values.yaml b/helm/gen3/values.yaml index 51c9dc25..b5d32a12 100644 --- a/helm/gen3/values.yaml +++ b/helm/gen3/values.yaml @@ -1,81 +1,157 @@ +# Default values for gen3. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. global: + aws: + enabled: false + account: + dev: true postgres: - host: postgres-postgresql.postgres.svc.cluster.local + db_create: true master: + host: username: postgres - password: - port: 5432 - -# Default values for gen3. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + dbRestoreBucket: gen3-dummy-data + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false # Dependancy Charts -ambassador: - enabled: false - -arborist: +ambassador: enabled: true - -argo-wrapper: - enabled: false - -audit: - enabled: false - -fence: + image: + repository: + tag: + +arborist: enabled: true - -guppy: - enabled: false - -hatchery: + image: + repository: + tag: + +argo-wrapper: enabled: true - -indexd: + image: + repository: + tag: + +audit: enabled: true - -manifestservice: + image: + repository: + tag: + +fence: enabled: true - -metadata: - enabled: false - -peregrine: + image: + repository: + tag: + +guppy: + enabled: true + image: + repository: + tag: + +hatchery: enabled: true - -pidgin: + image: + repository: + tag: + +indexd: + enabled: true + image: + repository: + tag: + +manifestservice: enabled: true - -portal: + image: + repository: + tag: + +metadata: enabled: true - -requestor: + image: + repository: + tag: + +peregrine: enabled: true - -revproxy: + image: + repository: + tag: + +pidgin: enabled: true - -sheepdog: + image: + repository: + tag: + +portal: enabled: true + image: + repository: + tag: -ssjdispatcher: +requestor: enabled: false - + image: + repository: + tag: -# Configmap -global: - environment: default - hostname: test - revproxyArn: arn:aws:acm:us-east-1:123456:certificate - dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json - portalApp: gitops - kubeBucket: kube-gen3 - logsBucket: logs-gen3 - syncFromDbgap: False - userYamlS3Path: s3://cdis-gen3-users/test/user.yaml - publicDataSets: true - tierAccessLevel: libre - netPolicy: on - dispatcherJobNum: 10 - ddEnabled: false \ No newline at end of file +revproxy: + enabled: true + image: + repository: + tag: + +sheepdog: + enabled: true + image: + repository: + tag: + +ssjdispatcher: + enabled: true + image: + repository: + tag: + +wts: + enabled: true + image: + repository: + tag: + +# If db does not exist in postgres cluster and db_create is set ot true then all relevant dbs will be created +db_create: true + +# If db_restore is set to true then the database will have fake data/tables dumped into it. +db_restore: false + +# The db restore job requires AWS credentials to access the S3 bucket +secrets: + awsAccessKeyId: test + awsSecretAccessKey: test + +# This is to configure postgresql subchart +# Disable persistence by default so we can spin up and down ephemeral environments +postgresql: + primary: + persistence: + enabled: false diff --git a/helm/guppy/Chart.lock b/helm/guppy/Chart.lock new file mode 100644 index 00000000..6be1837f --- /dev/null +++ b/helm/guppy/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: gen3-test-data-job + repository: file://../gen3-test-data-job + version: 0.1.0 +digest: sha256:8749d68f47ad3f94b51f802b0ebf869982c07167eccb23fbeff58f9648d20d49 +generated: "2022-12-07T10:38:58.726895+01:00" diff --git a/helm/guppy/Chart.yaml b/helm/guppy/Chart.yaml index 6f526c54..7eb938e4 100644 --- a/helm/guppy/Chart.yaml +++ b/helm/guppy/Chart.yaml @@ -15,10 +15,15 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. appVersion: "2022.10" + +dependencies: + - name: gen3-test-data-job + version: 0.1.0 + repository: file://../gen3-test-data-job diff --git a/helm/guppy/README.md b/helm/guppy/README.md new file mode 100644 index 00000000..5b3e7ef9 --- /dev/null +++ b/helm/guppy/README.md @@ -0,0 +1,84 @@ +# guppy + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 Guppy Service + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../gen3-test-data-job | gen3-test-data-job | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key | string | `"app"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator | string | `"In"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0] | string | `"guppy"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey | string | `"kubernetes.io/hostname"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight | int | `100` | | +| arboristUrl | string | `"http://arborist-service"` | | +| authFilterField | string | `"auth_resource_path"` | | +| automountServiceAccountToken | bool | `false` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| configIndex | string | `"dev_case-array-config"` | | +| containerPort[0].containerPort | int | `8000` | | +| dataDog.enabled | bool | `false` | | +| dataDog.env | string | `"dev"` | | +| ddEnv | string | `nil` | | +| ddLogsInjection | string | `nil` | | +| ddProfilingEnabled | string | `nil` | | +| ddService | string | `nil` | | +| ddTraceAgentHostname | string | `nil` | | +| ddTraceEnabled | string | `nil` | | +| ddTraceSampleRate | string | `nil` | | +| ddVersion | string | `nil` | | +| enableEncryptWhitelist | bool | `true` | | +| encryptWhitelist | string | `"test1"` | | +| esEndpoint | string | `"esproxy-service:9200"` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/cdis/guppy"` | | +| image.tag | string | `""` | | +| indices[0].index | string | `"dev_case"` | | +| indices[0].type | string | `"case"` | | +| indices[1].index | string | `"dev_file"` | | +| indices[1].type | string | `"file"` | | +| livenessProbe.httpGet.path | string | `"/_status"` | | +| livenessProbe.httpGet.port | int | `8000` | | +| livenessProbe.initialDelaySeconds | int | `30` | | +| livenessProbe.periodSeconds | int | `60` | | +| livenessProbe.timeoutSeconds | int | `30` | | +| readinessProbe.httpGet.path | string | `"/_status"` | | +| readinessProbe.httpGet.port | int | `8000` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | int | `1` | | +| resources.limits.memory | string | `"2400Mi"` | | +| resources.requests.cpu | float | `0.5` | | +| resources.requests.memory | string | `"1024Mi"` | | +| revisionHistoryLimit | int | `2` | | +| service.port[0].name | string | `"http"` | | +| service.port[0].port | int | `80` | | +| service.port[0].protocol | string | `"TCP"` | | +| service.port[0].targetPort | int | `8000` | | +| service.type | string | `"ClusterIP"` | | +| strategy.rollingUpdate.maxSurge | int | `1` | | +| strategy.rollingUpdate.maxUnavailable | int | `0` | | +| strategy.type | string | `"RollingUpdate"` | | +| tierAccessLevel | string | `"regular"` | | +| tierAccessLimit | int | `1000` | | +| volumeMounts[0].mountPath | string | `"/guppy/guppy_config.json"` | | +| volumeMounts[0].name | string | `"guppy-config"` | | +| volumeMounts[0].readOnly | bool | `true` | | +| volumeMounts[0].subPath | string | `"guppy_config.json"` | | +| volumes[0].configMap.items[0].key | string | `"guppy_config.json"` | | +| volumes[0].configMap.items[0].path | string | `"guppy_config.json"` | | +| volumes[0].configMap.name | string | `"manifest-guppy"` | | +| volumes[0].name | string | `"guppy-config"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/guppy/templates/appInit.yaml b/helm/guppy/templates/appInit.yaml new file mode 100644 index 00000000..52ab4d18 --- /dev/null +++ b/helm/guppy/templates/appInit.yaml @@ -0,0 +1,3 @@ +{{- if .Values.db_restore }} +{{ include "gen3-test-data-job.create-test-indices" . }} +{{- end }} \ No newline at end of file diff --git a/helm/guppy/values.yaml b/helm/guppy/values.yaml index 99e24104..3dd076e8 100644 --- a/helm/guppy/values.yaml +++ b/helm/guppy/values.yaml @@ -2,9 +2,7 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. - - -#Deployment +# Deployment autoscaling: enabled: false minReplicas: 1 @@ -20,12 +18,12 @@ strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0 - + dataDog: enabled: false env: dev -affinity: +affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 @@ -61,15 +59,15 @@ arboristUrl: http://arborist-service tierAccessLevel: regular # acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private` tierAccessLimit: 1000 -#Placeholders for datadog -ddTraceEnabled: -ddEnv: +# Placeholders for datadog +ddTraceEnabled: +ddEnv: ddService: ddVersion: ddLogsInjection: ddProfilingEnabled: -ddTraceSampleRate: -ddTraceAgentHostname: +ddTraceSampleRate: +ddTraceAgentHostname: livenessProbe: @@ -102,7 +100,7 @@ resources: memory: 2400Mi -#Service and Pod +# Service and Pod service: type: ClusterIP port: @@ -111,13 +109,13 @@ service: targetPort: 8000 name: http -#Configmap -indices: -- index: etl - type: subject -- index: file +# Configmap +indices: +- index: dev_case + type: case +- index: dev_file type: file -configIndex: array-config +configIndex: dev_case-array-config authFilterField: auth_resource_path enableEncryptWhitelist: true -encryptWhitelist: test1 \ No newline at end of file +encryptWhitelist: test1 diff --git a/helm/hatchery/Chart.yaml b/helm/hatchery/Chart.yaml index 5d081070..6ddd2aff 100644 --- a/helm/hatchery/Chart.yaml +++ b/helm/hatchery/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/hatchery/README.md b/helm/hatchery/README.md new file mode 100644 index 00000000..f2d248a0 --- /dev/null +++ b/helm/hatchery/README.md @@ -0,0 +1,100 @@ +# hatchery + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 Hatchery + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| env[0].name | string | `"HTTP_PORT"` | | +| env[0].value | string | `"8000"` | | +| env[1].name | string | `"POD_NAMESPACE"` | | +| env[1].valueFrom.fieldRef.fieldPath | string | `"metadata.namespace"` | | +| fullnameOverride | string | `""` | | +| global.aws.account | string | `nil` | | +| global.aws.enabled | bool | `false` | | +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| hatchery.containers[0].args[0] | string | `"--NotebookApp.base_url=/lw-workspace/proxy/"` | | +| hatchery.containers[0].args[1] | string | `"--NotebookApp.default_url=/lab"` | | +| hatchery.containers[0].args[2] | string | `"--NotebookApp.password=''"` | | +| hatchery.containers[0].args[3] | string | `"--NotebookApp.token=''"` | | +| hatchery.containers[0].args[4] | string | `"--NotebookApp.shutdown_no_activity_timeout=5400"` | | +| hatchery.containers[0].args[5] | string | `"--NotebookApp.quit_button=False"` | | +| hatchery.containers[0].command[0] | string | `"start-notebook.sh"` | | +| hatchery.containers[0].cpu-limit | string | `"1.0"` | | +| hatchery.containers[0].env.FRAME_ANCESTORS | string | `"https://{{ .Values.global.hostname }}"` | | +| hatchery.containers[0].fs-gid | int | `100` | | +| hatchery.containers[0].gen3-volume-location | string | `"/home/jovyan/.gen3"` | | +| hatchery.containers[0].image | string | `"quay.io/cdis/heal-notebooks:combined_tutorials__latest"` | | +| hatchery.containers[0].lifecycle-post-start[0] | string | `"/bin/sh"` | | +| hatchery.containers[0].lifecycle-post-start[1] | string | `"-c"` | | +| hatchery.containers[0].lifecycle-post-start[2] | string | `"export IAM=`whoami`; rm -rf /home/$IAM/pd/dockerHome; rm -rf /home/$IAM/pd/lost+found; ln -s /data /home/$IAM/pd/; true"` | | +| hatchery.containers[0].memory-limit | string | `"2Gi"` | | +| hatchery.containers[0].name | string | `"(Tutorials) Example Analysis Jupyter Lab Notebooks"` | | +| hatchery.containers[0].path-rewrite | string | `"/lw-workspace/proxy/"` | | +| hatchery.containers[0].ready-probe | string | `"/lw-workspace/proxy/"` | | +| hatchery.containers[0].target-port | int | `8888` | | +| hatchery.containers[0].use-tls | string | `"false"` | | +| hatchery.containers[0].user-uid | int | `1000` | | +| hatchery.containers[0].user-volume-location | string | `"/home/jovyan/pd"` | | +| hatchery.sidecarContainer.args | list | `[]` | | +| hatchery.sidecarContainer.command[0] | string | `"/bin/bash"` | | +| hatchery.sidecarContainer.command[1] | string | `"./sidecar.sh"` | | +| hatchery.sidecarContainer.cpu-limit | string | `"1.0"` | | +| hatchery.sidecarContainer.env.GEN3_ENDPOINT | string | `"{{ .Values.global.hostname }}"` | | +| hatchery.sidecarContainer.env.HOSTNAME | string | `"{{ .Values.global.hostname }}"` | | +| hatchery.sidecarContainer.env.NAMESPACE | string | `"{{ .Release.Namespace }}"` | | +| hatchery.sidecarContainer.image | string | `"quay.io/cdis/ecs-ws-sidecar:master"` | | +| hatchery.sidecarContainer.lifecycle-pre-stop[0] | string | `"su"` | | +| hatchery.sidecarContainer.lifecycle-pre-stop[1] | string | `"-c"` | | +| hatchery.sidecarContainer.lifecycle-pre-stop[2] | string | `"echo test"` | | +| hatchery.sidecarContainer.lifecycle-pre-stop[3] | string | `"-s"` | | +| hatchery.sidecarContainer.lifecycle-pre-stop[4] | string | `"/bin/sh"` | | +| hatchery.sidecarContainer.lifecycle-pre-stop[5] | string | `"root"` | | +| hatchery.sidecarContainer.memory-limit | string | `"256Mi"` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"quay.io/cdis/hatchery"` | | +| image.tag | string | `""` | | +| imagePullSecrets | list | `[]` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| replicaCount | int | `1` | | +| resources | object | `{}` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| tolerations | list | `[]` | | +| volumeMounts[0].mountPath | string | `"/hatchery.json"` | | +| volumeMounts[0].name | string | `"hatchery-config"` | | +| volumeMounts[0].readOnly | bool | `true` | | +| volumeMounts[0].subPath | string | `"json"` | | +| volumes[0].configMap.name | string | `"manifest-hatchery"` | | +| volumes[0].name | string | `"hatchery-config"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/hatchery/templates/deployment.yaml b/helm/hatchery/templates/deployment.yaml index 62a48cd1..40d02752 100644 --- a/helm/hatchery/templates/deployment.yaml +++ b/helm/hatchery/templates/deployment.yaml @@ -26,7 +26,7 @@ spec: {{- end }} volumes: {{- toYaml .Values.volumes | nindent 8 }} - serviceAccountName: {{ include "hatchery.serviceAccountName" . }} + serviceAccountName: hatchery-service-account securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: @@ -51,6 +51,10 @@ spec: {{- toYaml .Values.resources | nindent 12 }} env: {{- toYaml .Values.env | nindent 12 }} + - name: GEN3_ENDPOINT + value: {{ .Values.global.hostname }} + - name: GEN3_VPCID + value: {{ .Values.global.environment }} volumeMounts: {{- toYaml .Values.volumeMounts | nindent 12 }} {{- with .Values.nodeSelector }} diff --git a/helm/hatchery/templates/hatchery-manifest.yaml b/helm/hatchery/templates/hatchery-manifest.yaml index 30e91cd6..777e6922 100644 --- a/helm/hatchery/templates/hatchery-manifest.yaml +++ b/helm/hatchery/templates/hatchery-manifest.yaml @@ -5,165 +5,10 @@ metadata: data: json: | { - "user-namespace": "jupyter-pods", - "sub-dir": "/lw-workspace", - "user-volume-size": "10Gi", - "sidecar": { - "cpu-limit": "1.0", - "memory-limit": "256Mi", - "image": "quay.io/cdis/ecs-ws-sidecar:2022.05", - "env": { - "NAMESPACE": "default", - "GEN3_ENDPOINT": "healdata.org", - "HOSTNAME": "healdata.org" - }, - "args": [], - "command": [ - "/bin/bash", - "./sidecar.sh" - ], - "lifecycle-pre-stop": [ - "su", - "-c", - "echo test", - "-s", - "/bin/sh", - "root" - ] - }, - "containers": [ - { - "target-port": 8888, - "cpu-limit": "1.0", - "memory-limit": "2Gi", - "name": "(Generic) Jupyter Lab Notebook with R Kernel", - "image": "quay.io/cdis/jupyter-superslim-r:1.0.1", - "env": { - "FRAME_ANCESTORS": "https://healdata.org" - }, - "args": [ - "--NotebookApp.base_url=/lw-workspace/proxy/", - "--NotebookApp.default_url=/lab", - "--NotebookApp.password=''", - "--NotebookApp.token=''", - "--NotebookApp.ip='*'", - "--NotebookApp.notebook_dir='/home/jovyan'", - "--NotebookApp.shutdown_no_activity_timeout=5400", - "--NotebookApp.quit_button=False" - ], - "command": [ - "start-notebook.sh" - ], - "path-rewrite": "/lw-workspace/proxy/", - "use-tls": "false", - "ready-probe": "/lw-workspace/proxy/", - "lifecycle-post-start": [ - "/bin/sh", - "-c", - "export IAM=`whoami`; rm -rf /home/$IAM/pd/dockerHome; rm -rf /home/$IAM/pd/lost+found; ln -s /data /home/$IAM/pd/; true" - ], - "user-uid": 1000, - "fs-gid": 100, - "user-volume-location": "/home/jovyan/pd", - "gen3-volume-location": "/home/jovyan/.gen3" - }, - { - "target-port": 8888, - "cpu-limit": "1.0", - "memory-limit": "2Gi", - "name": "(Generic, User-licensed) Stata Notebook ", - "image": "quay.io/cdis/stata-heal:master", - "env": { - "FRAME_ANCESTORS": "https://healdata.org" - }, - "args": [ - "--NotebookApp.base_url=/lw-workspace/proxy/", - "--NotebookApp.password=''", - "--NotebookApp.token=''", - "--NotebookApp.shutdown_no_activity_timeout=5400", - "--NotebookApp.quit_button=False" - ], - "command": [ - "start-notebook.sh" - ], - "path-rewrite": "/lw-workspace/proxy/", - "use-tls": "false", - "ready-probe": "/lw-workspace/proxy/", - "lifecycle-post-start": [ - "/bin/sh", - "-c", - "(while true; do [ -d ~/pd ] && [ -f ~/pd/stata.lic ] && cp ~/pd/stata.lic /usr/local/stata17/; sleep 1; done) & export IAM=`whoami`; rm -rf /home/$IAM/pd/dockerHome; rm -rf /home/$IAM/pd/lost+found; ln -s /data /home/$IAM/pd/; true" - ], - "user-uid": 1000, - "fs-gid": 100, - "user-volume-location": "/home/jovyan/pd", - "gen3-volume-location": "/home/jovyan/.gen3" - }, - { - "target-port": 8888, - "cpu-limit": "1.0", - "memory-limit": "2Gi", - "name": "(Generic, Limited Gen3-licensed) Stata Notebook", - "image": "quay.io/cdis/stata-heal:gen3-licensed", - "env": { - "FRAME_ANCESTORS": "https://healdata.org" - }, - "args": [ - "--NotebookApp.base_url=/lw-workspace/proxy/", - "--NotebookApp.password=''", - "--NotebookApp.token=''", - "--NotebookApp.shutdown_no_activity_timeout=5400", - "--NotebookApp.quit_button=False" - ], - "command": [ - "/bin/bash", - "/tmp/wait_for_license.sh" - ], - "path-rewrite": "/lw-workspace/proxy/", - "use-tls": "false", - "ready-probe": "/lw-workspace/proxy/", - "lifecycle-post-start": [ - "/bin/sh", - "-c", - "export IAM=`whoami`; rm -rf /home/$IAM/pd/dockerHome; rm -rf /home/$IAM/pd/lost+found; ln -s /data /home/$IAM/pd/; true" - ], - "user-uid": 1000, - "fs-gid": 100, - "user-volume-location": "/home/jovyan/pd", - "gen3-volume-location": "/home/jovyan/.gen3" - }, - { - "target-port": 8888, - "cpu-limit": "1.0", - "memory-limit": "2Gi", - "name": "(Tutorials) Example Analysis Jupyter Lab Notebooks", - "image": "quay.io/cdis/heal-notebooks:combined_tutorials__fbd5ce467b9c2a8e4d59c2d7ec49ad6c5c80312a", - "env": { - "FRAME_ANCESTORS": "https://healdata.org" - }, - "args": [ - "--NotebookApp.base_url=/lw-workspace/proxy/", - "--NotebookApp.default_url=/lab", - "--NotebookApp.password=''", - "--NotebookApp.token=''", - "--NotebookApp.shutdown_no_activity_timeout=5400", - "--NotebookApp.quit_button=False" - ], - "command": [ - "start-notebook.sh" - ], - "path-rewrite": "/lw-workspace/proxy/", - "use-tls": "false", - "ready-probe": "/lw-workspace/proxy/", - "lifecycle-post-start": [ - "/bin/sh", - "-c", - "export IAM=`whoami`; rm -rf /home/$IAM/pd/dockerHome; rm -rf /home/$IAM/pd/lost+found; ln -s /data /home/$IAM/pd/; true" - ], - "user-uid": 1000, - "fs-gid": 100, - "user-volume-location": "/home/jovyan/pd", - "gen3-volume-location": "/home/jovyan/.gen3" - } - ] - } \ No newline at end of file + "user-namespace": "jupyter-pods-{{ .Release.Name }}", + "localdev": {{ .Values.global.dev }}, + "sub-dir": "/lw-workspace", + "user-volume-size": "10Gi", + "sidecar": {{ tpl (.Values.hatchery.sidecarContainer | toJson) . }}, + "containers": {{ tpl (.Values.hatchery.containers | toJson) . }} + } \ No newline at end of file diff --git a/helm/hatchery/templates/jupyter-namespace.yaml b/helm/hatchery/templates/jupyter-namespace.yaml new file mode 100644 index 00000000..cf7841a7 --- /dev/null +++ b/helm/hatchery/templates/jupyter-namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: "jupyter-pods-{{ .Release.Name }}" diff --git a/helm/hatchery/templates/serviceaccount.yaml b/helm/hatchery/templates/serviceaccount.yaml index f012aeb6..0640fac8 100644 --- a/helm/hatchery/templates/serviceaccount.yaml +++ b/helm/hatchery/templates/serviceaccount.yaml @@ -1,12 +1,38 @@ -{{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount metadata: - name: {{ include "hatchery.serviceAccountName" . }} - labels: - {{- include "hatchery.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} + name: hatchery-service-account + {{- if .Values.global.aws.enabled }} annotations: - {{- toYaml . | nindent 4 }} + eks.amazonaws.com/role-arn: arn:aws:iam::{{ .Values.global.aws.account }}:role/{{ .Values.global.aws.hatchery_role }} {{- end }} -{{- end }} + +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: hatchery-binding +subjects: +- kind: ServiceAccount + name: hatchery-service-account + apiGroup: "" + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: admin + apiGroup: rbac.authorization.k8s.io +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: hatchery-clusterrolebinding-{{ .Release.Namespace }} + namespace: jupyter-pods +subjects: +- kind: ServiceAccount + name: hatchery-service-account + apiGroup: "" + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: admin + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/helm/hatchery/values.yaml b/helm/hatchery/values.yaml index 51946ade..fae3aa38 100644 --- a/helm/hatchery/values.yaml +++ b/helm/hatchery/values.yaml @@ -1,66 +1,52 @@ # Default values for hatchery. # This is a YAML-formatted file. # Declare variables to be passed into your templates. +# Declare variables to be passed into your templates. +global: + aws: + enabled: false + account: + dev: true + postgres: + db_create: true + master: + host: + username: postgres + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false + replicaCount: 1 image: - # repository: mendhak/http-https-echo repository: quay.io/cdis/hatchery pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. - tag: "latest" + tag: "" imagePullSecrets: [] nameOverride: "" fullnameOverride: "" -serviceAccount: - # Specifies whether a service account should be created - create: true - # 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: "" - -podAnnotations: {} - -podSecurityContext: {} - # fsGroup: 2000 - -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 service: type: ClusterIP port: 80 -ingress: - enabled: true - className: "" - annotations: { - nginx.ingress.kubernetes.io/rewrite-target: /$2, - kubernetes.io/ingress.class: "nginx", - nginx.ingress.kubernetes.io/allow-headers: REMOTE_USER - } - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: ingress.local - paths: - - path: "/lw-workspace(/|$)(.*)" - pathType: Prefix - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - resources: {} # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little @@ -86,9 +72,14 @@ tolerations: [] affinity: {} -env: +env: - name: HTTP_PORT value: "8000" +- name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + volumes: - name: hatchery-config @@ -99,4 +90,56 @@ volumeMounts: - name: hatchery-config readOnly: true mountPath: /hatchery.json - subPath: json \ No newline at end of file + subPath: json + + +hatchery: + sidecarContainer: + cpu-limit: '1.0' + memory-limit: 256Mi + image: quay.io/cdis/ecs-ws-sidecar:master + env: + NAMESPACE: "{{ .Release.Namespace }}" + GEN3_ENDPOINT: "{{ .Values.global.hostname }}" + HOSTNAME: "{{ .Values.global.hostname }}" + args: [] + command: + - "/bin/bash" + - "./sidecar.sh" + lifecycle-pre-stop: + - su + - "-c" + - echo test + - "-s" + - "/bin/sh" + - root + + containers: + - target-port: 8888 + cpu-limit: '1.0' + memory-limit: 2Gi + name: "(Tutorials) Example Analysis Jupyter Lab Notebooks" + image: quay.io/cdis/heal-notebooks:combined_tutorials__latest + env: + FRAME_ANCESTORS: https://{{ .Values.global.hostname }} + args: + - "--NotebookApp.base_url=/lw-workspace/proxy/" + - "--NotebookApp.default_url=/lab" + - "--NotebookApp.password=''" + - "--NotebookApp.token=''" + - "--NotebookApp.shutdown_no_activity_timeout=5400" + - "--NotebookApp.quit_button=False" + command: + - start-notebook.sh + path-rewrite: "/lw-workspace/proxy/" + use-tls: 'false' + ready-probe: "/lw-workspace/proxy/" + lifecycle-post-start: + - "/bin/sh" + - "-c" + - export IAM=`whoami`; rm -rf /home/$IAM/pd/dockerHome; rm -rf /home/$IAM/pd/lost+found; + ln -s /data /home/$IAM/pd/; true + user-uid: 1000 + fs-gid: 100 + user-volume-location: "/home/jovyan/pd" + gen3-volume-location: "/home/jovyan/.gen3" diff --git a/helm/indexd/Chart.lock b/helm/indexd/Chart.lock index 9edc4c55..7cf496c4 100644 --- a/helm/indexd/Chart.lock +++ b/helm/indexd/Chart.lock @@ -1,6 +1,9 @@ dependencies: - name: common repository: file://../common - version: 0.0.1 -digest: sha256:9447ea9a4ddee41221215f9d511d904829f457523bc78ddaa817c161e934f27f -generated: "2022-10-20T21:34:38.85688-05:00" + version: 0.1.0 +- name: gen3-test-data-job + repository: file://../gen3-test-data-job + version: 0.1.0 +digest: sha256:69c9702ec96903c40a92569ca312d854a7dc2dc85be0fdbf75408a54df8beaf6 +generated: "2022-12-07T10:38:58.725167+01:00" diff --git a/helm/indexd/Chart.yaml b/helm/indexd/Chart.yaml index a80853b8..ac34aba9 100644 --- a/helm/indexd/Chart.yaml +++ b/helm/indexd/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,7 +25,11 @@ appVersion: "2022.10" dependencies: -- name: common - version: 0.0.1 - repository: file://../common - condition: db_creation.enabled \ No newline at end of file + - name: common + version: 0.1.0 + repository: file://../common + condition: db_creation.enabled + - name: gen3-test-data-job + version: 0.1.0 + repository: file://../gen3-test-data-job + condition: db_restore.enabled diff --git a/helm/indexd/README.md b/helm/indexd/README.md new file mode 100644 index 00000000..f4db3ec8 --- /dev/null +++ b/helm/indexd/README.md @@ -0,0 +1,68 @@ +# indexd + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 indexd + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../common | common | 0.1.0 | +| file://../gen3-test-data-job | gen3-test-data-job | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| db_create | bool | `true` | | +| env[0].name | string | `"GEN3_DEBUG"` | | +| env[0].value | string | `"False"` | | +| fullnameOverride | string | `""` | | +| global.dev | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"quay.io/cdis/indexd"` | | +| image.tag | string | `""` | | +| imagePullSecrets | list | `[]` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | | +| podSecurityContext | object | `{}` | | +| postgres.database | string | `"indexd"` | | +| postgres.db_restore | bool | `false` | | +| postgres.host | string | `nil` | | +| postgres.password | string | `nil` | | +| postgres.port | string | `"5432"` | | +| postgres.username | string | `"indexd"` | | +| replicaCount | int | `1` | | +| resources | object | `{}` | | +| secrets.userdb.fence | string | `nil` | | +| secrets.userdb.gateway | string | `nil` | | +| secrets.userdb.gdcapi | string | `nil` | | +| securityContext | object | `{}` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `false` | | +| serviceAccount.name | string | `""` | | +| tolerations | list | `[]` | | +| volumeMounts[0].mountPath | string | `"/var/www/indexd/local_settings.py"` | | +| volumeMounts[0].name | string | `"config-volume"` | | +| volumeMounts[0].readOnly | bool | `true` | | +| volumeMounts[0].subPath | string | `"local_settings.py"` | | +| volumes[0].name | string | `"config-volume"` | | +| volumes[0].secret.secretName | string | `"indexd-settings"` | | +| volumes[1].name | string | `"creds-volume"` | | +| volumes[1].secret.secretName | string | `"indexd-creds"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/indexd/indexd-secret/config_helper.py b/helm/indexd/indexd-secret/config_helper.py deleted file mode 100644 index 6b303bea..00000000 --- a/helm/indexd/indexd-secret/config_helper.py +++ /dev/null @@ -1,376 +0,0 @@ -import json -import os -import copy -import argparse -import re -import types - -# -# make it easy to change this for testing -XDG_DATA_HOME = os.getenv("XDG_DATA_HOME", "/usr/share/") - - -def default_search_folders(app_name): - """ - Return the list of folders to search for configuration files - """ - return [ - "%s/cdis/%s" % (XDG_DATA_HOME, app_name), - "/usr/share/cdis/%s" % app_name, - "%s/gen3/%s" % (XDG_DATA_HOME, app_name), - "/usr/share/gen3/%s" % app_name, - "/var/www/%s" % app_name, - "/etc/gen3/%s" % app_name, - ] - - -def find_paths(file_name, app_name, search_folders=None): - """ - Search the given folders for file_name - search_folders defaults to default_search_folders if not specified - return the first path to file_name found - """ - search_folders = search_folders or default_search_folders(app_name) - possible_files = [os.path.join(folder, file_name) for folder in search_folders] - return [path for path in possible_files if os.path.exists(path)] - - -def load_json(file_name, app_name, search_folders=None): - """ - json.load(file_name) after finding file_name in search_folders - - return the loaded json data or None if file not found - """ - actual_files = find_paths(file_name, app_name, search_folders) - if not actual_files: - return None - with open(actual_files[0], "r") as reader: - return json.load(reader) - - -def inject_creds_into_fence_config(creds_file_path, config_file_path): - creds_file = open(creds_file_path, "r") - creds = json.load(creds_file) - creds_file.close() - - # get secret values from creds.json file - db_host = _get_nested_value(creds, "db_host") - db_username = _get_nested_value(creds, "db_username") - db_password = _get_nested_value(creds, "db_password") - db_database = _get_nested_value(creds, "db_database") - hostname = _get_nested_value(creds, "hostname") - indexd_password = _get_nested_value(creds, "indexd_password") - google_client_secret = _get_nested_value(creds, "google_client_secret") - google_client_id = _get_nested_value(creds, "google_client_id") - hmac_key = _get_nested_value(creds, "hmac_key") - db_path = "postgresql://{}:{}@{}:5432/{}".format( - db_username, db_password, db_host, db_database - ) - - config_file = open(config_file_path, "r").read() - - print(" DB injected with value(s) from creds.json") - config_file = _replace(config_file, "DB", db_path) - - print(" BASE_URL injected with value(s) from creds.json") - config_file = _replace(config_file, "BASE_URL", "https://{}/user".format(hostname)) - - print(" INDEXD_PASSWORD injected with value(s) from creds.json") - config_file = _replace(config_file, "INDEXD_PASSWORD", indexd_password) - config_file = _replace(config_file, "INDEXD_USERNAME", "fence") - - print(" ENCRYPTION_KEY injected with value(s) from creds.json") - config_file = _replace(config_file, "ENCRYPTION_KEY", hmac_key) - - print( - " OPENID_CONNECT/google/client_secret injected with value(s) " - "from creds.json" - ) - config_file = _replace( - config_file, "OPENID_CONNECT/google/client_secret", google_client_secret - ) - - print(" OPENID_CONNECT/google/client_id injected with value(s) from creds.json") - config_file = _replace( - config_file, "OPENID_CONNECT/google/client_id", google_client_id - ) - - open(config_file_path, "w+").write(config_file) - - -def set_prod_defaults(config_file_path): - config_file = open(config_file_path, "r").read() - - print( - " CIRRUS_CFG/GOOGLE_APPLICATION_CREDENTIALS set as " - "var/www/fence/fence_google_app_creds_secret.json" - ) - config_file = _replace( - config_file, - "CIRRUS_CFG/GOOGLE_APPLICATION_CREDENTIALS", - "/var/www/fence/fence_google_app_creds_secret.json", - ) - - print( - " CIRRUS_CFG/GOOGLE_STORAGE_CREDS set as " - "var/www/fence/fence_google_storage_creds_secret.json" - ) - config_file = _replace( - config_file, - "CIRRUS_CFG/GOOGLE_STORAGE_CREDS", - "/var/www/fence/fence_google_storage_creds_secret.json", - ) - - print(" INDEXD set as http://indexd-service/") - config_file = _replace(config_file, "INDEXD", "http://indexd-service/") - - print(" ARBORIST set as http://arborist-service/") - config_file = _replace(config_file, "ARBORIST", "http://arborist-service/") - - print(" HTTP_PROXY/host set as cloud-proxy.internal.io") - config_file = _replace(config_file, "HTTP_PROXY/host", "cloud-proxy.internal.io") - - print(" HTTP_PROXY/port set as 3128") - config_file = _replace(config_file, "HTTP_PROXY/port", 3128) - - print(" DEBUG set to false") - config_file = _replace(config_file, "DEBUG", False) - - print(" MOCK_AUTH set to false") - config_file = _replace(config_file, "MOCK_AUTH", False) - - print(" MOCK_GOOGLE_AUTH set to false") - config_file = _replace(config_file, "MOCK_GOOGLE_AUTH", False) - - print(" AUTHLIB_INSECURE_TRANSPORT set to true") - config_file = _replace(config_file, "AUTHLIB_INSECURE_TRANSPORT", True) - - print(" SESSION_COOKIE_SECURE set to true") - config_file = _replace(config_file, "SESSION_COOKIE_SECURE", True) - - print(" ENABLE_CSRF_PROTECTION set to true") - config_file = _replace(config_file, "ENABLE_CSRF_PROTECTION", True) - - open(config_file_path, "w+").write(config_file) - - -def inject_other_files_into_fence_config(other_files, config_file_path): - additional_cfgs = _get_all_additional_configs(other_files) - - config_file = open(config_file_path, "r").read() - - for key, value in additional_cfgs.iteritems(): - print(" {} set to {}".format(key, value)) - config_file = _nested_replace(config_file, key, value) - - open(config_file_path, "w+").write(config_file) - - -def _get_all_additional_configs(other_files): - """ - Attempt to parse given list of files and extract configuration variables and values - """ - additional_configs = dict() - for file_path in other_files: - try: - file_ext = file_path.strip().split(".")[-1] - if file_ext == "json": - json_file = open(file_path, "r") - configs = json.load(json_file) - json_file.close() - elif file_ext == "py": - configs = from_pyfile(file_path) - else: - print( - "Cannot load config vars from a file with extention: {}".format( - file_ext - ) - ) - except Exception as exc: - # if there's any issue reading the file, exit - print( - "Error reading {}. Cannot get configuration. Skipping this file. " - "Details: {}".format(other_files, str(exc)) - ) - continue - - if configs: - additional_configs.update(configs) - - return additional_configs - - -def _nested_replace(config_file, key, value, replacement_path=None): - replacement_path = replacement_path or key - try: - for inner_key, inner_value in value.iteritems(): - temp_path = replacement_path - temp_path = temp_path + "/" + inner_key - config_file = _nested_replace( - config_file, inner_key, inner_value, temp_path - ) - except AttributeError: - # not a dict so replace - if value is not None: - config_file = _replace(config_file, replacement_path, value) - - return config_file - - -def _replace(yaml_config, path_to_key, replacement_value, start=0, nested_level=0): - """ - Replace a nested value in a YAML file string with the given value without - losing comments. Uses a regex to do the replacement. - - Args: - yaml_config (str): a string representing a full configuration file - path_to_key (str): nested/path/to/key. The value of this key will be - replaced - replacement_value (str): Replacement value for the key from - path_to_key - """ - nested_path_to_replace = path_to_key.split("/") - - # our regex looks for a specific number of spaces to ensure correct - # level of nesting. It matches to the end of the line - search_string = ( - " " * nested_level + ".*" + nested_path_to_replace[0] + "(')?(\")?:.*\n" - ) - matches = re.search(search_string, yaml_config[start:]) - - # early return if we haven't found anything - if not matches: - return yaml_config - - # if we're on the last item in the path, we need to get the value and - # replace it in the original file - if len(nested_path_to_replace) == 1: - # replace the current key:value with the new replacement value - match_start = start + matches.start(0) + len(" " * nested_level) - match_end = start + matches.end(0) - yaml_config = ( - yaml_config[:match_start] - + "{}: {}\n".format( - nested_path_to_replace[0], - _get_yaml_replacement_value(replacement_value, nested_level), - ) - + yaml_config[match_end:] - ) - - return yaml_config - - # set new start point to past current match and move on to next match - start = matches.end(0) - nested_level += 1 - del nested_path_to_replace[0] - - return _replace( - yaml_config, - "/".join(nested_path_to_replace), - replacement_value, - start, - nested_level, - ) - - -def from_pyfile(filename, silent=False): - """ - Modeled after flask's ability to load in python files: - https://github.com/pallets/flask/blob/master/flask/config.py - - Some alterations were made but logic is essentially the same - """ - filename = os.path.abspath(filename) - d = types.ModuleType("config") - d.__file__ = filename - try: - with open(filename, mode="rb") as config_file: - exec(compile(config_file.read(), filename, "exec"), d.__dict__) - except IOError as e: - print("Unable to load configuration file ({})".format(e.strerror)) - if silent: - return False - raise - return _from_object(d) - - -def _from_object(obj): - configs = {} - for key in dir(obj): - if key.isupper(): - configs[key] = getattr(obj, key) - return configs - - -def _get_yaml_replacement_value(value, nested_level=0): - if isinstance(value, str): - return "'" + value + "'" - elif isinstance(value, bool): - return str(value).lower() - elif isinstance(value, list) or isinstance(value, set): - output = "" - for item in value: - # spaces for nested level then spaces and hyphen for each list item - output += ( - "\n" - + " " * nested_level - + " - " - + _get_yaml_replacement_value(item) - + "" - ) - return output - else: - return value - - -def _get_nested_value(dictionary, nested_path): - """ - Return a value from a dictionary given a path-like nesting of keys. - - Will default to an empty string if value cannot be found. - - Args: - dictionary (dict): a dictionary - nested_path (str): nested/path/to/key - - Returns: - ?: Value from dict - """ - replacement_value_path = nested_path.split("/") - replacement_value = copy.deepcopy(dictionary) - - for item in replacement_value_path: - replacement_value = replacement_value.get(item, {}) - - if replacement_value == {}: - replacement_value = "" - - return replacement_value - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "-i", - "--creds_file_to_inject", - default="creds.json", - help="creds file to inject into the configuration yaml", - ) - parser.add_argument( - "--other_files_to_inject", - nargs="+", - help="fence_credentials.json, local_settings.py, fence_settings.py file(s) to " - "inject into the configuration yaml", - ) - parser.add_argument( - "-c", "--config_file", default="config.yaml", help="configuration yaml" - ) - args = parser.parse_args() - - inject_creds_into_fence_config(args.creds_file_to_inject, args.config_file) - set_prod_defaults(args.config_file) - - if args.other_files_to_inject: - inject_other_files_into_fence_config( - args.other_files_to_inject, args.config_file - ) diff --git a/helm/indexd/indexd-secret/local_settings.py b/helm/indexd/indexd-settings/local_settings.py similarity index 77% rename from helm/indexd/indexd-secret/local_settings.py rename to helm/indexd/indexd-settings/local_settings.py index 0b1cd138..cc30e482 100644 --- a/helm/indexd/indexd-secret/local_settings.py +++ b/helm/indexd/indexd-settings/local_settings.py @@ -1,25 +1,26 @@ from indexd.index.drivers.alchemy import SQLAlchemyIndexDriver from indexd.alias.drivers.alchemy import SQLAlchemyAliasDriver from indexd.auth.drivers.alchemy import SQLAlchemyAuthDriver -import config_helper + + from os import environ import json APP_NAME = "indexd" -def load_json(file_name): - return config_helper.load_json(file_name, APP_NAME) +usr = environ.get("PGUSER", "indexd") +db = environ.get("PGDB", "indexd") +psw = environ.get("PGPASSWORD") +pghost = environ.get("PGHOST") +pgport = environ.get("PGPORT", 5432) +# TODO: FIX THIS TO READ FROM ENV VARS +index_config = { + "DEFAULT_PREFIX": environ.get("DEFAULT_PREFIX", "testprefix"), + "PREPEND_PREFIX": environ.get("PREPEND_PREFIX", True), +} -conf_data = load_json("creds.json") - -usr = conf_data.get("db_username", "{{db_username}}") -db = conf_data.get("db_database", "{{db_database}}") -psw = conf_data.get("db_password", "{{db_password}}") -pghost = conf_data.get("db_host", "{{db_host}}") -pgport = 5432 -index_config = conf_data.get("index_config") CONFIG = {} CONFIG["JSONIFY_PRETTYPRINT_REGULAR"] = False diff --git a/helm/indexd/templates/db-init.yaml b/helm/indexd/templates/db-init.yaml index 7dc1039e..f6160079 100644 --- a/helm/indexd/templates/db-init.yaml +++ b/helm/indexd/templates/db-init.yaml @@ -1,3 +1,7 @@ -{{- include "common.db-setup-job" . }} +{{ include "common.db-setup-job" . }} --- -{{ include "common.db-secret" . }} \ No newline at end of file +{{ include "common.db-secret" . }} +--- +{{- if .Values.db_restore }} +{{ include "gen3-test-data-job.create-test-dbs" . }} +{{- end -}} \ No newline at end of file diff --git a/helm/indexd/templates/deployment.yaml b/helm/indexd/templates/deployment.yaml index 6207db02..892d7f8c 100644 --- a/helm/indexd/templates/deployment.yaml +++ b/helm/indexd/templates/deployment.yaml @@ -32,12 +32,36 @@ spec: securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: - - name: {{ .Chart.Name }} + - name: indexd securityContext: {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} env: + - name: PGHOST + valueFrom: + secretKeyRef: + name: indexd-dbcreds + key: host + optional: false + - name: PGUSER + valueFrom: + secretKeyRef: + name: indexd-dbcreds + key: username + optional: false + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: indexd-dbcreds + key: password + optional: false + - name: PGDB + valueFrom: + secretKeyRef: + name: indexd-dbcreds + key: database + optional: false {{- toYaml .Values.env | nindent 12 }} volumeMounts: {{- toYaml .Values.volumeMounts | nindent 12 }} @@ -92,7 +116,30 @@ spec: volumeMounts: {{- toYaml .Values.initVolumeMounts | nindent 12 }} env: - {{ toYaml .Values.initEnv | nindent 12 }} + - name: PGHOST + valueFrom: + secretKeyRef: + name: indexd-dbcreds + key: host + optional: false + - name: PGUSER + valueFrom: + secretKeyRef: + name: indexd-dbcreds + key: username + optional: false + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: indexd-dbcreds + key: password + optional: false + - name: PGDB + valueFrom: + secretKeyRef: + name: indexd-dbcreds + key: database + optional: false {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/helm/indexd/templates/indexd-secret.yaml b/helm/indexd/templates/indexd-secret.yaml index b243edbd..c27b415e 100644 --- a/helm/indexd/templates/indexd-secret.yaml +++ b/helm/indexd/templates/indexd-secret.yaml @@ -1,21 +1,15 @@ apiVersion: v1 kind: Secret metadata: - name: indexd-secret - annotations: - "helm.sh/hook": "pre-install,pre-upgrade" - "helm.sh/hook-weight": "-10" + name: indexd-settings type: Opaque data: -{{ (.Files.Glob "indexd-secret/*").AsSecrets | indent 2 }} +{{ (.Files.Glob "indexd-settings/*").AsSecrets | indent 2 }} --- apiVersion: v1 kind: Secret metadata: name: indexd-creds - annotations: - "helm.sh/hook": "pre-install,pre-upgrade" - "helm.sh/hook-weight": "-10" type: Opaque stringData: creds.json: |- @@ -35,9 +29,6 @@ apiVersion: v1 kind: Secret metadata: name: indexd-service-creds - annotations: - "helm.sh/hook": "pre-install,pre-upgrade" - "helm.sh/hook-weight": "-10" type: Opaque stringData: fence: {{ include "indexd-fence-creds" . | quote }} diff --git a/helm/indexd/templates/pre-install.yaml b/helm/indexd/templates/pre-install.yaml index c87f4e9f..5551f879 100644 --- a/helm/indexd/templates/pre-install.yaml +++ b/helm/indexd/templates/pre-install.yaml @@ -9,8 +9,6 @@ metadata: # creds.json # name: indexd-userdb - annotations: - "helm.sh/hook": "pre-install,pre-upgrade" spec: backoffLimit: 0 template: @@ -22,13 +20,7 @@ spec: volumes: - name: config-volume secret: - secretName: "indexd-secret" - - name: "sheepdog-creds-volume" - secret: - secretName: "sheepdog-creds" - - name: "indexd-creds-volume" - secret: - secretName: "indexd-creds" + secretName: "indexd-settings" containers: - name: indexd image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" @@ -37,14 +29,6 @@ spec: readOnly: true mountPath: "/var/www/indexd/local_settings.py" subPath: "local_settings.py" - - name: "sheepdog-creds-volume" - readOnly: true - mountPath: "/var/www/indexd/sheepdog_creds.json" - subPath: creds.json - - name: "indexd-creds-volume" - readOnly: true - mountPath: "/var/www/indexd/creds.json" - subPath: creds.json imagePullPolicy: Always command: ["/bin/bash" ] args: @@ -70,5 +54,4 @@ spec: for user in "${!user_db[@]}"; do python /indexd/bin/index_admin.py create --username "$user" --password "${user_db[$user]}" done - echo "Exit code: $?" restartPolicy: Never \ No newline at end of file diff --git a/helm/indexd/values.yaml b/helm/indexd/values.yaml index b50077d2..066f84f5 100644 --- a/helm/indexd/values.yaml +++ b/helm/indexd/values.yaml @@ -3,23 +3,26 @@ # Declare variables to be passed into your templates. global: + dev: true # Default values are for postgres deployed as a helm chart postgres: - host: postgres-postgresql.postgres.svc.cluster.local master: + host: username: postgres password: - port: 5432 + port: "5432" db_create: true postgres: - # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you + # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you database: indexd username: indexd host: - port: 5432 + port: "5432" # If left empty password will be auto-generated password: + # If db_restore is set to true then the database will have fake data/tables dumped into it. + db_restore: false replicaCount: 1 @@ -89,7 +92,7 @@ affinity: {} volumes: - name: config-volume secret: - secretName: "indexd-secret" + secretName: "indexd-settings" - name: creds-volume secret: secretName: "indexd-creds" @@ -100,21 +103,13 @@ volumeMounts: readOnly: true mountPath: "/var/www/indexd/local_settings.py" subPath: "local_settings.py" -- name: "creds-volume" - readOnly: true - mountPath: "/var/www/indexd/creds.json" - subPath: creds.json -- name: "config-volume" - readOnly: true - mountPath: "/var/www/indexd/config_helper.py" - subPath: config_helper.py env: - name: "GEN3_DEBUG" - value: "false" + value: "False" secrets: userdb: fence: gdcapi: - gateway: \ No newline at end of file + gateway: diff --git a/helm/manifestservice/Chart.yaml b/helm/manifestservice/Chart.yaml index 7ae2d9cf..f2f06351 100644 --- a/helm/manifestservice/Chart.yaml +++ b/helm/manifestservice/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/manifestservice/README.md b/helm/manifestservice/README.md new file mode 100644 index 00000000..232a403e --- /dev/null +++ b/helm/manifestservice/README.md @@ -0,0 +1,58 @@ +# manifestservice + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for Kubernetes + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key | string | `"app"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator | string | `"In"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0] | string | `"manifestservice"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey | string | `"kubernetes.io/hostname"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight | int | `100` | | +| automountServiceAccountToken | bool | `false` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| env[0].name | string | `"REQUESTS_CA_BUNDLE"` | | +| env[0].value | string | `"/etc/ssl/certs/ca-certificates.crt"` | | +| env[1].name | string | `"MANIFEST_SERVICE_CONFIG_PATH"` | | +| env[1].value | string | `"/var/gen3/config/config.json"` | | +| env[2].name | string | `"GEN3_DEBUG"` | | +| env[2].value | string | `"False"` | | +| labels.public | string | `"yes"` | | +| labels.s3 | string | `"yes"` | | +| labels.userhelper | string | `"yes"` | | +| manifestserviceG3auto.awsaccesskey | string | `""` | | +| manifestserviceG3auto.awssecretkey | string | `""` | | +| manifestserviceG3auto.bucketName | string | `"testbucket"` | | +| manifestserviceG3auto.hostname | string | `"testinstall"` | | +| manifestserviceG3auto.prefix | string | `"test"` | | +| resources.limits.cpu | float | `1` | | +| resources.limits.memory | string | `"1024Mi"` | | +| resources.requests.cpu | float | `0.5` | | +| resources.requests.memory | string | `"512Mi"` | | +| revisionHistoryLimit | int | `2` | | +| selectorLabels.app | string | `"manifestservice"` | | +| selectorLabels.release | string | `"production"` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| strategy.rollingUpdate.maxSurge | int | `1` | | +| strategy.rollingUpdate.maxUnavailable | int | `0` | | +| strategy.type | string | `"RollingUpdate"` | | +| terminationGracePeriodSeconds | int | `50` | | +| volumeMounts[0].mountPath | string | `"/var/gen3/config/"` | | +| volumeMounts[0].name | string | `"config-volume"` | | +| volumeMounts[0].readOnly | bool | `true` | | +| volumes[0].name | string | `"config-volume"` | | +| volumes[0].secret.secretName | string | `"manifestservice-g3auto"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/manifestservice/values.yaml b/helm/manifestservice/values.yaml index 333b82a7..bcaab814 100644 --- a/helm/manifestservice/values.yaml +++ b/helm/manifestservice/values.yaml @@ -24,11 +24,6 @@ autoscaling: minReplicas: 1 maxReplicas: 100 targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - - - - strategy: type: RollingUpdate @@ -40,7 +35,6 @@ labels: s3: "yes" public: "yes" userhelper: "yes" - #GEN3_DATE_LABEL affinity: podAntiAffinity: @@ -93,4 +87,3 @@ manifestserviceG3auto: prefix: test awsaccesskey: "" awssecretkey: "" - diff --git a/helm/metadata/Chart.lock b/helm/metadata/Chart.lock index ef02940e..f0c5fb37 100644 --- a/helm/metadata/Chart.lock +++ b/helm/metadata/Chart.lock @@ -1,6 +1,9 @@ dependencies: - name: common repository: file://../common - version: 0.0.1 -digest: sha256:9447ea9a4ddee41221215f9d511d904829f457523bc78ddaa817c161e934f27f -generated: "2022-10-20T21:34:40.594362-05:00" + version: 0.1.0 +- name: gen3-test-data-job + repository: file://../gen3-test-data-job + version: 0.1.0 +digest: sha256:69c9702ec96903c40a92569ca312d854a7dc2dc85be0fdbf75408a54df8beaf6 +generated: "2022-12-07T10:38:58.724924+01:00" diff --git a/helm/metadata/Chart.yaml b/helm/metadata/Chart.yaml index 52ddd4a8..509774e0 100644 --- a/helm/metadata/Chart.yaml +++ b/helm/metadata/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -24,7 +24,11 @@ version: 0.0.1 appVersion: "2022.10" dependencies: -- name: common - version: 0.0.1 - repository: file://../common - condition: db_creation.enabled \ No newline at end of file + - name: common + version: 0.1.0 + repository: file://../common + condition: db_creation.enabled + - name: gen3-test-data-job + version: 0.1.0 + repository: file://../gen3-test-data-job + condition: db_restore.enabled diff --git a/helm/metadata/README.md b/helm/metadata/README.md new file mode 100644 index 00000000..2a409b86 --- /dev/null +++ b/helm/metadata/README.md @@ -0,0 +1,109 @@ +# metadata + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 Metadata Service + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../common | common | 0.1.0 | +| file://../gen3-test-data-job | gen3-test-data-job | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key | string | `"app"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator | string | `"In"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0] | string | `"metadata"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey | string | `"kubernetes.io/hostname"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight | int | `100` | | +| aggMdsNamespace | string | `nil` | | +| args[0] | string | `"-c"` | | +| args[1] | string | `"/env/bin/alembic upgrade head\n"` | | +| automountServiceAccountToken | bool | `false` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| command[0] | string | `"/bin/sh"` | | +| containerPort[0].containerPort | int | `80` | | +| dataDog.enabled | bool | `false` | | +| dataDog.env | string | `"dev"` | | +| debug | bool | `false` | | +| esEndpoint | string | `"esproxy-service:9200"` | | +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/cdis/metadata-service"` | | +| image.tag | string | `"master"` | | +| initContainerName | string | `"metadata-db-migrate"` | | +| initResources.limits.cpu | float | `0.8` | | +| initResources.limits.memory | string | `"512Mi"` | | +| initVolumeMounts[0].mountPath | string | `"/src/.env"` | | +| initVolumeMounts[0].name | string | `"config-volume-g3auto"` | | +| initVolumeMounts[0].readOnly | bool | `true` | | +| initVolumeMounts[0].subPath | string | `"metadata.env"` | | +| livenessProbe.httpGet.path | string | `"/_status"` | | +| livenessProbe.httpGet.port | int | `80` | | +| livenessProbe.initialDelaySeconds | int | `30` | | +| livenessProbe.periodSeconds | int | `60` | | +| livenessProbe.timeoutSeconds | int | `30` | | +| postgres.database | string | `"metadata"` | | +| postgres.db_create | string | `nil` | | +| postgres.db_restore | bool | `false` | | +| postgres.host | string | `nil` | | +| postgres.password | string | `nil` | | +| postgres.port | string | `"5432"` | | +| postgres.username | string | `"metadata"` | | +| readinessProbe.httpGet.path | string | `"/_status"` | | +| readinessProbe.httpGet.port | int | `80` | | +| releaseLabel | string | `"production"` | | +| replicaCount | int | `1` | | +| resources | string | `nil` | | +| revisionHistoryLimit | int | `2` | | +| service.port[0].name | string | `"http"` | | +| service.port[0].port | int | `80` | | +| service.port[0].protocol | string | `"TCP"` | | +| service.port[0].targetPort | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAnnotations."getambassador.io/config" | string | `"---\napiVersion: ambassador/v1\nambassador_id: \"gen3\"\nkind: Mapping\nname: metadata_mapping\nprefix: /index/\nservice: http://metadata-service:80\n"` | | +| strategy.rollingUpdate.maxSurge | int | `1` | | +| strategy.rollingUpdate.maxUnavailable | int | `0` | | +| strategy.type | string | `"RollingUpdate"` | | +| useAggMds | string | `nil` | | +| volumeMounts[0].mountPath | string | `"/src/.env"` | | +| volumeMounts[0].name | string | `"config-volume-g3auto"` | | +| volumeMounts[0].readOnly | bool | `true` | | +| volumeMounts[0].subPath | string | `"metadata.env"` | | +| volumeMounts[1].mountPath | string | `"/aggregate_config.json"` | | +| volumeMounts[1].name | string | `"config-volume"` | | +| volumeMounts[1].readOnly | bool | `true` | | +| volumeMounts[1].subPath | string | `"aggregate_config.json"` | | +| volumeMounts[2].mountPath | string | `"/metadata.json"` | | +| volumeMounts[2].name | string | `"config-manifest"` | | +| volumeMounts[2].readOnly | bool | `true` | | +| volumeMounts[2].subPath | string | `"json"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/metadata/templates/db-init.yaml b/helm/metadata/templates/db-init.yaml index e53cb144..0bcbb894 100644 --- a/helm/metadata/templates/db-init.yaml +++ b/helm/metadata/templates/db-init.yaml @@ -1,3 +1,7 @@ {{- include "common.db-setup-job" . }} --- -{{- include "common.db-secret" . }} +{{ include "common.db-secret" . }} +--- +{{- if .Values.db_restore }} +{{ include "gen3-test-data-job.create-test-dbs" . }} +{{- end -}} \ No newline at end of file diff --git a/helm/metadata/templates/deployment.yaml b/helm/metadata/templates/deployment.yaml index 869a6d27..e61cd755 100644 --- a/helm/metadata/templates/deployment.yaml +++ b/helm/metadata/templates/deployment.yaml @@ -54,6 +54,30 @@ spec: value: "False" - name: GEN3_ES_ENDPOINT value: {{ .Values.esEndpoint }} + - name: DB_HOST + valueFrom: + secretKeyRef: + name: metadata-dbcreds + key: host + optional: false + - name: DB_USER + valueFrom: + secretKeyRef: + name: metadata-dbcreds + key: username + optional: false + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: metadata-dbcreds + key: password + optional: false + - name: DB_DATABASE + valueFrom: + secretKeyRef: + name: metadata-dbcreds + key: database + optional: false {{- with .Values.useAggMds }} - name: USE_AGG_MDS value: {{ . }} @@ -88,6 +112,31 @@ spec: image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} {{- with .Values.initVolumeMounts }} + env: + - name: DB_HOST + valueFrom: + secretKeyRef: + name: metadata-dbcreds + key: host + optional: false + - name: DB_USER + valueFrom: + secretKeyRef: + name: metadata-dbcreds + key: username + optional: false + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: metadata-dbcreds + key: password + optional: false + - name: DB_DATABASE + valueFrom: + secretKeyRef: + name: metadata-dbcreds + key: database + optional: false volumeMounts: {{- toYaml . | nindent 10 }} {{- end }} diff --git a/helm/metadata/values.yaml b/helm/metadata/values.yaml index 09169334..4504102b 100644 --- a/helm/metadata/values.yaml +++ b/helm/metadata/values.yaml @@ -2,24 +2,40 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. global: - # Default values are for postgres deployed as a helm chart + dev: true postgres: - host: postgres-postgresql.postgres.svc.cluster.local + db_create: true master: + host: username: postgres - password: - port: 5432 + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false + -db_create: true postgres: - database: - # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you - database: metadata - username: metadata - host: - port: 5432 - # If left empty password will be auto-generated - password: + db_create: + database: metadata + username: metadata + host: + port: "5432" + # If left empty password will be auto-generated + password: + # If db_restore is set to true then the database will have fake data/tables dumped into it. + db_restore: false # Deployment @@ -45,7 +61,7 @@ dataDog: enabled: false env: dev -affinity: +affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 @@ -131,7 +147,7 @@ args: - | /env/bin/alembic upgrade head -#Service and Pod +# Service and Pod serviceAnnotations: getambassador.io/config: | --- @@ -147,5 +163,5 @@ service: port: - protocol: TCP port: 80 - targetPort: 80 + targetPort: 80 name: http diff --git a/helm/peregrine/Chart.lock b/helm/peregrine/Chart.lock index ee2e57ed..fb63959e 100644 --- a/helm/peregrine/Chart.lock +++ b/helm/peregrine/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: common repository: file://../common - version: 0.0.1 -digest: sha256:9447ea9a4ddee41221215f9d511d904829f457523bc78ddaa817c161e934f27f -generated: "2022-10-20T21:12:56.035146-05:00" + version: 0.1.0 +digest: sha256:8e96d9e4e8522837b307a10e8683e8b21330a984d519e9ed2867ea759da7207e +generated: "2022-12-07T10:38:58.714301+01:00" diff --git a/helm/peregrine/Chart.yaml b/helm/peregrine/Chart.yaml index 6a035831..78e88c8b 100644 --- a/helm/peregrine/Chart.yaml +++ b/helm/peregrine/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -26,6 +26,6 @@ appVersion: "2022.10" dependencies: - name: common - version: 0.0.1 + version: 0.1.0 repository: file://../common - condition: db_creation.enabled \ No newline at end of file + condition: db_creation.enabled diff --git a/helm/peregrine/README.md b/helm/peregrine/README.md new file mode 100644 index 00000000..f63118dc --- /dev/null +++ b/helm/peregrine/README.md @@ -0,0 +1,74 @@ +# peregrine + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 Peregrine service + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../common | common | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| env | string | `nil` | | +| fullnameOverride | string | `""` | | +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"quay.io/cdis/peregrine"` | | +| image.tag | string | `""` | | +| imagePullSecrets | list | `[]` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | | +| podSecurityContext | object | `{}` | | +| postgres.database | string | `"peregrine"` | | +| postgres.db_create | string | `nil` | | +| postgres.host | string | `nil` | | +| postgres.password | string | `nil` | | +| postgres.port | string | `"5432"` | | +| postgres.username | string | `"peregrine"` | | +| replicaCount | int | `1` | | +| resources | object | `{}` | | +| securityContext | object | `{}` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| tolerations | list | `[]` | | +| volumeMounts | string | `nil` | | +| volumes[0].emptyDir | object | `{}` | | +| volumes[0].name | string | `"shared-data"` | | +| volumes[1].name | string | `"config-volume"` | | +| volumes[1].secret.secretName | string | `"peregrine-secret"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/peregrine/templates/db-init.yaml b/helm/peregrine/templates/db-init.yaml index e53cb144..a197f530 100644 --- a/helm/peregrine/templates/db-init.yaml +++ b/helm/peregrine/templates/db-init.yaml @@ -1,3 +1,3 @@ -{{- include "common.db-setup-job" . }} +{{ include "common.db-setup-job" . }} --- -{{- include "common.db-secret" . }} +{{ include "common.db-secret" . }} diff --git a/helm/peregrine/values.yaml b/helm/peregrine/values.yaml index da48976a..09bce443 100644 --- a/helm/peregrine/values.yaml +++ b/helm/peregrine/values.yaml @@ -1,24 +1,39 @@ # Default values for peregrine. # This is a YAML-formatted file. global: + dev: true postgres: + db_create: true master: - host: postgres-postgresql.postgres.svc.cluster.local + host: username: postgres - port: 5432 - # If password is left empty the lookup function will look for postgres master password - password: + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false -db_create: true postgres: + db_create: host: - # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you + # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you database: peregrine username: peregrine - port: 5432 + port: "5432" # If left empty password will be auto-generated password: - + replicaCount: 1 image: @@ -86,8 +101,6 @@ affinity: {} env: - - volumes: - name: shared-data emptyDir: {} @@ -96,5 +109,3 @@ volumes: secretName: "peregrine-secret" volumeMounts: - - diff --git a/helm/pidgin/Chart.lock b/helm/pidgin/Chart.lock index 274a5f2b..7dac1bf2 100644 --- a/helm/pidgin/Chart.lock +++ b/helm/pidgin/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: common repository: file://../common - version: 0.0.1 -digest: sha256:9447ea9a4ddee41221215f9d511d904829f457523bc78ddaa817c161e934f27f -generated: "2022-10-20T21:34:43.297641-05:00" + version: 0.1.0 +digest: sha256:8e96d9e4e8522837b307a10e8683e8b21330a984d519e9ed2867ea759da7207e +generated: "2022-12-07T10:38:58.75975+01:00" diff --git a/helm/pidgin/Chart.yaml b/helm/pidgin/Chart.yaml index 53cfa799..02c89819 100644 --- a/helm/pidgin/Chart.yaml +++ b/helm/pidgin/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -26,6 +26,6 @@ appVersion: "2022.10" dependencies: - name: common - version: 0.0.1 + version: 0.1.0 repository: file://../common - condition: db_creation.enabled \ No newline at end of file + condition: db_creation.enabled diff --git a/helm/pidgin/README.md b/helm/pidgin/README.md new file mode 100644 index 00000000..3f9a11cb --- /dev/null +++ b/helm/pidgin/README.md @@ -0,0 +1,91 @@ +# pidgin + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 Pidgin Service + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../common | common | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key | string | `"app"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator | string | `"In"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0] | string | `"pidgin"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey | string | `"kubernetes.io/hostname"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight | int | `100` | | +| automountServiceAccountToken | bool | `false` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| containerPort[0].containerPort | int | `80` | | +| containerPort[1].containerPort | int | `443` | | +| dataDog.enabled | bool | `false` | | +| dataDog.env | string | `"dev"` | | +| ddEnv | string | `nil` | | +| ddLogsInjection | string | `nil` | | +| ddProfilingEnabled | string | `nil` | | +| ddService | string | `nil` | | +| ddTraceAgentHostname | string | `nil` | | +| ddTraceEnabled | string | `nil` | | +| ddTraceSampleRate | string | `nil` | | +| ddVersion | string | `nil` | | +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/cdis/pidgin"` | | +| image.tag | string | `""` | | +| livenessProbe.httpGet.path | string | `"/_status"` | | +| livenessProbe.httpGet.port | int | `80` | | +| livenessProbe.initialDelaySeconds | int | `30` | | +| livenessProbe.periodSeconds | int | `60` | | +| livenessProbe.timeoutSeconds | int | `30` | | +| postgres.database | string | `"pidgin"` | | +| postgres.db_create | string | `nil` | | +| postgres.password | string | `nil` | | +| postgres.port | string | `"5432"` | | +| postgres.username | string | `"pidgin"` | | +| readinessProbe.httpGet.path | string | `"/_status"` | | +| readinessProbe.httpGet.port | int | `80` | | +| replicaCount | int | `1` | | +| resources | string | `nil` | | +| revisionHistoryLimit | int | `2` | | +| service.port[0].name | string | `"http"` | | +| service.port[0].port | int | `80` | | +| service.port[0].protocol | string | `"TCP"` | | +| service.port[0].targetPort | int | `80` | | +| service.port[1].name | string | `"https"` | | +| service.port[1].port | int | `443` | | +| service.port[1].protocol | string | `"TCP"` | | +| service.port[1].targetPort | int | `443` | | +| service.type | string | `"ClusterIP"` | | +| strategy.rollingUpdate.maxSurge | int | `1` | | +| strategy.rollingUpdate.maxUnavailable | int | `0` | | +| strategy.type | string | `"RollingUpdate"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/pidgin/templates/db-init.yaml b/helm/pidgin/templates/db-init.yaml index e53cb144..a197f530 100644 --- a/helm/pidgin/templates/db-init.yaml +++ b/helm/pidgin/templates/db-init.yaml @@ -1,3 +1,3 @@ -{{- include "common.db-setup-job" . }} +{{ include "common.db-setup-job" . }} --- -{{- include "common.db-secret" . }} +{{ include "common.db-secret" . }} diff --git a/helm/pidgin/values.yaml b/helm/pidgin/values.yaml index 9144a563..3c145733 100644 --- a/helm/pidgin/values.yaml +++ b/helm/pidgin/values.yaml @@ -2,22 +2,37 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. global: - # Default values are for postgres deployed as a helm chart + dev: true postgres: - host: postgres-postgresql.postgres.svc.cluster.local + db_create: true master: + host: username: postgres - password: - port: 5432 + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false -db_create: true postgres: - # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you + db_create: + # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you database: pidgin username: pidgin - port: 5432 + port: "5432" # If left empty password will be auto-generated - password: + password: # Deployment @@ -41,7 +56,7 @@ dataDog: enabled: false env: dev -affinity: +affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 @@ -63,15 +78,15 @@ image: tag: "" # Environment Variables -#Placeholders for datadog -ddTraceEnabled: -ddEnv: +# Placeholders for datadog +ddTraceEnabled: +ddEnv: ddService: ddVersion: ddLogsInjection: ddProfilingEnabled: -ddTraceSampleRate: -ddTraceAgentHostname: +ddTraceSampleRate: +ddTraceAgentHostname: livenessProbe: httpGet: @@ -94,16 +109,15 @@ resources: # cpu: 1 # memory: 512Mi - -#Service and Pod +# Service and Pod service: type: ClusterIP port: - protocol: TCP port: 80 - targetPort: 80 + targetPort: 80 name: http - - protocol: TCP - port: 443 + - protocol: TCP + port: 443 targetPort: 443 - name: https \ No newline at end of file + name: https diff --git a/helm/portal/Chart.yaml b/helm/portal/Chart.yaml index 36633f3a..c2622b7a 100644 --- a/helm/portal/Chart.yaml +++ b/helm/portal/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/portal/README.md b/helm/portal/README.md new file mode 100644 index 00000000..a5c7daa8 --- /dev/null +++ b/helm/portal/README.md @@ -0,0 +1,52 @@ +# portal + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 data-portal + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key | string | `"app"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator | string | `"In"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0] | string | `"portal"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey | string | `"kubernetes.io/hostname"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight | int | `100` | | +| automountServiceAccountToken | bool | `false` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"quay.io/cdis/data-portal-prebuilt"` | | +| image.tag | string | `"brh.data-commons.org-feat-develop"` | | +| imagePullSecrets | list | `[]` | | +| labels.app | string | `"portal"` | | +| labels.public | string | `"yes"` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | | +| podSecurityContext | object | `{}` | | +| portalApp | string | `"dev"` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | float | `2` | | +| resources.limits.memory | string | `"4096Mi"` | | +| resources.requests.cpu | float | `0.6` | | +| resources.requests.memory | string | `"512Mi"` | | +| revisionHistoryLimit | int | `2` | | +| securityContext | object | `{}` | | +| selectorLabels.app | string | `"portal"` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| strategy.rollingUpdate.maxSurge | int | `2` | | +| strategy.rollingUpdate.maxUnavailable | string | `"25%"` | | +| strategy.type | string | `"RollingUpdate"` | | +| tolerations | list | `[]` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/portal/defaults/gitops.json b/helm/portal/defaults/gitops.json index 311847da..ffb1bb01 100644 --- a/helm/portal/defaults/gitops.json +++ b/helm/portal/defaults/gitops.json @@ -1,2 +1,258 @@ -{} +{ + "graphql": { + "boardCounts": [ + { + "graphql": "_case_count", + "name": "Case", + "plural": "Cases" + }, + { + "graphql": "_experiment_count", + "name": "Experiment", + "plural": "Experiments" + }, + { + "graphql": "_aliquot_count", + "name": "Aliquot", + "plural": "Aliquots" + } + ], + "chartCounts": [ + { + "graphql": "_case_count", + "name": "Case" + }, + { + "graphql": "_experiment_count", + "name": "Experiment" + }, + { + "graphql": "_aliquot_count", + "name": "Aliquot" + } + ], + "projectDetails": "boardCounts" + }, + "components": { + "appName": "Generic Data Commons Portal", + "index": { + "introduction": { + "heading": "Data Commons", + "text": "The Generic Data Commons supports the management, analysis and sharing of data for the research community.", + "link": "/submission" + }, + "buttons": [ + { + "name": "Define Data Field", + "icon": "data-field-define", + "body": "The Generic Data Commons define the data in a general way. Please study the dictionary before you start browsing.", + "link": "/DD", + "label": "Learn more" + }, + { + "name": "Explore Data", + "icon": "data-explore", + "body": "The Exploration Page gives you insights and a clear overview under selected factors.", + "link": "/explorer", + "label": "Explore data" + }, + { + "name": "Access Data", + "icon": "data-access", + "body": "Use our selected tool to filter out the data you need.", + "link": "/query", + "label": "Query data" + }, + { + "name": "Submit Data", + "icon": "data-submit", + "body": "Submit Data based on the dictionary.", + "link": "/submission", + "label": "Submit data" + } + ] + }, + "navigation": { + "title": "Generic Data Commons", + "items": [ + { + "icon": "dictionary", + "link": "/DD", + "color": "#a2a2a2", + "name": "Dictionary" + }, + { + "icon": "exploration", + "link": "/explorer", + "color": "#a2a2a2", + "name": "Exploration" + }, + { + "icon": "query", + "link": "/query", + "color": "#a2a2a2", + "name": "Query" + }, + { + "icon": "workspace", + "link": "/workspace", + "color": "#a2a2a2", + "name": "Workspace" + }, + { + "icon": "profile", + "link": "/identity", + "color": "#a2a2a2", + "name": "Profile" + } + ] + }, + "topBar": { + "items": [ + { + "icon": "upload", + "link": "/submission", + "name": "Submit Data" + }, + { + "link": "https://gen3.org/resources/user", + "name": "Documentation" + } + ] + }, + "login": { + "title": "Generic Data Commons", + "subTitle": "Explore, Analyze, and Share Data", + "text": "This website supports the management, analysis and sharing of human disease data for the research community and aims to advance basic understanding of the genetic basis of complex traits and accelerate discovery and development of therapies, diagnostic tests, and other technologies for diseases like cancer.", + "contact": "If you have any questions about access or the registration process, please contact ", + "email": "support@datacommons.io" + }, + "certs": {}, + "footerLogos": [ + { + "src": "/src/img/gen3.png", + "href": "https://ctds.uchicago.edu/gen3", + "alt": "Gen3 Data Commons" + }, + { + "src": "/src/img/createdby.png", + "href": "https://ctds.uchicago.edu/", + "alt": "Center for Translational Data Science at the University of Chicago" + } + ] + }, + "requiredCerts": [], + "featureFlags": { + "explorer": true, + "noIndex": true, + "analysis": false, + "discovery": false, + "discoveryUseAggMDS": false, + "studyRegistration": false + }, + "dataExplorerConfig": { + "charts": { + "project_id": { + "chartType": "count", + "title": "Projects" + }, + "case_id": { + "chartType": "count", + "title": "Cases" + }, + "gender": { + "chartType": "pie", + "title": "Gender" + }, + "race": { + "chartType": "bar", + "title": "Race" + } + }, + "filters": { + "tabs": [ + { + "title": "Case", + "fields":[ + "project_id", + "gender", + "race", + "ethnicity" + ] + } + ] + }, + "table": { + "enabled": false + }, + "dropdowns": {}, + "buttons": [], + "guppyConfig": { + "dataType": "case", + "nodeCountTitle": "Cases", + "fieldMapping": [ + { "field": "disease_type", "name": "Disease type" }, + { "field": "primary_site", "name": "Site where samples were collected"} + ], + "manifestMapping": { + "resourceIndexType": "file", + "resourceIdField": "object_id", + "referenceIdFieldInResourceIndex": "case_id", + "referenceIdFieldInDataIndex": "node_id" + }, + "accessibleFieldCheckList": ["case_id"], + "accessibleValidationField": "case_id" + } + }, + "fileExplorerConfig": { + "charts": { + "data_type": { + "chartType": "stackedBar", + "title": "File Type" + }, + "data_format": { + "chartType": "stackedBar", + "title": "File Format" + } + }, + "filters": { + "tabs": [ + { + "title": "File", + "fields": [ + "project_id", + "data_type", + "data_format" + ] + } + ] + }, + "table": { + "enabled": true, + "fields": [ + "project_id", + "file_name", + "file_size", + "object_id" + ] + }, + "dropdowns": {}, + "guppyConfig": { + "dataType": "file", + "fieldMapping": [ + { "field": "object_id", "name": "GUID" } + ], + "nodeCountTitle": "Files", + "manifestMapping": { + "resourceIndexType": "case", + "resourceIdField": "case_id", + "referenceIdFieldInResourceIndex": "object_id", + "referenceIdFieldInDataIndex": "object_id" + }, + "accessibleFieldCheckList": ["case_id"], + "accessibleValidationField": "case_id", + "downloadAccessor": "object_id" + } + } + } diff --git a/helm/portal/portal.yaml b/helm/portal/portal.yaml deleted file mode 100644 index c89d0de2..00000000 --- a/helm/portal/portal.yaml +++ /dev/null @@ -1,274 +0,0 @@ ---- -# Source: portal/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: portal - labels: - helm.sh/chart: portal-0.1.0 - app.kubernetes.io/name: portal - app.kubernetes.io/instance: portal - app.kubernetes.io/version: "1.16.0" - app.kubernetes.io/managed-by: Helm ---- -# Source: portal/templates/secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: portal-config -data: - gitops-createdby.png: | - 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 - gitops-favicon.ico: | - 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 - gitops-logo.png: | - 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 - gitops.css: | - LyogZ2l0b3BzIGRlZmF1bHQgY3NzICovCg== - gitops.json: | - e30KCg== ---- -# Source: portal/templates/secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: portal-sponsor-config ---- -# Source: portal/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: portal - labels: - helm.sh/chart: portal-0.1.0 - app.kubernetes.io/name: portal - app.kubernetes.io/instance: portal - app.kubernetes.io/version: "1.16.0" - app.kubernetes.io/managed-by: Helm -spec: - type: ClusterIP - ports: - - port: 80 - targetPort: http - protocol: TCP - name: http - selector: - app.kubernetes.io/name: portal - app.kubernetes.io/instance: portal ---- -# Source: portal/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: portal-deployment -spec: - selector: - matchLabels: - app.kubernetes.io/name: portal - app.kubernetes.io/instance: portal - revisionHistoryLimit: 2 - strategy: - rollingUpdate: - maxSurge: 2 - maxUnavailable: 25% - type: RollingUpdate - template: - metadata: - labels: - helm.sh/chart: portal-0.1.0 - app.kubernetes.io/name: portal - app.kubernetes.io/instance: portal - app.kubernetes.io/version: "1.16.0" - app.kubernetes.io/managed-by: Helm - spec: - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchExpressions: - - key: app - operator: In - values: - - portal - topologyKey: kubernetes.io/hostname - weight: 100 - automountServiceAccountToken: false - volumes: - - name: config-volume - secret: - secretName: portal-config - - name: sponsor-img-volume - secret: - secretName: portal-sponsor-config - - configMap: - name: privacy-policy - name: privacy-policy - containers: - - name: portal - image: "quay.io/cdis/data-portal:3.30.0" - imagePullPolicy: Always - livenessProbe: - httpGet: - path: /portal/ - port: 80 - initialDelaySeconds: 60 - periodSeconds: 30 - timeoutSeconds: 30 - failureThreshold: 30 - readinessProbe: - httpGet: - path: /portal/ - port: 80 - initialDelaySeconds: 30 - periodSeconds: 60 - timeoutSeconds: 30 - # TODO: re-add resources - ports: - - containerPort: 80 - - containerPort: 443 - command: - - /bin/bash - - ./dockerStart.sh - env: - - name: HOSTNAME - value: revproxy-service - # disable npm 7's brand new update notifier to prevent Portal from stuck at starting up - # see https://github.com/npm/cli/issues/3163 - - name: NPM_CONFIG_UPDATE_NOTIFIER - value: "false" - - name: APP - value: "dev" - - name: GEN3_BUNDLE - # optional: true - value: "" - - name: LOGOUT_INACTIVE_USERS - valueFrom: - configMapKeyRef: - name: manifest-global - key: logout_inactive_users - optional: true - - name: WORKSPACE_TIMEOUT_IN_MINUTES - valueFrom: - configMapKeyRef: - name: manifest-global - key: workspace_timeout_in_minutes - optional: true - - name: TIER_ACCESS_LEVEL - valueFrom: - configMapKeyRef: - name: manifest-global - # acceptable values for `tier_access_level` are: `libre`, `regular` and `private`. If omitted, by default common will be treated as `private` - key: tier_access_level - # for now making it optional so won't break anything - optional: true - - name: TIER_ACCESS_LIMIT - valueFrom: - configMapKeyRef: - name: manifest-global - key: tier_access_limit - optional: true - - name: FENCE_URL - valueFrom: - configMapKeyRef: - name: manifest-global - key: fence_url - optional: true - - name: INDEXD_URL - valueFrom: - configMapKeyRef: - name: manifest-global - key: indexd_url - optional: true - - name: WORKSPACE_URL - valueFrom: - configMapKeyRef: - name: manifest-global - key: workspace_url - optional: true - - name: MANIFEST_SERVICE_URL - valueFrom: - configMapKeyRef: - name: manifest-global - key: manifest_service_url - optional: true - - name: WTS_URL - valueFrom: - configMapKeyRef: - name: manifest-global - key: wts_url - optional: true - - name: PRIVACY_POLICY_URL - valueFrom: - configMapKeyRef: - name: manifest-global - key: privacy_policy_url - optional: true - - name: MAPBOX_API_TOKEN - # Optional token for mapbox api - valueFrom: - configMapKeyRef: - name: global - key: mapbox_token - optional: true - - name: DATADOG_APPLICATION_ID - # Optional application ID for Datadog - valueFrom: - secretKeyRef: - name: portal-datadog-config - key: datadog_application_id - optional: true - - name: DATADOG_CLIENT_TOKEN - # Optional client token for Datadog - valueFrom: - secretKeyRef: - name: portal-datadog-config - key: datadog_client_token - optional: true - - name: DATA_UPLOAD_BUCKET - # S3 bucket name for data upload, for setting up CSP - #GEN3_DATA_UPLOAD_BUCKET|-value: ""-| - - name: BASENAME - volumeMounts: - - mountPath: /data-portal/data/config/gitops.json - name: config-volume - subPath: gitops.json - - mountPath: /data-portal/custom/logo/gitops-logo.png - name: config-volume - subPath: gitops-logo.png - - mountPath: /data-portal/custom/createdby/gitops.png - name: config-volume - subPath: gitops-createdby.png - - mountPath: /data-portal/custom/favicon/gitops-favicon.ico - name: config-volume - subPath: gitops-favicon.ico - - mountPath: /data-portal/custom/css/gitops.css - name: config-volume - subPath: gitops.css - - mountPath: /data-portal/custom/sponsors/gitops-sponsors - name: sponsor-img-volume - - mountPath: /data-portal/custom/privacy_policy.md - name: privacy-policy - readOnly: true - subPath: privacy_policy.md ---- -# Source: portal/templates/tests/test-connection.yaml -apiVersion: v1 -kind: Pod -metadata: - name: "portal-test-connection" - labels: - helm.sh/chart: portal-0.1.0 - app.kubernetes.io/name: portal - app.kubernetes.io/instance: portal - app.kubernetes.io/version: "1.16.0" - app.kubernetes.io/managed-by: Helm - annotations: - "helm.sh/hook": test -spec: - containers: - - name: wget - image: busybox - command: ['wget'] - args: ['portal:80'] - restartPolicy: Never diff --git a/helm/portal/templates/configMap.yaml b/helm/portal/templates/configMap.yaml deleted file mode 100644 index ab730274..00000000 --- a/helm/portal/templates/configMap.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: docker-command -data: - dockerStart.sh: - #!/bin/sh - # - # Little startup script fetches data dictionary, and runs the relay - # compiler, then webpack before launching nginx - # - set -eu - - export NODE_ENV=production; - - bash runWebpack.sh - - /usr/sbin/nginx -g 'daemon off;' \ No newline at end of file diff --git a/helm/portal/templates/deployment.yaml b/helm/portal/templates/deployment.yaml index 9331869d..027e407a 100644 --- a/helm/portal/templates/deployment.yaml +++ b/helm/portal/templates/deployment.yaml @@ -24,11 +24,19 @@ spec: {{- end }} automountServiceAccountToken: {{ .Values.automountServiceAccountToken}} volumes: - {{- toYaml .Values.volumes | nindent 8 }} + - name: config-volume + secret: + secretName: "portal-config" + - name: sponsor-img-volume + secret: + secretName: "portal-sponsor-config" + - name: privacy-policy + configMap: + name: "privacy-policy" containers: - name: portal - image: "quay.io/cdis/data-portal:latest" - # imagePullPolicy: Never + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} # livenessProbe: # httpGet: # path: / @@ -48,12 +56,10 @@ spec: ports: - containerPort: 80 - containerPort: 443 - command: - - /bin/bash - - ./dockerStart.sh + # command: + # - /bin/bash + # - ./dockerStart.sh env: - - name: NODE_ENV - value: dev - name: HOSTNAME value: revproxy-service # disable npm 7's brand new update notifier to prevent Portal from stuck at starting up @@ -154,7 +160,27 @@ spec: {{- end }} # S3 bucket name for data upload, for setting up CSP #GEN3_DATA_UPLOAD_BUCKET|-value: ""-| - - name: BASENAME + # - name: BASENAME volumeMounts: - {{- toYaml .Values.volumeMounts | nindent 12 }} - + - name: "config-volume" + mountPath: "/data-portal/data/config/gitops.json" + subPath: "gitops.json" + - name: "config-volume" + mountPath: "/data-portal/custom/logo/gitops-logo.png" + subPath: "gitops-logo.png" + - name: "config-volume" + mountPath: "/data-portal/custom/createdby/gitops.png" + subPath: "gitops-createdby.png" + - name: "config-volume" + mountPath: "/data-portal/custom/favicon/gitops-favicon.ico" + subPath: "gitops-favicon.ico" + - name: "config-volume" + mountPath: "/data-portal/custom/css/gitops.css" + subPath: "gitops.css" + - name: "sponsor-img-volume" + mountPath: "/data-portal/custom/sponsors/gitops-sponsors" + - name: "privacy-policy" + readOnly: true + mountPath: "/data-portal/custom/privacy_policy.md" + subPath: "privacy_policy.md" + \ No newline at end of file diff --git a/helm/portal/values.yaml b/helm/portal/values.yaml index 26324ef5..e782cac7 100644 --- a/helm/portal/values.yaml +++ b/helm/portal/values.yaml @@ -5,10 +5,11 @@ replicaCount: 1 image: - repository: nginx + repository: quay.io/cdis/data-portal-prebuilt pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. - tag: "" + tag: "brh.data-commons.org-feat-develop" + imagePullSecrets: [] nameOverride: "" @@ -40,34 +41,6 @@ service: type: ClusterIP port: 80 -ingress: - enabled: false - className: "" - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: - - path: / - pathType: ImplementationSpecific - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - autoscaling: enabled: false minReplicas: 1 @@ -79,8 +52,6 @@ nodeSelector: {} tolerations: [] -affinity: {} - selectorLabels: app: portal @@ -112,8 +83,6 @@ affinity: automountServiceAccountToken: false - - resources: requests: cpu: 0.6 @@ -123,45 +92,3 @@ resources: memory: 4096Mi portalApp: "dev" - -volumes: - - name: docker-config - configMap: - name: docker-command - - name: config-volume - secret: - secretName: "portal-config" - - name: sponsor-img-volume - secret: - secretName: "portal-sponsor-config" - - name: privacy-policy - configMap: - name: "privacy-policy" - -env: - -volumeMounts: - - name: "docker-config" - mountPath: "/data-portal/dockerStart.sh" - subPath: "dockerStart.sh" - - name: "config-volume" - mountPath: "/data-portal/data/config/gitops.json" - subPath: "gitops.json" - - name: "config-volume" - mountPath: "/data-portal/custom/logo/gitops-logo.png" - subPath: "gitops-logo.png" - - name: "config-volume" - mountPath: "/data-portal/custom/createdby/gitops.png" - subPath: "gitops-createdby.png" - - name: "config-volume" - mountPath: "/data-portal/custom/favicon/gitops-favicon.ico" - subPath: "gitops-favicon.ico" - - name: "config-volume" - mountPath: "/data-portal/custom/css/gitops.css" - subPath: "gitops.css" - - name: "sponsor-img-volume" - mountPath: "/data-portal/custom/sponsors/gitops-sponsors" - - name: "privacy-policy" - readOnly: true - mountPath: "/data-portal/custom/privacy_policy.md" - subPath: "privacy_policy.md" diff --git a/helm/requestor/Chart.lock b/helm/requestor/Chart.lock index 2d4691a8..36d20121 100644 --- a/helm/requestor/Chart.lock +++ b/helm/requestor/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: common repository: file://../common - version: 0.0.1 -digest: sha256:9447ea9a4ddee41221215f9d511d904829f457523bc78ddaa817c161e934f27f -generated: "2022-10-20T21:34:44.799398-05:00" + version: 0.1.0 +digest: sha256:8e96d9e4e8522837b307a10e8683e8b21330a984d519e9ed2867ea759da7207e +generated: "2022-12-07T10:38:58.71358+01:00" diff --git a/helm/requestor/Chart.yaml b/helm/requestor/Chart.yaml index 77d1dee4..8433fdef 100644 --- a/helm/requestor/Chart.yaml +++ b/helm/requestor/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -26,6 +26,6 @@ appVersion: "2022.10" dependencies: - name: common - version: 0.0.1 + version: 0.1.0 repository: file://../common - condition: db_creation.enabled \ No newline at end of file + condition: db_creation.enabled diff --git a/helm/requestor/README.md b/helm/requestor/README.md new file mode 100644 index 00000000..75f2b869 --- /dev/null +++ b/helm/requestor/README.md @@ -0,0 +1,90 @@ +# requestor + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 Requestor Service + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../common | common | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key | string | `"app"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator | string | `"In"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0] | string | `"requestor"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey | string | `"kubernetes.io/hostname"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight | int | `100` | | +| arboristUrl | string | `"http://arborist-service"` | | +| args[0] | string | `"-c"` | | +| args[1] | string | `"/env/bin/alembic upgrade head\n"` | | +| automountServiceAccountToken | bool | `false` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| command[0] | string | `"/bin/sh"` | | +| containerPort[0].containerPort | int | `80` | | +| dataDog.enabled | bool | `false` | | +| dataDog.env | string | `"dev"` | | +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/cdis/requestor"` | | +| image.tag | string | `"master"` | | +| initContainerName | string | `"requestor-db-migrate"` | | +| initResources.limits.cpu | float | `0.8` | | +| initResources.limits.memory | string | `"512Mi"` | | +| livenessProbe.httpGet.path | string | `"/_status"` | | +| livenessProbe.httpGet.port | int | `80` | | +| livenessProbe.initialDelaySeconds | int | `30` | | +| livenessProbe.periodSeconds | int | `60` | | +| livenessProbe.timeoutSeconds | int | `30` | | +| postgres.database | string | `"requestor"` | | +| postgres.db_create | string | `nil` | | +| postgres.password | string | `nil` | | +| postgres.port | string | `"5432"` | | +| postgres.username | string | `"requestor"` | | +| readinessProbe.httpGet.path | string | `"/_status"` | | +| readinessProbe.httpGet.port | int | `80` | | +| releaseLabel | string | `"production"` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | float | `0.8` | | +| resources.limits.memory | string | `"1024Mi"` | | +| resources.requests.cpu | float | `0.1` | | +| resources.requests.memory | string | `"128Mi"` | | +| revisionHistoryLimit | int | `2` | | +| service.port[0].name | string | `"http"` | | +| service.port[0].port | int | `80` | | +| service.port[0].protocol | string | `"TCP"` | | +| service.port[0].targetPort | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| strategy.rollingUpdate.maxSurge | int | `1` | | +| strategy.rollingUpdate.maxUnavailable | int | `0` | | +| strategy.type | string | `"RollingUpdate"` | | +| volumeMounts | string | `nil` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/requestor/templates/db-init.yaml b/helm/requestor/templates/db-init.yaml index e53cb144..a197f530 100644 --- a/helm/requestor/templates/db-init.yaml +++ b/helm/requestor/templates/db-init.yaml @@ -1,3 +1,3 @@ -{{- include "common.db-setup-job" . }} +{{ include "common.db-setup-job" . }} --- -{{- include "common.db-secret" . }} +{{ include "common.db-secret" . }} diff --git a/helm/requestor/templates/deployment.yaml b/helm/requestor/templates/deployment.yaml index ccad623c..306aeccd 100644 --- a/helm/requestor/templates/deployment.yaml +++ b/helm/requestor/templates/deployment.yaml @@ -39,9 +39,35 @@ spec: secret: secretName: "requestor-g3auto" containers: - - name: {{ .Chart.Name }} + - name: requestor image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - env: + env: + - name: DB_PORT + value: "5432" + - name: DB_HOST + valueFrom: + secretKeyRef: + name: requestor-dbcreds + key: host + optional: false + - name: DB_USER + valueFrom: + secretKeyRef: + name: requestor-dbcreds + key: username + optional: false + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: requestor-dbcreds + key: password + optional: false + - name: DB_DATABASE + valueFrom: + secretKeyRef: + name: requestor-dbcreds + key: database + optional: false - name: GEN3_DEBUG value: "False" {{- with .Values.arboristUrl }} @@ -73,6 +99,33 @@ spec: - name: requestor-db-migrate image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: DB_PORT + value: "5432" + - name: DB_HOST + valueFrom: + secretKeyRef: + name: requestor-dbcreds + key: host + optional: false + - name: DB_USER + valueFrom: + secretKeyRef: + name: requestor-dbcreds + key: username + optional: false + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: requestor-dbcreds + key: password + optional: false + - name: DB_DATABASE + valueFrom: + secretKeyRef: + name: requestor-dbcreds + key: database + optional: false {{- with .Values.volumeMounts }} volumeMounts: {{- toYaml . | nindent 10 }} diff --git a/helm/requestor/templates/requestor-secret.yaml b/helm/requestor/templates/requestor-secret.yaml deleted file mode 100644 index eec42442..00000000 --- a/helm/requestor/templates/requestor-secret.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: requestor-g3auto -type: Opaque -stringData: - dbcreds.json: |- - { - "db_host": {{ .Values.secrets.host | quote }}, - "db_username": {{ .Values.secrets.user | quote }}, - "db_password": {{ include "requestor.postgres.password" . | quote }}, - "db_database": {{ .Values.secrets.database | quote }} - - } - requestor-config.yaml: |- - # Server - - DEBUG: true - - # Database - - DB_HOST: {{ .Values.secrets.host | quote }} - DB_USER: {{ .Values.secrets.user | quote }} - DB_PASSWORD: {{ include "requestor.postgres.password" . | quote }} - DB_DATABASE: {{ .Values.secrets.database | quote }} - \ No newline at end of file diff --git a/helm/requestor/values.yaml b/helm/requestor/values.yaml index 0c3c4af3..d94ae64d 100644 --- a/helm/requestor/values.yaml +++ b/helm/requestor/values.yaml @@ -2,22 +2,37 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. global: - # Default values are for postgres deployed as a helm chart + dev: true postgres: - host: postgres-postgresql.postgres.svc.cluster.local + db_create: true master: + host: username: postgres - password: - port: 5432 + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false -db_create: true postgres: - # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you + db_create: + # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you database: requestor username: requestor - port: 5432 + port: "5432" # If left empty password will be auto-generated - password: + password: # Deployment @@ -43,7 +58,7 @@ dataDog: enabled: false env: dev -affinity: +affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 @@ -62,7 +77,7 @@ image: repository: quay.io/cdis/requestor pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. - tag: "" + tag: "master" # Environment Variables arboristUrl: http://arborist-service @@ -82,11 +97,11 @@ readinessProbe: containerPort: - containerPort: 80 -volumeMounts: - - name: "config-volume" - readOnly: true - mountPath: "/src/requestor-config.yaml" - subPath: "requestor-config.yaml" +volumeMounts: + # - name: "config-volume" + # readOnly: true + # mountPath: "/src/requestor-config.yaml" + # subPath: "requestor-config.yaml" resources: requests: @@ -111,18 +126,11 @@ args: - | /env/bin/alembic upgrade head -#Service and Pod +# Service and Pod service: type: ClusterIP port: - protocol: TCP port: 80 - targetPort: 80 + targetPort: 80 name: http - -# Secrets -secrets: - host: postgres-postgresql.postgres.svc.cluster.local - user: postgres - password: - database: requestor \ No newline at end of file diff --git a/helm/revproxy/Chart.yaml b/helm/revproxy/Chart.yaml index 42fc5592..307a0d43 100644 --- a/helm/revproxy/Chart.yaml +++ b/helm/revproxy/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/revproxy/README.md b/helm/revproxy/README.md new file mode 100644 index 00000000..6fd94da5 --- /dev/null +++ b/helm/revproxy/README.md @@ -0,0 +1,74 @@ +# revproxy + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 revproxy + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| fullnameOverride | string | `""` | | +| global.aws.account | string | `nil` | | +| global.aws.enabled | bool | `false` | | +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"nginx"` | | +| image.tag | string | `"1.13.9-perl"` | | +| imagePullSecrets | list | `[]` | | +| ingress.annotations | object | `{}` | | +| ingress.className | string | `""` | | +| ingress.enabled | bool | `false` | | +| ingress.hosts[0].host | string | `"chart-example.local"` | | +| ingress.hosts[0].paths[0].path | string | `"/"` | | +| ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | | +| ingress.tls | list | `[]` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | | +| podSecurityContext | object | `{}` | | +| replicaCount | int | `1` | | +| resources | string | `nil` | | +| revisionHistoryLimit | int | `2` | | +| revproxyElb.gen3SecretsFolder | string | `"Gen3Secrets"` | | +| revproxyElb.sslCert | string | `""` | | +| revproxyElb.targetPortHTTP | int | `80` | | +| revproxyElb.targetPortHTTPS | int | `443` | | +| securityContext | object | `{}` | | +| service.port | int | `80` | | +| service.type | string | `"NodePort"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| strategy.rollingUpdate.maxSurge | int | `1` | | +| strategy.rollingUpdate.maxUnavailable | int | `0` | | +| strategy.type | string | `"RollingUpdate"` | | +| tolerations | list | `[]` | | +| userhelperEnabled | bool | `false` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/revproxy/gen3.nginx.conf/arborist-service.conf b/helm/revproxy/gen3.nginx.conf/arborist-service.conf index 53d8c952..f68f6dd0 100644 --- a/helm/revproxy/gen3.nginx.conf/arborist-service.conf +++ b/helm/revproxy/gen3.nginx.conf/arborist-service.conf @@ -30,7 +30,7 @@ location = /gen3-authz { error_page 500 =403 @errorworkspace; # avoid setting $upstream in authz subrequests ... - set $upstream_authz http://${arborist_release_name}-service.$namespace.svc.cluster.local; + set $upstream_authz http://arborist-service.$namespace.svc.cluster.local; proxy_pass $upstream_authz/auth/proxy?resource=$authz_resource&method=$authz_method&service=$authz_service; @@ -58,7 +58,7 @@ location ~ /authz/? { return 403 "failed csrf check"; } set $proxy_service "arborist"; - set $upstream http://${arborist_release_name}-service.$namespace.svc.cluster.local; + set $upstream http://arborist-service.$namespace.svc.cluster.local; proxy_pass $upstream/auth/proxy?resource=$arg_resource&method=$arg_method&service=$arg_service; } @@ -68,7 +68,7 @@ location = /authz/resources { return 403 "failed csrf check"; } set $proxy_service "arborist"; - set $upstream http://${arborist_release_name}-service.$namespace.svc.cluster.local; + set $upstream http://arborist-service.$namespace.svc.cluster.local; proxy_pass $upstream/auth/resources; } @@ -84,7 +84,7 @@ location = /authz/mapping { } set $proxy_service "arborist"; - set $upstream http://${arborist_release_name}-service.$namespace.svc.cluster.local; + set $upstream http://arborist-service.$namespace.svc.cluster.local; # Do not pass the username arg here! Otherwise anyone can see anyone's access. # Arborist will fall back to parsing the jwt for username. @@ -108,8 +108,8 @@ location = /authz/policy { # be careful - sub-request runs in same context as this request auth_request /gen3-authz; - set $proxy_service ${arborist_release_name}; - set $upstream http://${arborist_release_name}-service.$namespace.svc.cluster.local; + set $proxy_service arborist; + set $upstream http://arborist-service.$namespace.svc.cluster.local; rewrite ^/authz/(.*) /$1 break; proxy_pass $upstream; proxy_redirect http://$host/ https://$host/authz/; @@ -126,7 +126,7 @@ location = /gen3-authz-test { # be careful - sub-request runs in same context as this request auth_request /gen3-authz; - set $proxy_service "${fence_release_name}"; - set $upstream http://${fence_release_name}-service.$namespace.svc.cluster.local; + set $proxy_service "fence"; + set $upstream http://fence-service.$namespace.svc.cluster.local; proxy_pass $upstream/$authz_method; } diff --git a/helm/revproxy/gen3.nginx.conf/argocd-service.conf b/helm/revproxy/gen3.nginx.conf/argocd-service.conf new file mode 100644 index 00000000..afe1f454 --- /dev/null +++ b/helm/revproxy/gen3.nginx.conf/argocd-service.conf @@ -0,0 +1,19 @@ +location /argocd { + error_page 403 @errorworkspace; + set $authz_resource "/argocd"; + set $authz_method "access"; + set $authz_service "argocd"; + # be careful - sub-request runs in same context as this request + auth_request /gen3-authz; + + set $proxy_service "argocd"; + # $upstream is written to the logs + set $upstream http://argocd-server.argocd.svc.cluster.local; + rewrite ^/argocd/(.*) /$1 break; + + proxy_set_header Connection ''; + proxy_http_version 1.1; + chunked_transfer_encoding off; + + proxy_pass $upstream; +} \ No newline at end of file diff --git a/helm/revproxy/gen3.nginx.conf/devbot-service.conf b/helm/revproxy/gen3.nginx.conf/devbot-service.conf index 26aaae23..85804739 100644 --- a/helm/revproxy/gen3.nginx.conf/devbot-service.conf +++ b/helm/revproxy/gen3.nginx.conf/devbot-service.conf @@ -4,8 +4,8 @@ return 403 "failed csrf check"; } - set $proxy_service "${devbot_release_name}"; - set $upstream http://${devbot_release_name}-service$des_domain; + set $proxy_service "devbot"; + set $upstream http://devbot-service$des_domain; rewrite ^/devbot/(.*) /$1 break; proxy_pass $upstream; proxy_redirect http://$host/ https://$host/devbot/; diff --git a/helm/revproxy/gen3.nginx.conf/fence-service-ga4gh.conf b/helm/revproxy/gen3.nginx.conf/fence-service-ga4gh.conf index dc055af2..b017919f 100644 --- a/helm/revproxy/gen3.nginx.conf/fence-service-ga4gh.conf +++ b/helm/revproxy/gen3.nginx.conf/fence-service-ga4gh.conf @@ -3,8 +3,8 @@ location ~ \/ga4gh\/drs\/v1\/objects\/(.*)\/access { return 403 "failed csrf check"; } - set $proxy_service "${presigned_url_fence_release_name}"; - set $upstream http://${presigned_url_fence_release_name}-service$des_domain; + set $proxy_service "presigned_url_fence"; + set $upstream http://presigned_url_fence-service$des_domain; rewrite ^/user/(.*) /$1 break; proxy_pass $upstream; } diff --git a/helm/revproxy/gen3.nginx.conf/fence-service.conf b/helm/revproxy/gen3.nginx.conf/fence-service.conf index f37b0f3a..5a792424 100644 --- a/helm/revproxy/gen3.nginx.conf/fence-service.conf +++ b/helm/revproxy/gen3.nginx.conf/fence-service.conf @@ -4,8 +4,8 @@ # of the logged in user for later use location /authn-proxy { internal; - set $proxy_service "${fence_release_name}"; - set $upstream_auth http://${fence_release_name}-service${des_domain}/user/anyaccess; + set $proxy_service "fence"; + set $upstream_auth http://fence-service${des_domain}/user/anyaccess; proxy_pass $upstream_auth; proxy_pass_request_body off; proxy_set_header Authorization "$access_token"; @@ -25,8 +25,8 @@ location /user/ { return 403 "failed csrf check"; } - set $proxy_service "${fence_release_name}"; - set $upstream http://${fence_release_name}-service$des_domain; + set $proxy_service "fence"; + set $upstream http://fence-service$des_domain; rewrite ^/user/(.*) /$1 break; proxy_pass $upstream; } @@ -35,8 +35,8 @@ location /user/register { # Like /user/ but without CSRF check. Registration form submission is # incompatible with revproxy-level cookie-to-header CSRF check. # Fence enforces its own CSRF protection here so this is OK. - set $proxy_service "${fence_release_name}"; - set $upstream http://${fence_release_name}-service$des_domain; + set $proxy_service "fence"; + set $upstream http://fence-service$des_domain; rewrite ^/user/(.*) /$1 break; proxy_pass $upstream; } @@ -46,8 +46,8 @@ location /user/data/download { return 403 "failed csrf check"; } - set $proxy_service "${presigned_url_fence_release_name}"; - set $upstream http://${presigned_url_fence_release_name}-service$des_domain; + set $proxy_service "presigned_url_fence"; + set $upstream http://presigned_url_fence-service$des_domain; rewrite ^/user/(.*) /$1 break; proxy_pass $upstream; } @@ -62,7 +62,7 @@ location /.well-known/ { return 403 "failed csrf check"; } - set $proxy_service "${fence_release_name}"; - set $upstream http://${fence_release_name}-service$des_domain; + set $proxy_service "fence"; + set $upstream http://fence-service$des_domain; proxy_pass $upstream; } diff --git a/helm/revproxy/gen3.nginx.conf/indexd-service.conf b/helm/revproxy/gen3.nginx.conf/indexd-service.conf index 964f4507..a464afcc 100644 --- a/helm/revproxy/gen3.nginx.conf/indexd-service.conf +++ b/helm/revproxy/gen3.nginx.conf/indexd-service.conf @@ -5,8 +5,8 @@ return 403 "failed csrf check"; } - set $proxy_service "${indexd_release_name}"; - set $upstream http://${indexd_release_name}-service$des_domain; + set $proxy_service "indexd"; + set $upstream http://indexd-service$des_domain; proxy_pass $upstream; proxy_redirect http://$host/ https://$host/; } @@ -16,8 +16,8 @@ return 403 "failed csrf check"; } - set $proxy_service "${indexd_release_name}"; - set $upstream http://${indexd_release_name}-service$des_domain; + set $proxy_service "indexd"; + set $upstream http://indexd-service$des_domain; rewrite ^/index/(.*) /$1 break; proxy_pass $upstream; proxy_redirect http://$host/ https://$host/index/; @@ -42,8 +42,8 @@ # For testing: #add_header Set-Cookie "X-Frickjack=${indexd_password};Path=/;Max-Age=600"; - set $proxy_service "${indexd_release_name}"; - set $upstream http://${indexd_release_name}-service$des_domain; + set $proxy_service "indexd"; + set $upstream http://indexd-service$des_domain; rewrite ^/index-admin/(.*) /$1 break; proxy_set_header Host $host; proxy_set_header X-Forwarded-For "$realip"; diff --git a/helm/revproxy/gen3.nginx.conf/manifestservice-service.conf b/helm/revproxy/gen3.nginx.conf/manifestservice-service.conf index 99899ea0..2e271130 100644 --- a/helm/revproxy/gen3.nginx.conf/manifestservice-service.conf +++ b/helm/revproxy/gen3.nginx.conf/manifestservice-service.conf @@ -4,8 +4,8 @@ return 403 "failed csrf check"; } - set $proxy_service "${manifestservice_release_name}"; - set $upstream http://${manifestservice_release_name}-service.$namespace.svc.cluster.local; + set $proxy_service "manifestservice"; + set $upstream http://manifestservice-service.$namespace.svc.cluster.local; rewrite ^/manifests/(.*) /$1 break; proxy_pass $upstream; proxy_redirect http://$host/ https://$host/manifests/; diff --git a/helm/revproxy/gen3.nginx.conf/peregrine-service.conf b/helm/revproxy/gen3.nginx.conf/peregrine-service.conf index 3b0c3679..db172326 100644 --- a/helm/revproxy/gen3.nginx.conf/peregrine-service.conf +++ b/helm/revproxy/gen3.nginx.conf/peregrine-service.conf @@ -1,11 +1,11 @@ # Simplify external access to health checks location /peregrine/_status { - set $proxy_service "${peregrine_release_name}"; - set $upstream http://${peregrine_release_name}-service.$namespace.svc.cluster.local/_status; + set $proxy_service "peregrine"; + set $upstream http://peregrine-service.$namespace.svc.cluster.local/_status; proxy_pass $upstream; } location /peregrine/_version { - set $upstream http://${peregrine_release_name}-service.$namespace.svc.cluster.local/_version; + set $upstream http://peregrine-service.$namespace.svc.cluster.local/_version; proxy_pass $upstream; } location /api/search { @@ -28,8 +28,8 @@ proxy_read_timeout 300; send_timeout 300; - set $proxy_service "${peregrine_release_name}"; - set $upstream http://${peregrine_release_name}-service.$namespace.svc.cluster.local; + set $proxy_service "peregrine"; + set $upstream http://peregrine-service.$namespace.svc.cluster.local; rewrite ^/api/search/(.*) /$1 break; proxy_pass $upstream; } @@ -53,8 +53,8 @@ proxy_read_timeout 300; send_timeout 300; - set $proxy_service "${peregrine_release_name}"; - set $upstream http://${peregrine_release_name}-service.$namespace.svc.cluster.local/v0/submission/graphql; + set $proxy_service "peregrine"; + set $upstream http://peregrine-service.$namespace.svc.cluster.local/v0/submission/graphql; proxy_pass $upstream; } location /api/v0/submission/getschema { @@ -64,7 +64,7 @@ proxy_next_upstream off; - set $proxy_service "${peregrine_release_name}"; - set $upstream http://${peregrine_release_name}-service.$namespace.svc.cluster.local/v0/submission/getschema; + set $proxy_service "peregrine"; + set $upstream http://peregrine-service.$namespace.svc.cluster.local/v0/submission/getschema; proxy_pass $upstream; } diff --git a/helm/revproxy/gen3.nginx.conf/status-api-service.conf b/helm/revproxy/gen3.nginx.conf/status-api-service.conf index e6601327..c558833e 100644 --- a/helm/revproxy/gen3.nginx.conf/status-api-service.conf +++ b/helm/revproxy/gen3.nginx.conf/status-api-service.conf @@ -5,8 +5,8 @@ return 403 "failed csrf check"; } - set $proxy_service "${status_api_release_name}"; - set $upstream http://${status_api_release_name}-service$des_domain; + set $proxy_service "status_api"; + set $upstream http://status_api-service$des_domain; rewrite ^/status/(.*) /$1 break; proxy_pass $upstream; proxy_redirect http://$host/ https://$host/status/; diff --git a/helm/revproxy/nginx/nginx.conf b/helm/revproxy/nginx/nginx.conf index f7a04f10..7edb1739 100644 --- a/helm/revproxy/nginx/nginx.conf +++ b/helm/revproxy/nginx/nginx.conf @@ -87,12 +87,6 @@ include /etc/nginx/gen3_server*.conf; # # Setup root path frontend service # perl_set $frontend_root_service 'sub { return $ENV{"FRONTEND_ROOT"} eq "gen3ff" ? "gen3ff" : "portal"; }'; -# ## -# # Get canary weight environment vars into block -# # This allows us to use the var in njs scripts -# ## -# perl_set $canary_percent_json 'sub { return $ENV{"CANARY_PERCENT_JSON"}; }'; - ## # Service release parsing and assignment # @@ -101,11 +95,6 @@ js_set $service_releases getServiceReleases; ## # Logging Settings ## -# log_format aws '$realip - $userid [$time_local] ' -# '"$request" "$upstream" $status $body_bytes_sent ' -# '"$http_referer" "$http_user_agent" "$canary_percent_json"'; -# error_log /dev/stderr warn; - log_format json '{"gen3log": "nginx", ' '"date_access": "$time_iso8601", ' '"user_id": "$userid", ' @@ -353,37 +342,6 @@ server { set $csrf_check "ok-tokenauth"; } - ## - # Set variables for service release names - ## - set $fence_release_name "fence"; - # TODO: configure the rest of the canary-related config later - set $presigned_url_fence_release_name "presigned-url-fence"; - if ($service_releases ~* "fence\.canary") { - set $fence_release_name "${fence_release_name}-canary"; - } - set $fenceshib_release_name "fenceshib"; - if ($service_releases ~* "fenceshib\.canary") { - set $fenceshib_release_name "${fenceshib_release_name}-canary"; - } - set $sheepdog_release_name "sheepdog"; - if ($service_releases ~* "sheepdog\.canary") { - set $sheepdog_release_name "${sheepdog_release_name}-canary"; - } - set $peregrine_release_name "peregrine"; - if ($service_releases ~* "peregrine\.canary") { - set $peregrine_release_name "${peregrine_release_name}-canary"; - } - set $indexd_release_name "indexd"; - if ($service_releases ~* "indexd\.canary") { - set $indexd_release_name "${indexd_release_name}-canary"; - } - set $manifestservice_release_name "manifestservice"; - if ($service_releases ~* "manifestservice\.canary") { - set $manifestservice_release_name "${manifestservice_release_name}-canary"; - } - set $arborist_release_name "arborist"; - error_page 500 501 502 503 504 @5xx; location @5xx { diff --git a/helm/revproxy/templates/deployment.yaml b/helm/revproxy/templates/deployment.yaml index 41666220..83bb2f1e 100644 --- a/helm/revproxy/templates/deployment.yaml +++ b/helm/revproxy/templates/deployment.yaml @@ -50,25 +50,6 @@ spec: - name: revproxy-subconf configMap: name: revproxy-nginx-subconf - # TODO: Evaluate if we can omit these - # - name: modsec-conf - # configMap: - # name: manifest-modsec - # - name: revproxy-manifest-conf - # configMap: - # name: manifest-revproxy - # - name: helper-js - # configMap: - # name: revproxy-helper-js - # - name: cert-external-volume - # secret: - # secretName: "cert-external" - # - name: cert-volume - # secret: - # secretName: "cert-revproxy-service" - # - name: ca-volume - # secret: - # secretName: "service-ca" {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} @@ -100,11 +81,6 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace - # - name: CANARY_PERCENT_JSON - # valueFrom: - # configMapKeyRef: - # name: manifest-canary - # key: json - name: MAINTENANCE_MODE valueFrom: configMapKeyRef: diff --git a/helm/revproxy/templates/ingress.yaml b/helm/revproxy/templates/ingress.yaml index b7850dba..8bcda121 100644 --- a/helm/revproxy/templates/ingress.yaml +++ b/helm/revproxy/templates/ingress.yaml @@ -2,7 +2,19 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: revproxy + annotations: + {{- if .Values.global.aws.enabled }} + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/tags: Environment={{ .Values.global.environment }} + alb.ingress.kubernetes.io/certificate-arn: {{ .Values.global.revproxyArn }} + alb.ingress.kubernetes.io/group.name: {{ .Values.global.environment }} + alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' + alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}' + {{- end }} spec: + {{- if .Values.global.aws.enabled }} + ingressClassName: alb + {{- end }} rules: - host: {{ default .Values.global.hostname .Values.hostname }} http: diff --git a/helm/revproxy/templates/service-elb.yaml b/helm/revproxy/templates/service-elb.yaml deleted file mode 100644 index d5af8890..00000000 --- a/helm/revproxy/templates/service-elb.yaml +++ /dev/null @@ -1,28 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: revproxy-service-elb - annotations: - # TODO: Make these annotations work with templating. - # service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp - # service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443" - # # service.beta.kubernetes.io/aws-load-balancer-ssl-cert: {{ .Values.revproxyElb.sslCert }} - # service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*" - # # for holding idle noVNC websocket connections - # service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "300" - # # supported in k8s 1.9 - # service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy: "ELBSecurityPolicy-TLS-1-2-2017-01" - # see kube-setup-revproxy -spec: - selector: - app: revproxy - ports: - - protocol: TCP - port: 443 - targetPort: {{ .Values.revproxyElb.targetPortHTTPS }} - name: https - - protocol: TCP - port: 80 - targetPort: {{ .Values.revproxyElb.targetPortHTTP }} - name: http - type: LoadBalancer \ No newline at end of file diff --git a/helm/revproxy/values.yaml b/helm/revproxy/values.yaml index 56f328c7..87b802c0 100644 --- a/helm/revproxy/values.yaml +++ b/helm/revproxy/values.yaml @@ -1,6 +1,33 @@ # Default values for revproxy. # This is a YAML-formatted file. # Declare variables to be passed into your templates. +global: + aws: + enabled: false + account: + dev: true + postgres: + db_create: true + master: + host: + username: postgres + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false + replicaCount: 1 @@ -56,7 +83,7 @@ ingress: # hosts: # - chart-example.local -resources: +resources: # TODO: revaluate thse # requests: # cpu: 0.5 @@ -92,4 +119,4 @@ revproxyElb: targetPortHTTPS: 443 targetPortHTTP: 80 - gen3SecretsFolder: Gen3Secrets \ No newline at end of file + gen3SecretsFolder: Gen3Secrets diff --git a/helm/sheepdog/Chart.lock b/helm/sheepdog/Chart.lock index 71060338..cf05722b 100644 --- a/helm/sheepdog/Chart.lock +++ b/helm/sheepdog/Chart.lock @@ -1,6 +1,9 @@ dependencies: - name: common repository: file://../common - version: 0.0.1 -digest: sha256:a25c79b74ec6d89ca5c732e4222f8726ed02aa6a4a21f376afc499e53696c9b5 -generated: "2022-10-20T21:34:46.434949-05:00" + version: 0.1.0 +- name: gen3-test-data-job + repository: file://../gen3-test-data-job + version: 0.1.0 +digest: sha256:dd71fdfaf0ac6220cc7ba22fa2a9d1c53a5936271a875dbaad8e1632f408f0e9 +generated: "2022-12-07T10:38:58.727525+01:00" diff --git a/helm/sheepdog/Chart.yaml b/helm/sheepdog/Chart.yaml index 744f45d3..695a41bb 100644 --- a/helm/sheepdog/Chart.yaml +++ b/helm/sheepdog/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,9 @@ appVersion: "2022.10" dependencies: - name: common - version: 0.0.1 - repository: file://../common \ No newline at end of file + version: 0.1.0 + repository: file://../common + - name: gen3-test-data-job + version: 0.1.0 + repository: file://../gen3-test-data-job + condition: db_restore.enabled diff --git a/helm/sheepdog/README.md b/helm/sheepdog/README.md new file mode 100644 index 00000000..88ec4712 --- /dev/null +++ b/helm/sheepdog/README.md @@ -0,0 +1,117 @@ +# sheepdog + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 Sheepdog Service + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../common | common | 0.1.0 | +| file://../gen3-test-data-job | gen3-test-data-job | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key | string | `"app"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator | string | `"In"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0] | string | `"sheepdog"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey | string | `"kubernetes.io/hostname"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight | int | `100` | | +| arboristUrl | string | `"http://arborist-service.default.svc.cluster.local"` | | +| authNamespace | string | `"default"` | | +| automountServiceAccountToken | bool | `false` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| dataDog.enabled | bool | `false` | | +| dataDog.env | string | `"dev"` | | +| ddEnv | string | `nil` | | +| ddLogsInjection | string | `nil` | | +| ddProfilingEnabled | string | `nil` | | +| ddService | string | `nil` | | +| ddTraceAgentHostname | string | `nil` | | +| ddTraceEnabled | string | `nil` | | +| ddTraceSampleRate | string | `nil` | | +| ddVersion | string | `nil` | | +| dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| fenceUrl | string | `"http://fence-service"` | | +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/cdis/sheepdog"` | | +| image.tag | string | `"helm-test"` | | +| indexdUrl | string | `"http://indexd-service"` | | +| livenessProbe.httpGet.path | string | `"/_status?timeout=20"` | | +| livenessProbe.httpGet.port | int | `80` | | +| livenessProbe.initialDelaySeconds | int | `30` | | +| livenessProbe.periodSeconds | int | `60` | | +| livenessProbe.timeoutSeconds | int | `30` | | +| podAnnotations."gen3.io/network-ingress" | string | `"sheepdog"` | | +| ports[0].containerPort | int | `80` | | +| ports[1].containerPort | int | `443` | | +| postgres.database | string | `"sheepdog"` | | +| postgres.db_create | string | `nil` | | +| postgres.db_restore | bool | `false` | | +| postgres.password | string | `nil` | | +| postgres.port | string | `"5432"` | | +| postgres.username | string | `"sheepdog"` | | +| readinessProbe.httpGet.path | string | `"/_status?timeout=2"` | | +| readinessProbe.httpGet.port | int | `80` | | +| readinessProbe.initialDelaySeconds | int | `30` | | +| releaseLabel | string | `"production"` | | +| replicaCount | int | `1` | | +| resources | string | `nil` | | +| revisionHistoryLimit | int | `2` | | +| secrets.fence.database | string | `"fence"` | | +| secrets.fence.host | string | `"postgres-postgresql.postgres.svc.cluster.local"` | | +| secrets.fence.password | string | `"postgres"` | | +| secrets.fence.user | string | `"postgres"` | | +| secrets.gdcapi.secretKey | string | `nil` | | +| secrets.indexd.password | string | `"postgres"` | | +| secrets.sheepdog.database | string | `"sheepdog"` | | +| secrets.sheepdog.host | string | `"postgres-postgresql.postgres.svc.cluster.local"` | | +| secrets.sheepdog.password | string | `"postgres"` | | +| secrets.sheepdog.user | string | `"postgres"` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| strategy.rollingUpdate.maxSurge | int | `1` | | +| strategy.rollingUpdate.maxUnavailable | int | `0` | | +| strategy.type | string | `"RollingUpdate"` | | +| terminationGracePeriodSeconds | int | `50` | | +| volumeMounts[0].mountPath | string | `"/var/www/sheepdog/wsgi.py"` | | +| volumeMounts[0].name | string | `"config-volume"` | | +| volumeMounts[0].readOnly | bool | `true` | | +| volumeMounts[0].subPath | string | `"wsgi.py"` | | +| volumeMounts[1].mountPath | string | `"/var/www/sheepdog/creds.json"` | | +| volumeMounts[1].name | string | `"creds-volume"` | | +| volumeMounts[1].readOnly | bool | `true` | | +| volumeMounts[1].subPath | string | `"creds.json"` | | +| volumeMounts[2].mountPath | string | `"/var/www/sheepdog/config_helper.py"` | | +| volumeMounts[2].name | string | `"config-volume"` | | +| volumeMounts[2].readOnly | bool | `true` | | +| volumeMounts[2].subPath | string | `"config_helper.py"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/sheepdog/templates/db-init.yaml b/helm/sheepdog/templates/db-init.yaml index e53cb144..0bcbb894 100644 --- a/helm/sheepdog/templates/db-init.yaml +++ b/helm/sheepdog/templates/db-init.yaml @@ -1,3 +1,7 @@ {{- include "common.db-setup-job" . }} --- -{{- include "common.db-secret" . }} +{{ include "common.db-secret" . }} +--- +{{- if .Values.db_restore }} +{{ include "gen3-test-data-job.create-test-dbs" . }} +{{- end -}} \ No newline at end of file diff --git a/helm/sheepdog/templates/deployment.yaml b/helm/sheepdog/templates/deployment.yaml index 095fb200..644d5bb2 100644 --- a/helm/sheepdog/templates/deployment.yaml +++ b/helm/sheepdog/templates/deployment.yaml @@ -50,9 +50,52 @@ spec: - name: config-helper configMap: name: config-helper - + initContainers: + - name: sheepdog-init + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + env: + - name: DICTIONARY_URL + value: {{ .Values.dictionaryUrl }} + - name: PGHOST + valueFrom: + secretKeyRef: + name: sheepdog-dbcreds + key: host + optional: false + - name: PGUSER + valueFrom: + secretKeyRef: + name: sheepdog-dbcreds + key: username + optional: false + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: sheepdog-dbcreds + key: password + optional: false + - name: PGDB + valueFrom: + secretKeyRef: + name: sheepdog-dbcreds + key: database + optional: false + command: ["/bin/bash" ] + args: + - "-c" + # Script always succeeds if it runs (echo exits with 0) + - | + # + # sheepdog sets up core data model now, + # but suffers from a race condition doing it ... + # + echo datamodel_postgres_admin create-all -U "${PGUSER}" -P XXXXXXX -H "${PGHOST}" -D "${PGDB}" + datamodel_postgres_admin create-all -U "${PGUSER}" -P "${PGPASSWORD}" -H "${PGHOST}" -D "${PGDB}" + + echo python /sheepdog/bin/setup_transactionlogs.py --user "${PGUSER}" --password XXXXX --host "${PGHOST}" --database "${PGDB}" + python /sheepdog/bin/setup_transactionlogs.py --user "${PGUSER}" --password "${PGPASSWORD}" --host "${PGHOST}" --database "${PGDB}" containers: - - name: {{ .Chart.Name }} + - name: sheepdog image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} {{- with .Values.ports}} @@ -101,25 +144,25 @@ spec: - name: PGHOST valueFrom: secretKeyRef: - name: {{ .Chart.Name }}-dbcreds + name: sheepdog-dbcreds key: host optional: false - name: PGUSER valueFrom: secretKeyRef: - name: {{ .Chart.Name }}-dbcreds + name: sheepdog-dbcreds key: username optional: false - name: PGPASSWORD valueFrom: secretKeyRef: - name: {{ .Chart.Name }}-dbcreds + name: sheepdog-dbcreds key: password optional: false - name: PGDB valueFrom: secretKeyRef: - name: {{ .Chart.Name }}-dbcreds + name: sheepdog-dbcreds key: database optional: false - name: PUBLIC_DATASETS diff --git a/helm/sheepdog/templates/pre-install.yaml b/helm/sheepdog/templates/pre-install.yaml deleted file mode 100644 index 5ec2f0c5..00000000 --- a/helm/sheepdog/templates/pre-install.yaml +++ /dev/null @@ -1,70 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: sheepdog-dbinit - annotations: - "helm.sh/hook": "pre-install" #,pre-upgrade" -spec: - backoffLimit: 0 - template: - metadata: - labels: - app: gen3job - spec: - automountServiceAccountToken: false - # volumes: - # - name: creds-volume - # secret: - # secretName: "sheepdog-creds" - containers: - - name: sheepdog - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - env: - - name: DICTIONARY_URL - value: {{ .Values.dictionaryUrl }} - - name: PGHOST - valueFrom: - secretKeyRef: - name: {{ .Chart.Name }}-dbcreds - key: host - optional: false - - name: PGUSER - valueFrom: - secretKeyRef: - name: {{ .Chart.Name }}-dbcreds - key: username - optional: false - - name: PGPASSWORD - valueFrom: - secretKeyRef: - name: {{ .Chart.Name }}-dbcreds - key: password - optional: false - - name: PGDB - valueFrom: - secretKeyRef: - name: {{ .Chart.Name }}-dbcreds - key: database - optional: false - # volumeMounts: - # - name: "creds-volume" - # readOnly: true - # mountPath: "/var/www/sheepdog/creds.json" - # subPath: creds.json - # imagePullPolicy: Always - command: ["/bin/bash" ] - args: - - "-c" - # Script always succeeds if it runs (echo exits with 0) - - | - # - # sheepdog sets up core data model now, - # but suffers from a race condition doing it ... - # - echo datamodel_postgres_admin create-all -U "${PGUSER}" -P XXXXXXX -H "${PGHOST}" -D "${PGDB}" - datamodel_postgres_admin create-all -U "${PGUSER}" -P "${PGPASSWORD}" -H "${PGHOST}" -D "${PGDB}" - - echo python /sheepdog/bin/setup_transactionlogs.py --user "${PGUSER}" --password XXXXX --host "${PGHOST}" --database "${PGDB}" - python /sheepdog/bin/setup_transactionlogs.py --user "${PGUSER}" --password "${PGPASSWORD}" --host "${PGHOST}" --database "${PGDB}" - echo "Exit code: $?" - restartPolicy: Never \ No newline at end of file diff --git a/helm/sheepdog/templates/sheepdog-secret.yaml b/helm/sheepdog/templates/sheepdog-secret.yaml index efbcb3dc..1aa1d5af 100644 --- a/helm/sheepdog/templates/sheepdog-secret.yaml +++ b/helm/sheepdog/templates/sheepdog-secret.yaml @@ -2,13 +2,11 @@ apiVersion: v1 kind: Secret metadata: name: sheepdog-secret - annotations: - "helm.sh/hook": "pre-install,pre-upgrade" - "helm.sh/hook-weight": "-10" type: Opaque data: {{ (.Files.Glob "sheepdog-secret/*").AsSecrets | indent 2 }} --- +# TODO: Depreacate this by moving everything to environment variables apiVersion: v1 kind: Secret metadata: diff --git a/helm/sheepdog/values.yaml b/helm/sheepdog/values.yaml index 6d7d5aba..00e45c5e 100644 --- a/helm/sheepdog/values.yaml +++ b/helm/sheepdog/values.yaml @@ -4,23 +4,41 @@ # GLOBAL global: + dev: true postgres: - host: postgres-postgresql.postgres.svc.cluster.local + db_create: true master: + host: username: postgres - password: - port: 5432 + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false -# DATABASE -db_create: true postgres: - # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you + db_create: + # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you database: sheepdog username: sheepdog + port: "5432" # If left empty it will be auto-generated - password: + password: + # If db_restore is set to true then the database will have fake data/tables dumped into it. + db_restore: false -#Deployment +# Deployment releaseLabel: production podAnnotations: {"gen3.io/network-ingress": "sheepdog"} @@ -45,7 +63,7 @@ dataDog: enabled: false env: dev -affinity: +affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 @@ -76,15 +94,15 @@ indexdUrl: http://indexd-service fenceUrl: http://fence-service arboristUrl: http://arborist-service.default.svc.cluster.local authNamespace: default -#Placeholders for datadog -ddTraceEnabled: -ddEnv: +# Placeholders for datadog +ddTraceEnabled: +ddEnv: ddService: ddVersion: ddLogsInjection: ddProfilingEnabled: -ddTraceSampleRate: -ddTraceAgentHostname: +ddTraceSampleRate: +ddTraceAgentHostname: livenessProbe: @@ -127,26 +145,24 @@ resources: # cpu: 2 # memory: 2048Mi -#Service and Pod +# Service and Pod service: type: ClusterIP port: 80 # Secrets secrets: - fence: + fence: host: postgres-postgresql.postgres.svc.cluster.local user: postgres password: postgres database: fence sheepdog: - host: postgres-postgresql.postgres.svc.cluster.local + host: postgres-postgresql.postgres.svc.cluster.local password: postgres user: postgres database: sheepdog gdcapi: secretKey: - indexd: + indexd: password: postgres - - diff --git a/helm/ssjdispatcher/Chart.yaml b/helm/ssjdispatcher/Chart.yaml index 1ad87cf7..f6470521 100644 --- a/helm/ssjdispatcher/Chart.yaml +++ b/helm/ssjdispatcher/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/ssjdispatcher/README.md b/helm/ssjdispatcher/README.md new file mode 100644 index 00000000..2e86a9b5 --- /dev/null +++ b/helm/ssjdispatcher/README.md @@ -0,0 +1,73 @@ +# ssjdispatcher + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 ssjdispatcher + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key | string | `"app"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator | string | `"In"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0] | string | `"ssjdispatcher"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey | string | `"kubernetes.io/hostname"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight | int | `100` | | +| automountServiceAccountToken | bool | `true` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| awsRegion | string | `"us-east-1"` | | +| awsStsRegionalEndpoints | string | `"regional"` | | +| dispatcherJobNum | string | `"10"` | | +| fullnameOverride | string | `""` | | +| gen3Namespace | string | `"default"` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"nginx"` | | +| image.tag | string | `""` | | +| imagePullSecrets | list | `[]` | | +| indexing | string | `"707767160287.dkr.ecr.us-east-1.amazonaws.com/gen3/indexs3client:2022.08"` | | +| labels.netnolimit | string | `"yes"` | | +| labels.public | string | `"yes"` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podSecurityContext.fsGroup | int | `1000` | | +| podSecurityContext.runAsUser | int | `1000` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | float | `1` | | +| resources.limits.memory | string | `"2400Mi"` | | +| resources.requests.cpu | float | `0.1` | | +| resources.requests.memory | string | `"128Mi"` | | +| securityContext | object | `{}` | | +| selectorLabels.app | string | `"ssjdispatcher"` | | +| selectorLabels.release | string | `"production"` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `"ssjdispatcher-service-account"` | | +| ssjcreds.jobName | string | `"indexing"` | | +| ssjcreds.jobPassword | string | `"replace_with_password"` | | +| ssjcreds.jobPattern | string | `"s3://test-12345678901234-upload/*"` | | +| ssjcreds.jobRequestCpu | string | `"500m"` | | +| ssjcreds.jobRequestMem | string | `"0.5Gi"` | | +| ssjcreds.jobUrl | string | `"http://indexd-service/index"` | | +| ssjcreds.jobUser | string | `"ssj"` | | +| ssjcreds.metadataservicePassword | string | `"replace_with_password"` | | +| ssjcreds.metadataserviceUrl | string | `"http://revproxy-service/mds"` | | +| ssjcreds.metadataserviceUsername | string | `"gateway"` | | +| ssjcreds.sqsUrl | string | `"https://sqs.us-east-1.amazonaws.com/12345678901234/test-upload_data_upload"` | | +| strategy.rollingUpdate.maxSurge | int | `1` | | +| strategy.rollingUpdate.maxUnavailable | int | `0` | | +| strategy.type | string | `"RollingUpdate"` | | +| tolerations | list | `[]` | | +| volumeMounts[0].mountPath | string | `"/credentials.json"` | | +| volumeMounts[0].name | string | `"ssjdispatcher-creds-volume"` | | +| volumeMounts[0].readOnly | bool | `true` | | +| volumeMounts[0].subPath | string | `"credentials.json"` | | +| volumes[0].name | string | `"ssjdispatcher-creds-volume"` | | +| volumes[0].secret.secretName | string | `"ssjdispatcher-creds"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/ssjdispatcher/templates/service.yaml b/helm/ssjdispatcher/templates/service.yaml index 018de5a1..30ee24a0 100644 --- a/helm/ssjdispatcher/templates/service.yaml +++ b/helm/ssjdispatcher/templates/service.yaml @@ -11,5 +11,5 @@ spec: targetPort: http protocol: TCP name: http - selector:k get + selector: {{- include "ssjdispatcher.selectorLabels" . | nindent 4 }} diff --git a/helm/ssjdispatcher/templates/serviceaccount.yaml b/helm/ssjdispatcher/templates/serviceaccount.yaml index 22541c21..ac52270f 100644 --- a/helm/ssjdispatcher/templates/serviceaccount.yaml +++ b/helm/ssjdispatcher/templates/serviceaccount.yaml @@ -1,4 +1,3 @@ -{{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount metadata: @@ -6,7 +5,8 @@ metadata: labels: {{- include "ssjdispatcher.labels" . | nindent 4 }} {{- with .Values.serviceAccount.annotations }} + {{- if .Values.global.aws.enabled }} annotations: - {{- toYaml . | nindent 4 }} + eks.amazonaws.com/role-arn: arn:aws:iam::{{ .Values.global.aws.account }}:role/{{ .Values.global.aws.hatchery_role }} {{- end }} {{- end }} diff --git a/helm/ssjdispatcher/values.yaml b/helm/ssjdispatcher/values.yaml index 0879ab42..5d42b434 100644 --- a/helm/ssjdispatcher/values.yaml +++ b/helm/ssjdispatcher/values.yaml @@ -14,20 +14,6 @@ imagePullSecrets: [] nameOverride: "" fullnameOverride: "" -serviceAccount: - # Specifies whether a service account should be created - create: true - # 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: "" - -#podAnnotations: {} - -#podSecurityContext: {} - # fsGroup: 2000 - securityContext: {} # capabilities: # drop: @@ -40,34 +26,6 @@ service: type: ClusterIP port: 80 -ingress: - enabled: false - className: "" - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: - - path: / - pathType: ImplementationSpecific - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - autoscaling: enabled: false minReplicas: 1 @@ -79,8 +37,6 @@ nodeSelector: {} tolerations: [] -#affinity: {} - selectorLabels: app: ssjdispatcher release: production @@ -88,7 +44,6 @@ selectorLabels: labels: netnolimit: "yes" public: "yes" - #GEN3_DATE_LABEL podSecurityContext: runAsUser: 1000 @@ -151,7 +106,6 @@ ssjcreds: metadataserviceUrl: "http://revproxy-service/mds" metadataserviceUsername: "gateway" metadataservicePassword: "replace_with_password" - serviceAccount: # Specifies whether a service account should be created @@ -161,4 +115,3 @@ serviceAccount: # The name of the service account to use. # If not set and create is true, a name is generated using the fullname template name: "ssjdispatcher-service-account" - diff --git a/helm/terraform-runner-job/Chart.yaml b/helm/terraform-runner-job/Chart.yaml index a8b74404..fa3edf8b 100644 --- a/helm/terraform-runner-job/Chart.yaml +++ b/helm/terraform-runner-job/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm/terraform-runner-job/README.md b/helm/terraform-runner-job/README.md new file mode 100644 index 00000000..15c24c77 --- /dev/null +++ b/helm/terraform-runner-job/README.md @@ -0,0 +1,20 @@ +# terraform-runner-job + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: feat_tf1X_jq](https://img.shields.io/badge/AppVersion-feat_tf1X_jq-informational?style=flat-square) + +A Helm chart for provisioning prequisites cloud resources for gen3 + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| credentials.aws.key | string | `""` | | +| credentials.aws.secret | string | `""` | | +| credentials.aws.session_token | string | `""` | | +| image.tag | string | `"master"` | | +| terraform.destroy | bool | `false` | | +| terraform.resource_name | string | `""` | | +| terraform.workspace_name | string | `""` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/terraform-runner-job/values.yaml b/helm/terraform-runner-job/values.yaml index c9ad0816..8acbd13d 100644 --- a/helm/terraform-runner-job/values.yaml +++ b/helm/terraform-runner-job/values.yaml @@ -14,4 +14,4 @@ credentials: terraform: resource_name: "" workspace_name: "" - destroy: false \ No newline at end of file + destroy: false diff --git a/helm/wts/Chart.lock b/helm/wts/Chart.lock index d251d368..7bb434f6 100644 --- a/helm/wts/Chart.lock +++ b/helm/wts/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: common repository: file://../common - version: 0.0.1 -digest: sha256:a25c79b74ec6d89ca5c732e4222f8726ed02aa6a4a21f376afc499e53696c9b5 -generated: "2022-10-20T21:34:47.899465-05:00" + version: 0.1.0 +digest: sha256:636a65e9846bdff17cc4e65b0849061f783759a37aa51fb85ff6fd8ba5e68467 +generated: "2022-12-07T10:38:58.750918+01:00" diff --git a/helm/wts/Chart.yaml b/helm/wts/Chart.yaml index 1b71326d..019c3657 100644 --- a/helm/wts/Chart.yaml +++ b/helm/wts/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -25,5 +25,5 @@ appVersion: "2022.10" dependencies: - name: common - version: 0.0.1 - repository: file://../common \ No newline at end of file + version: 0.1.0 + repository: file://../common diff --git a/helm/wts/README.md b/helm/wts/README.md new file mode 100644 index 00000000..acf9666a --- /dev/null +++ b/helm/wts/README.md @@ -0,0 +1,82 @@ +# wts + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 workspace token service + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| file://../common | common | 0.1.0 | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| fullnameOverride | string | `""` | | +| global.ddEnabled | bool | `false` | | +| global.dev | bool | `true` | | +| global.dictionaryUrl | string | `"https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json"` | | +| global.dispatcherJobNum | int | `10` | | +| global.environment | string | `"default"` | | +| global.hostname | string | `"localhost"` | | +| global.kubeBucket | string | `"kube-gen3"` | | +| global.logsBucket | string | `"logs-gen3"` | | +| global.netPolicy | bool | `true` | | +| global.portalApp | string | `"gitops"` | | +| global.postgres.db_create | bool | `true` | | +| global.postgres.master.host | string | `nil` | | +| global.postgres.master.password | string | `nil` | | +| global.postgres.master.port | string | `"5432"` | | +| global.postgres.master.username | string | `"postgres"` | | +| global.publicDataSets | bool | `true` | | +| global.revproxyArn | string | `"arn:aws:acm:us-east-1:123456:certificate"` | | +| global.syncFromDbgap | bool | `false` | | +| global.tierAccessLevel | string | `"libre"` | | +| global.userYamlS3Path | string | `"s3://cdis-gen3-users/test/user.yaml"` | | +| hostname | string | `nil` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"quay.io/cdis/workspace-token-service"` | | +| image.tag | string | `"feat_wts_internalfence"` | | +| imagePullSecrets | list | `[]` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| oidc_client_id | string | `nil` | | +| oidc_client_secret | string | `nil` | | +| podAnnotations | object | `{}` | | +| podLabels."tags.datadoghq.com/service" | string | `"token-service"` | | +| podLabels.netnolimit | string | `"yes"` | | +| podLabels.public | string | `"yes"` | | +| podLabels.release | string | `"production"` | | +| podLabels.userhelper | string | `"yes"` | | +| podSecurityContext | object | `{}` | | +| postgres.database | string | `"wts"` | | +| postgres.db_create | string | `nil` | | +| postgres.password | string | `nil` | | +| postgres.port | string | `"5432"` | | +| postgres.username | string | `"wts"` | | +| release | string | `"production"` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | float | `0.5` | | +| resources.limits.memory | string | `"512Mi"` | | +| resources.requests.cpu | float | `0.1` | | +| resources.requests.memory | string | `"12Mi"` | | +| roleName | string | `"workspace-token-service"` | | +| secrets.external_oidc | string | `nil` | | +| securityContext | object | `{}` | | +| service.httpPort | int | `80` | | +| service.httpsPort | int | `443` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| tolerations | list | `[]` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/helm/wts/templates/db-init.yaml b/helm/wts/templates/db-init.yaml index e53cb144..a197f530 100644 --- a/helm/wts/templates/db-init.yaml +++ b/helm/wts/templates/db-init.yaml @@ -1,3 +1,3 @@ -{{- include "common.db-setup-job" . }} +{{ include "common.db-setup-job" . }} --- -{{- include "common.db-secret" . }} +{{ include "common.db-secret" . }} diff --git a/helm/wts/templates/deployment.yaml b/helm/wts/templates/deployment.yaml index 72c1c6be..d08219a7 100644 --- a/helm/wts/templates/deployment.yaml +++ b/helm/wts/templates/deployment.yaml @@ -79,6 +79,18 @@ spec: path: /_status port: 80 env: + - name: OIDC_CLIENT_ID + valueFrom: + secretKeyRef: + name: wts-oidc-client + key: client_id + optional: false + - name: OIDC_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: wts-oidc-client + key: client_secret + optional: false - name: SECRET_CONFIG value: "/var/www/wts/appcreds.json" - name: AUTH_PLUGINS @@ -113,8 +125,8 @@ spec: {{- toYaml .Values.resources | nindent 12 }} initContainers: - name: wts-db-migrate - imagePullPolicy: Always image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} volumeMounts: - name: "wts-secret" readOnly: true diff --git a/helm/wts/templates/role.yaml b/helm/wts/templates/role.yaml index 02321fbc..a0610bb4 100644 --- a/helm/wts/templates/role.yaml +++ b/helm/wts/templates/role.yaml @@ -1,7 +1,8 @@ +# TODO: name this so it can work in multiple namespaces kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: - name: {{ .Values.roleName }} + name: {{ include "wts.fullname" . }} rules: - apiGroups: [""] resources: ["namespaces", "pods"] diff --git a/helm/wts/templates/rolebinding.yaml b/helm/wts/templates/rolebinding.yaml index fb084102..b949bbe4 100644 --- a/helm/wts/templates/rolebinding.yaml +++ b/helm/wts/templates/rolebinding.yaml @@ -11,5 +11,5 @@ subjects: namespace: {{ $.Release.Namespace }} roleRef: kind: ClusterRole - name: {{ .Values.roleName }} + name: {{ include "wts.fullname" . }} apiGroup: "" diff --git a/helm/wts/templates/secret.yaml b/helm/wts/templates/secret.yaml index 76901964..5cff9815 100644 --- a/helm/wts/templates/secret.yaml +++ b/helm/wts/templates/secret.yaml @@ -1,17 +1,3 @@ -{{- range $secretName, $secret := .Values.secrets }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ $secretName }} - namespace: {{ $.Release.Namespace }} -type: Opaque -data: -{{- range $key, $value := $secret }} - {{ $key }}: {{ $value | b64enc | quote }} -{{- end }} ---- -{{- end }} ---- apiVersion: v1 kind: Secret metadata: @@ -21,11 +7,14 @@ stringData: #TODO: Fill in external_oidc in appcreds.json from values.yaml appcreds.json: | { - "wts_base_url": "https://{{ .Values.hostname }}/wts/", + "wts_base_url": "https://{{ .Values.global.hostname }}/wts/", "encryption_key": "{{ .Values.encpryption_key | default (randAlphaNum 32 | b64enc) }}", "secret_key": "{{ .Values.secret_key | default (randAlphaNum 32 | b64enc) }}", - "fence_base_url": "https://localhost/user", - "oidc_client_id": "{{ .Values.oidc_client_id | default (randAlphaNum 32) }}", - "oidc_client_secret": "{{ .Values.oidc_client_secret | default (randAlphaNum 32) }}", - "external_oidc": [] - } \ No newline at end of file + "fence_base_url": "https://{{ .Values.global.hostname }}/user", + "external_oidc": {{ default (.Values.secrets.external_oidc | toJson) "[]" }} + } +--- +apiVersion: v1 +kind: Secret +metadata: + name: wts-oidc-client \ No newline at end of file diff --git a/helm/wts/templates/serviceaccount.yaml b/helm/wts/templates/serviceaccount.yaml index cec10794..85b63b11 100644 --- a/helm/wts/templates/serviceaccount.yaml +++ b/helm/wts/templates/serviceaccount.yaml @@ -10,3 +10,30 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} {{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: wts-secrets-role +rules: +- apiGroups: [""] # "" indicates the core API group + resources: ["secrets"] + verbs: ["*"] +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: wts-secrets +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: wts-secrets-rolebinding +subjects: +- kind: ServiceAccount + name: wts-secrets + apiGroup: "" +roleRef: + kind: Role + name: wts-secrets-role + apiGroup: "" diff --git a/helm/wts/templates/wts-oidc.yaml b/helm/wts/templates/wts-oidc.yaml new file mode 100644 index 00000000..721fbaf1 --- /dev/null +++ b/helm/wts/templates/wts-oidc.yaml @@ -0,0 +1,107 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: wts-oidc-job +spec: + template: + metadata: + labels: + app: gen3job + spec: + restartPolicy: OnFailure + serviceAccountName: wts-secrets + volumes: + - name: config-volume + secret: + secretName: "fence-config" + - name: shared-volume + emptyDir: {} + + containers: + - name: fence-client + # TODO: Make this configurable + image: "quay.io/cdis/fence:feat_dbenvvar" + imagePullPolicy: {{ .Values.image.pullPolicy }} + # TODO: ADD RESOURCES + # resources: + command: ["/bin/bash"] + args: + - "-c" + - | + export WTS_HOSTNAME={{ .Values.global.hostname }} + echo "Trying to generate WTS client for hostname : $WTS_HOSTNAME..." + + + + secrets=$(fence-create client-create --client wts --urls "https://${WTS_HOSTNAME}/wts/oauth2/authorize" --username wts --auto-approve | tail -1) + if [[ ! $secrets =~ (\'(.*)\', \'(.*)\') ]]; then + echo "Failed generating oidc client for workspace token service: $secrets" + exit 1 + fi + client_id="${BASH_REMATCH[2]}" + client_secret="${BASH_REMATCH[3]}" + echo client_id: $client_id + echo client_secret: $client_secret + echo -n $client_id > /shared/client_id + echo -n $client_secret > /shared/client_secret + env: + - name: PGHOST + valueFrom: + secretKeyRef: + name: fence-dbcreds + key: host + optional: false + - name: PGUSER + valueFrom: + secretKeyRef: + name: fence-dbcreds + key: username + optional: false + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: fence-dbcreds + key: password + optional: false + - name: PGDB + valueFrom: + secretKeyRef: + name: fence-dbcreds + key: database + optional: false + - name: DB + value: postgresql://$(PGUSER):$(PGPASSWORD)@$(PGHOST):5432/$(PGDB) + - name: PYTHONPATH + value: /var/www/fence + - name: FENCE_PUBLIC_CONFIG + valueFrom: + configMapKeyRef: + name: manifest-fence + key: fence-config-public.yaml + optional: true + volumeMounts: + - name: "shared-volume" + mountPath: "/shared" + - name: "config-volume" + readOnly: true + mountPath: "/var/www/fence/fence-config.yaml" + subPath: fence-config.yaml + - name: kubectl + #TODO: Make this configurable? + image: bitnami/kubectl:latest + volumeMounts: + - name: "shared-volume" + mountPath: "/shared" + command: ["/bin/bash"] + args: + - "-c" + - | + while [ ! -e /shared/client_id ] + do + echo "waiting for /shared/client_id" + sleep 30 + done + echo "Updating k8s secret wts-oidc-client" + CLIENT_ID=$(cat /shared/client_id | base64) + CLIENT_SECRET=$(cat /shared/client_secret | base64) + kubectl patch secret/wts-oidc-client --patch="{\"data\":{\"client_secret\":\"${CLIENT_SECRET}\", \"client_id\":\"${CLIENT_ID}\"}}" \ No newline at end of file diff --git a/helm/wts/values.yaml b/helm/wts/values.yaml index 382f9980..bcd0dc43 100644 --- a/helm/wts/values.yaml +++ b/helm/wts/values.yaml @@ -1,45 +1,54 @@ +# Default values for wts. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. global: - # Default values are for postgres deployed as a helm chart + dev: true postgres: - host: postgres-postgresql.postgres.svc.cluster.local + db_create: true master: + host: username: postgres - password: - port: 5432 - + password: + port: "5432" + environment: default + hostname: localhost + revproxyArn: arn:aws:acm:us-east-1:123456:certificate + dictionaryUrl: https://s3.amazonaws.com/dictionary-artifacts/datadictionary/develop/schema.json + portalApp: gitops + kubeBucket: kube-gen3 + logsBucket: logs-gen3 + syncFromDbgap: false + userYamlS3Path: s3://cdis-gen3-users/test/user.yaml + publicDataSets: true + tierAccessLevel: libre + netPolicy: true + dispatcherJobNum: 10 + ddEnabled: false -# Whether or not to run database creation job -# The job is idempotant -db_creation: true postgres: - # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you + db_create: + # If db does not exist in postgres cluster and db_creation is set ot true then these databases will be created for you database: wts username: wts + port: "5432" # If left empty it will be auto-generated - password: - - -# Default values for wts. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. + password: replicaCount: 1 image: - repository: quay.io/cdis/wts - pullPolicy: Never + repository: quay.io/cdis/workspace-token-service + pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. - tag: "jqtest" + tag: "feat_wts_internalfence" imagePullSecrets: [] nameOverride: "" fullnameOverride: "" - - -hostname: localhost -oidc_client_id: -oidc_client_secret: +hostname: +oidc_client_id: +oidc_client_secret: serviceAccount: # Specifies whether a service account should be created @@ -56,9 +65,7 @@ podLabels: netnolimit: "yes" userhelper: "yes" tags.datadoghq.com/service: "token-service" - #GEN3_DATE_LABEL - #GEN3_WTS_VERSION - #GEN3_ENV_LABEL + podAnnotations: {} @@ -79,7 +86,7 @@ service: httpPort: 80 httpsPort: 443 -resources: +resources: requests: cpu: 0.1 memory: 12Mi @@ -105,6 +112,16 @@ roleName: workspace-token-service release: production secrets: + external_oidc: + # - base_url: + # oidc_client_id: + # oidc_client_secret: + # login_options: + # example-google-login: + # name: + # params: + # idp: + # wts-g3auto: # appcreds.json: | # { @@ -123,4 +140,3 @@ secrets: # "db_passwurd": "WTS_DB_PWD.REPLACE", # "db_database": "wts_default" # } - diff --git a/wip/acronymbot/README.md b/wip/acronymbot/README.md new file mode 100644 index 00000000..63a37446 --- /dev/null +++ b/wip/acronymbot/README.md @@ -0,0 +1,47 @@ +# acronymbot + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.16.0](https://img.shields.io/badge/AppVersion-1.16.0-informational?style=flat-square) + +A Helm chart for gen3 acronymbot + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"nginx"` | | +| image.tag | string | `""` | | +| imagePullSecrets | list | `[]` | | +| ingress.annotations | object | `{}` | | +| ingress.className | string | `""` | | +| ingress.enabled | bool | `false` | | +| ingress.hosts[0].host | string | `"chart-example.local"` | | +| ingress.hosts[0].paths[0].path | string | `"/"` | | +| ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | | +| ingress.tls | list | `[]` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | | +| podSecurityContext | object | `{}` | | +| replicaCount | int | `1` | | +| resources | object | `{}` | | +| secrets.github.key | string | `""` | | +| secrets.github.name | string | `""` | | +| secrets.slack.key | string | `""` | | +| secrets.slack.name | string | `""` | | +| securityContext | object | `{}` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| tolerations | list | `[]` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/wip/auspice/.helmignore b/wip/auspice/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/wip/auspice/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/wip/auspice/Chart.yaml b/wip/auspice/Chart.yaml new file mode 100644 index 00000000..a55cc856 --- /dev/null +++ b/wip/auspice/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: auspice +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/wip/auspice/README.md b/wip/auspice/README.md new file mode 100644 index 00000000..9f139584 --- /dev/null +++ b/wip/auspice/README.md @@ -0,0 +1,45 @@ +# auspice + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.16.0](https://img.shields.io/badge/AppVersion-1.16.0-informational?style=flat-square) + +A Helm chart for Kubernetes + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].key | string | `"app"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].operator | string | `"In"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.labelSelector.matchExpressions[0].values[0] | string | `"portal"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].podAffinityTerm.topologyKey | string | `"kubernetes.io/hostname"` | | +| affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution[0].weight | int | `100` | | +| automountServiceAccountToken | bool | `false` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"nginx"` | | +| imagePullSecrets | list | `[]` | | +| labels.public | string | `"yes"` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | | +| podSecurityContext | object | `{}` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | float | `1` | | +| resources.limits.memory | string | `"2400Mi"` | | +| resources.requests.cpu | float | `0.5` | | +| resources.requests.memory | string | `"1024Mi"` | | +| securityContext | object | `{}` | | +| selectorLabels.app | string | `"auspice"` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| tolerations | list | `[]` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/wip/auspice/templates/NOTES.txt b/wip/auspice/templates/NOTES.txt new file mode 100644 index 00000000..37256963 --- /dev/null +++ b/wip/auspice/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "auspice.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "auspice.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "auspice.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "auspice.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/wip/auspice/templates/_helpers.tpl b/wip/auspice/templates/_helpers.tpl new file mode 100644 index 00000000..ce8c8ac2 --- /dev/null +++ b/wip/auspice/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "auspice.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "auspice.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "auspice.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "auspice.labels" -}} +helm.sh/chart: {{ include "auspice.chart" . }} +{{ include "auspice.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "auspice.selectorLabels" -}} +app.kubernetes.io/name: {{ include "auspice.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "auspice.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "auspice.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/wip/auspice/templates/deployment.yaml b/wip/auspice/templates/deployment.yaml new file mode 100644 index 00000000..17ca4b66 --- /dev/null +++ b/wip/auspice/templates/deployment.yaml @@ -0,0 +1,63 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: auspice-deployment +spec: + selector: + {{- with .Values.selectorLabels }} + matchLabels: + {{- toYaml . | nindent 8 }} + {{- end }} + revisionHistoryLimit: 2 + strategy: + {{- toYaml .Values.strategy | nindent 8 }} + template: + metadata: + {{- with .Values.labels }} + labels: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.selectorLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + automountServiceAccountToken: {{ .Values.automountServiceAccountToken}} + containers: + - name: auspice + image: "quay.io/cdis/gen3-auspice:master" + imagePullPolicy: Always + command: + - /bin/sh + - ./dockerStart.sh + env: + - name: HOST + value: "0.0.0.0" + - name: MAPBOX_API_TOKEN + # Optional token for mapbox api + valueFrom: + configMapKeyRef: + name: global + key: mapbox_token + optional: true + livenessProbe: + httpGet: + path: / + port: 4000 + initialDelaySeconds: 30 + periodSeconds: 60 + timeoutSeconds: 30 + readinessProbe: + httpGet: + path: / + port: 4000 + ports: + - name: http + containerPort: 4000 + protocol: TCP + resources: + {{- toYaml .Values.resources | nindent 12 }} + diff --git a/wip/auspice/templates/hpa.yaml b/wip/auspice/templates/hpa.yaml new file mode 100644 index 00000000..e2fc0fad --- /dev/null +++ b/wip/auspice/templates/hpa.yaml @@ -0,0 +1,28 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "auspice.fullname" . }} + labels: + {{- include "auspice.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "auspice.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/wip/auspice/templates/service.yaml b/wip/auspice/templates/service.yaml new file mode 100644 index 00000000..3bb771aa --- /dev/null +++ b/wip/auspice/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "auspice.fullname" . }} + labels: + {{- include "auspice.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "auspice.selectorLabels" . | nindent 4 }} diff --git a/wip/auspice/templates/serviceaccount.yaml b/wip/auspice/templates/serviceaccount.yaml new file mode 100644 index 00000000..51b30c8a --- /dev/null +++ b/wip/auspice/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "auspice.serviceAccountName" . }} + labels: + {{- include "auspice.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/wip/auspice/templates/tests/test-connection.yaml b/wip/auspice/templates/tests/test-connection.yaml new file mode 100644 index 00000000..a6f74f0e --- /dev/null +++ b/wip/auspice/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "auspice.fullname" . }}-test-connection" + labels: + {{- include "auspice.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "auspice.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/wip/auspice/values.yaml b/wip/auspice/values.yaml new file mode 100644 index 00000000..26d07727 --- /dev/null +++ b/wip/auspice/values.yaml @@ -0,0 +1,82 @@ +# Default values for auspice. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. +# tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # 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: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + + +selectorLabels: + app: auspice + +labels: + public: "yes" + +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - portal + topologyKey: "kubernetes.io/hostname" + +automountServiceAccountToken: false + +resources: + requests: + cpu: 0.5 + memory: 1024Mi + limits: + cpu: 1.0 + memory: 2400Mi diff --git a/wip/cogwheel/Chart.yaml b/wip/cogwheel/Chart.yaml index 87fb8367..8f797a45 100644 --- a/wip/cogwheel/Chart.yaml +++ b/wip/cogwheel/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.1 +version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/wip/cogwheel/README.md b/wip/cogwheel/README.md new file mode 100644 index 00000000..efd46ff1 --- /dev/null +++ b/wip/cogwheel/README.md @@ -0,0 +1,81 @@ +# cogwheel + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 2022.10](https://img.shields.io/badge/AppVersion-2022.10-informational?style=flat-square) + +A Helm chart for gen3 cogwheel + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"quay.io/cdis/cogwheel"` | | +| image.tag | string | `""` | | +| imagePullSecrets | list | `[]` | | +| ingress.annotations | object | `{}` | | +| ingress.className | string | `""` | | +| ingress.enabled | bool | `false` | | +| ingress.hosts[0].host | string | `"chart-example.local"` | | +| ingress.hosts[0].paths[0].path | string | `"/"` | | +| ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | | +| ingress.tls | list | `[]` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | | +| podSecurityContext | object | `{}` | | +| replicaCount | int | `1` | | +| resources.limits.cpu | string | `"1000m"` | | +| resources.limits.memory | string | `"1Gi"` | | +| resources.requests.cpu | string | `"10m"` | | +| resources.requests.memory | string | `"128Mi"` | | +| securityContext | object | `{}` | | +| service.port | int | `80` | | +| service.type | string | `"ClusterIP"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `false` | | +| serviceAccount.name | string | `""` | | +| tolerations | list | `[]` | | +| volumeMounts[0].mountPath | string | `"/etc/shibboleth/sp-encrypt-cert.pem"` | | +| volumeMounts[0].name | string | `"cogwheel-g3auto"` | | +| volumeMounts[0].subPath | string | `"sp-encrypt-cert.pem"` | | +| volumeMounts[10].mountPath | string | `"/etc/cogwheel/rsa/publickey.pem"` | | +| volumeMounts[10].name | string | `"cogwheel-g3auto"` | | +| volumeMounts[10].subPath | string | `"rsa_publickey.pem"` | | +| volumeMounts[1].mountPath | string | `"/etc/shibboleth/sp-encrypt-key.pem"` | | +| volumeMounts[1].name | string | `"cogwheel-g3auto"` | | +| volumeMounts[1].subPath | string | `"sp-encrypt-key.pem"` | | +| volumeMounts[2].mountPath | string | `"/etc/shibboleth/sp-signing-cert.pem"` | | +| volumeMounts[2].name | string | `"cogwheel-g3auto"` | | +| volumeMounts[2].subPath | string | `"sp-signing-cert.pem"` | | +| volumeMounts[3].mountPath | string | `"/etc/shibboleth/sp-signing-key.pem"` | | +| volumeMounts[3].name | string | `"cogwheel-g3auto"` | | +| volumeMounts[3].subPath | string | `"sp-signing-key.pem"` | | +| volumeMounts[4].mountPath | string | `"/etc/shibboleth/mdqsigner.pem"` | | +| volumeMounts[4].name | string | `"cogwheel-g3auto"` | | +| volumeMounts[4].subPath | string | `"mdqsigner.pem"` | | +| volumeMounts[5].mountPath | string | `"/etc/shibboleth/shibboleth2.xml"` | | +| volumeMounts[5].name | string | `"cogwheel-g3auto"` | | +| volumeMounts[5].subPath | string | `"shibboleth2.xml"` | | +| volumeMounts[6].mountPath | string | `"/etc/httpd/conf.d/ssl.conf"` | | +| volumeMounts[6].name | string | `"cogwheel-g3auto"` | | +| volumeMounts[6].subPath | string | `"ssl.conf"` | | +| volumeMounts[7].mountPath | string | `"/etc/cogwheel/wsgi_settings.py"` | | +| volumeMounts[7].name | string | `"cogwheel-g3auto"` | | +| volumeMounts[7].subPath | string | `"wsgi_settings.py"` | | +| volumeMounts[8].mountPath | string | `"/etc/cogwheel/oauth2_metadata.json"` | | +| volumeMounts[8].name | string | `"cogwheel-g3auto"` | | +| volumeMounts[8].subPath | string | `"oauth2_metadata.json"` | | +| volumeMounts[9].mountPath | string | `"/etc/cogwheel/rsa/privatekey.pem"` | | +| volumeMounts[9].name | string | `"cogwheel-g3auto"` | | +| volumeMounts[9].subPath | string | `"rsa_privatekey.pem"` | | +| volumes[0].name | string | `"cogwheel-g3auto"` | | +| volumes[0].secret.secretName | string | `"cogwheel-g3auto"` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0)