From 5f9e482b9f1fec9e0836b688a5caf5ff5dc0cf12 Mon Sep 17 00:00:00 2001 From: Leo J <153937047+leiicamundi@users.noreply.github.com> Date: Wed, 22 May 2024 09:21:23 +0200 Subject: [PATCH] feat: init (#1) --- .github/actions/rosa-create-cluster/README.md | 67 +++++++ .../actions/rosa-create-cluster/action.yml | 106 ++++++++---- .github/actions/rosa-delete-cluster/README.md | 44 +++++ .../actions/rosa-delete-cluster/action.yml | 54 +++++- .github/labeler.yml | 17 ++ .github/markdown-links.json | 20 --- .github/renovate.json5 | 5 + .github/workflows/labeler.yml | 13 ++ .github/workflows/links.yml | 40 +++++ .github/workflows/lint.yml | 1 - .github/workflows/tests.yml | 66 +++++-- .lint/terraform_docs/.terraform-docs.yml | 42 +++++ .lint/tflint/.tflint.hcl | 25 +++ .pre-commit-config.yaml | 16 +- .tool-versions | 12 +- DEVELOPER.md | 62 +++++++ LICENSE | 14 ++ README.md | 163 +++++++++++++++--- lychee-links.toml | 19 ++ modules/rosa-hcp/vars.tf | 2 +- 20 files changed, 676 insertions(+), 112 deletions(-) create mode 100644 .github/actions/rosa-create-cluster/README.md create mode 100644 .github/actions/rosa-delete-cluster/README.md create mode 100644 .github/labeler.yml delete mode 100644 .github/markdown-links.json create mode 100644 .github/renovate.json5 create mode 100644 .github/workflows/labeler.yml create mode 100644 .github/workflows/links.yml create mode 100644 .lint/terraform_docs/.terraform-docs.yml create mode 100644 .lint/tflint/.tflint.hcl create mode 100644 DEVELOPER.md create mode 100644 LICENSE create mode 100644 lychee-links.toml diff --git a/.github/actions/rosa-create-cluster/README.md b/.github/actions/rosa-create-cluster/README.md new file mode 100644 index 0000000..c7c864a --- /dev/null +++ b/.github/actions/rosa-create-cluster/README.md @@ -0,0 +1,67 @@ +# Deploy ROSA HCP Cluster GitHub Action + +This GitHub Action automates the deployment of a ROSA (Red Hat OpenShift Service on AWS) cluster using Terraform. It also installs `oc`, `awscli`, and `rosa` CLI tools. + +## Inputs + +| Input | Description | Required | Default | +|---------------------|--------------------------------------------------------------|----------|------------------| +| `rh-token` | Red Hat Hybrid Cloud Console Token | true | | +| `cluster-name` | Name of the ROSA cluster to deploy | true | | +| `admin-password` | Admin password for the ROSA cluster | true | | +| `admin-username` | Admin username for the ROSA cluster | false | `cluster-admin` | +| `aws-region` | AWS region where the ROSA cluster will be deployed | true | | +| `rosa-cli-version` | Version of the ROSA CLI to use | false | `latest` | +| `awscli-version` | Version of the AWS CLI to use | false | __see `action.yml`__ | +| `openshift-version` | Version of the OpenShift to install | false | __see `action.yml`__ | +| `replicas` | Number of replicas for the ROSA cluster | false | `2` | +| `s3-backend-bucket` | Name of the S3 bucket to store Terraform state | true | | +| `tf-modules-revision`| Git revision of the Terraform modules to use | false | `main` | +| `tf-modules-path` | Path where the Terraform ROSA modules will be cloned | false | `./.action-tf-modules/rosa/` | +| `login` | Authenticate the current kube context on the created cluster | false | `true` | +| `tf-cli-config-credentials-hostname` | The hostname of a HCP Terraform/Terraform Enterprise instance to place within the credentials block of the Terraform CLI configuration file. Defaults to `app.terraform.io`. | false | `app.terraform.io` | +| `tf-cli-config-credentials-token` | The API token for a HCP Terraform/Terraform Enterprise instance to place within the credentials block of the Terraform CLI configuration file. | false | | +| `tf-terraform-version` | The version of Terraform CLI to install. Defaults to `latest`. | false | `latest` | +| `tf-terraform-wrapper` | Whether or not to install a wrapper to wrap subsequent calls of the `terraform` binary and expose its STDOUT, STDERR, and exit code as outputs named `stdout`, `stderr`, and `exitcode` respectively. Defaults to `true`. | false | `true` | + +## Outputs + +| Output | Description | +|--------------------------|------------------------------------------------------------| +| `openshift-server-api` | The server API URL of the deployed ROSA cluster | +| `openshift-cluster-id` | The ID of the deployed ROSA cluster | +| `terraform-state-url` | URL of the Terraform state file in the S3 bucket | + +## Usage + +This action is idempotent and can be re-run without affecting the existing cluster, following the principles of Terraform. + +Create a file in your repository's `.github/workflows` directory, for example `deploy-rosa-hcp.yml`, with the following content: + +```yaml +name: Deploy ROSA HCP Cluster + +on: + pull_request: + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Add profile credentials to ~/.aws/credentials + run: | + aws configure set aws_access_key_id ${{ secrets.AWS_ACCESS_KEY }} --profile ${{ env.AWS_PROFILE }} + aws configure set aws_secret_access_key ${{ secrets.AWS_SECRET_KEY }} --profile ${{ env.AWS_PROFILE }} + aws configure set region ${{ env.AWS_REGION }} --profile ${{ env.AWS_PROFILE }} + + - name: Deploy ROSA HCP Cluster + uses: camunda/camunda-tf-rosa/.github/actions/rosa-create-cluster@main + id: create_cluster + with: + rh-token: ${{ secrets.RH_OPENSHIFT_TOKEN }} + cluster-name: "my-ocp-cluster" + admin-username: "cluster-admin" + admin-password: ${{ secrets.CI_OPENSHIFT_MAIN_PASSWORD }} + aws-region: "us-west-2" + s3-backend-bucket: ${{ secrets.TF_S3_BUCKET }} +``` diff --git a/.github/actions/rosa-create-cluster/action.yml b/.github/actions/rosa-create-cluster/action.yml index 5b59e4a..7925a9f 100644 --- a/.github/actions/rosa-create-cluster/action.yml +++ b/.github/actions/rosa-create-cluster/action.yml @@ -1,9 +1,9 @@ name: Deploy ROSA HCP Cluster description: | - This GitHub Action automates the deployment of a ROSA (Red Hat OpenShift Service on AWS) cluster using Terraform with a dedicated namespace. + This GitHub Action automates the deployment of a ROSA (Red Hat OpenShift Service on AWS) cluster using Terraform. This action will also install oc, awscli, rosa cli. - This action also set the current kube context on the created namespace. + The kube context will be set on the created cluster. inputs: rh-token: @@ -17,14 +17,11 @@ inputs: required: true admin-username: description: 'Admin username for the ROSA cluster' - default: "kubeadmin" + default: "cluster-admin" required: true aws-region: description: 'AWS region where the ROSA cluster will be deployed' required: true - namespace: - description: 'Namespace to create in the ROSA cluster' - required: true rosa-cli-version: description: 'Version of the ROSA CLI to use' required: true @@ -32,14 +29,12 @@ inputs: awscli-version: description: 'Version of the aws cli to use' required: true - default: "1.32.105" # TODO: for all versions, update default one with renovate - oc-version: - description: 'Version of the oc cli to install' - required: true - default: "latest" + # renovate: datasource=github-releases depName=aws/aws-cli + default: "2.15.52" openshift-version: description: 'Version of the OpenShift to install' required: true + # renovate: datasource=endoflife-date depName=red-hat-openshift versioning=semver default: "4.15.11" replicas: description: 'Number of replicas for the ROSA cluster' @@ -56,11 +51,32 @@ inputs: description: 'Path where the tf rosa modules will be cloned' default: './.action-tf-modules/rosa/' required: true + login: + description: 'Authenticate the current kube context on the created cluster' + default: "true" + required: true + + # inherited from https://github.com/hashicorp/setup-terraform/blob/main/action.yml + tf-cli-config-credentials-hostname: + description: 'The hostname of a HCP Terraform/Terraform Enterprise instance to place within the credentials block of the Terraform CLI configuration file. Defaults to `app.terraform.io`.' + default: 'app.terraform.io' + required: false + tf-cli-config-credentials-token: + description: 'The API token for a HCP Terraform/Terraform Enterprise instance to place within the credentials block of the Terraform CLI configuration file.' + required: false + tf-terraform-version: + description: 'The version of Terraform CLI to install. Instead of full version string you can also specify constraint string starting with "<" (for example `<1.13.0`) to install the latest version satisfying the constraint. A value of `latest` will install the latest version of Terraform CLI. Defaults to `latest`.' + default: 'latest' + required: false + tf-terraform-wrapper: + description: 'Whether or not to install a wrapper to wrap subsequent calls of the `terraform` binary and expose its STDOUT, STDERR, and exit code as outputs named `stdout`, `stderr`, and `exitcode` respectively. Defaults to `true`.' + default: 'true' + required: false outputs: openshift-server-api: description: 'The server API URL of the deployed ROSA cluster' - value: ${{ steps.kube_config.outputs.cluster_api }} + value: ${{ steps.cluster_info.outputs.cluster_api }} openshift-cluster-id: description: 'The ID of the deployed ROSA cluster' @@ -79,15 +95,22 @@ runs: curl -O "https://mirror.openshift.com/pub/openshift-v4/clients/rosa/${{ inputs.rosa-cli-version }}/rosa-linux.tar.gz" tar -xvf rosa-linux.tar.gz sudo mv rosa /usr/local/bin/rosa + chmod +x /usr/local/bin/rosa + rm -f rosa-linux.tar.gz rosa version - name: Install Terraform - uses: hashicorp/setup-terraform@v3 + uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3 + with: + cli_config_credentials_hostname: ${{ inputs.tf-cli-config-credentials-hostname }} + cli_config_credentials_token: ${{ inputs.tf-cli-config-credentials-token }} + terraform_version: ${{ inputs.tf-terraform-version }} + terraform_wrapper: ${{ inputs.tf-terraform-wrapper }} - - name: Install oc CLI - uses: redhat-actions/oc-installer@v1 + - name: Install CLI tools from OpenShift Mirror + uses: redhat-actions/openshift-tools-installer@2de9a80cf012ad0601021515481d433b91ef8fd5 # v1 with: - oc_version: ${{ inputs.oc-version }} + oc: "${{ inputs.openshift-version }}" - name: Login to Red Hat Hybrid Cloud Console shell: bash @@ -102,10 +125,15 @@ runs: rosa verify permissions --region="${{ inputs.aws-region }}" rosa create account-roles --mode auto - - name: Install aws-cli + - name: Install aws-cli v2 shell: bash run: | - python3 -m pip install "awscli==${{ inputs.awscli-version }}" + sudo rm -rf /usr/local/aws-cli + mkdir -p /tmp/awscli && cd /tmp/awscli + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64-${{ inputs.awscli-version }}.zip" -o "awscliv2.zip" + unzip -qq awscliv2.zip + sudo ./aws/install + cd - && rm -Rf /tmp/awscli - name: Check if S3 bucket exists id: create-s3-bucket @@ -135,17 +163,19 @@ runs: echo "terraform-state-url=${terraform_state_url}" >> "$GITHUB_OUTPUT" - name: Checkout Repository rosa modules - uses: actions/checkout@v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 with: repository: "camunda/camunda-tf-rosa" ref: ${{ inputs.tf-modules-revision }} path: ${{ inputs.tf-modules-path }} + fetch-depth: 0 - name: Terraform Init shell: bash id: init working-directory: "${{ inputs.tf-modules-path }}/modules/rosa-hcp/" run: | + terraform version terraform init -backend-config="bucket=${{ steps.set-terraform-variables.outputs.TFSTATE_BUCKET }}" -backend-config="key=${{ steps.set-terraform-variables.outputs.TFSTATE_KEY }}" -backend-config="region=${{ steps.set-terraform-variables.outputs.TFSTATE_REGION }}" terraform validate -no-color @@ -171,23 +201,29 @@ runs: id: cluster_info run: | rosa describe cluster --output=json -c "${{ steps.apply.outputs.cluster_id }}" + export cluster_api=$(rosa describe cluster --output=json -c "${{ steps.apply.outputs.cluster_id }}" | jq -r '.api.url') + echo "cluster_api=$cluster_api" + echo "cluster_api=$cluster_api" >> "$GITHUB_OUTPUT" - - name: Generate kubeconfig - shell: bash + - name: Login and generate kubeconfig + # we need to retry due as the cluster has just been created and the OIDC provider may not be available yet + uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3 id: kube_config - run: | - export server_api=$(rosa describe cluster --output=json -c "${{ steps.apply.outputs.cluster_id }}" | jq -r '.api.url') - echo "server_api=$server_api" >> "$GITHUB_OUTPUT" - - oc login --username "${{ inputs.admin-username }}" --password "${{ inputs.admin-password }}" --server=$server_api - kubectl config rename-context $(oc config current-context) "${{ inputs.cluster-name }}" - kubectl config use "${{ inputs.cluster-name }}" - - - name: Create namespace if not exists + if: inputs.login == 'true' + with: + timeout_minutes: 10 + max_attempts: 40 + shell: bash + retry_wait_seconds: 15 + command: | + oc login --username "${{ inputs.admin-username }}" --password "${{ inputs.admin-password }}" "${{ steps.cluster_info.outputs.cluster_api }}" + oc whoami + + kubectl config rename-context $(oc config current-context) "${{ inputs.cluster-name }}" + kubectl config use "${{ inputs.cluster-name }}" + + - name: Clean up cloned modules + if: always() shell: bash run: | - if ! oc get namespace "${{ inputs.namespace }}"; then - oc new-project "${{ inputs.namespace }}" - else - echo "Namespace '${{ inputs.namespace }}' already exists" - fi + rm -rf "${{ inputs.tf-modules-path }}" diff --git a/.github/actions/rosa-delete-cluster/README.md b/.github/actions/rosa-delete-cluster/README.md new file mode 100644 index 0000000..797a8d1 --- /dev/null +++ b/.github/actions/rosa-delete-cluster/README.md @@ -0,0 +1,44 @@ +# Delete ROSA HCP Cluster GitHub Action + +This GitHub Action automates the deletion of a ROSA (Red Hat OpenShift Service on AWS) cluster using Terraform. It also installs `awscli`. + +## Inputs + +| Input | Description | Required | Default | +|----------------------|----------------------------------------------------------|----------|--------------------------------| +| `rh-token` | Red Hat Hybrid Cloud Console Token | true | | +| `cluster-name` | Name of the ROSA cluster to delete | true | | +| `aws-region` | AWS region where the ROSA cluster is deployed | true | | +| `s3-backend-bucket` | Name of the S3 bucket where the Terraform state is stored| true | | +| `awscli-version` | Version of the aws cli to use | false | __see `action.yml`__ | +| `tf-modules-revision`| Git revision of the tf modules to use | false | `main` | +| `tf-modules-path` | Path where the tf rosa modules will be cloned | false | `./.action-tf-modules/rosa/` | +| `tf-cli-config-credentials-hostname` | The hostname of a HCP Terraform/Terraform Enterprise instance to place within the credentials block of the Terraform CLI configuration file. Defaults to `app.terraform.io`. | false | `app.terraform.io` | +| `tf-cli-config-credentials-token` | The API token for a HCP Terraform/Terraform Enterprise instance to place within the credentials block of the Terraform CLI configuration file. | false | | +| `tf-terraform-version` | The version of Terraform CLI to install. Defaults to `latest`. | false | `latest` | +| `tf-terraform-wrapper` | Whether or not to install a wrapper to wrap subsequent calls of the `terraform` binary and expose its STDOUT, STDERR, and exit code as outputs named `stdout`, `stderr`, and `exitcode` respectively. Defaults to `true`. | false | `true` | + +## Usage + +For this destruction action, it is not necessary to have called the creation action just before, as the state will be retrieved via the bucket. + +Create a file in your repository's `.github/workflows` directory, for example `delete-rosa-hcp.yml`, with the following content: + +```yaml +name: Delete ROSA HCP Cluster + +on: + pull_request: + +jobs: + delete: + runs-on: ubuntu-latest + steps: + - name: Delete ROSA HCP Cluster + uses: camunda/camunda-tf-rosa/.github/actions/rosa-delete-cluster@main + with: + rh-token: ${{ secrets.RH_OPENSHIFT_TOKEN }} + cluster-name: "my-ocp-cluster" + aws-region: "us-west-2" + s3-backend-bucket: ${{ secrets.TF_S3_BUCKET }} +``` diff --git a/.github/actions/rosa-delete-cluster/action.yml b/.github/actions/rosa-delete-cluster/action.yml index 00697d6..032b597 100644 --- a/.github/actions/rosa-delete-cluster/action.yml +++ b/.github/actions/rosa-delete-cluster/action.yml @@ -2,7 +2,7 @@ name: Delete ROSA HCP Cluster description: | This GitHub Action automates the deletion of a ROSA (Red Hat OpenShift Service on AWS) cluster using Terraform. - This action will also uninstall oc, awscli, rosa cli. + This action will also install awscli. inputs: rh-token: @@ -20,7 +20,8 @@ inputs: awscli-version: description: 'Version of the aws cli to use' required: true - default: "1.32.105" + # renovate: datasource=github-releases depName=aws/aws-cli + default: "2.15.52" tf-modules-revision: description: 'Git revision of the tf modules to use' default: 'main' @@ -30,11 +31,43 @@ inputs: default: './.action-tf-modules/rosa/' required: true + # inherited from https://github.com/hashicorp/setup-terraform/blob/main/action.yml + tf-cli-config-credentials-hostname: + description: 'The hostname of a HCP Terraform/Terraform Enterprise instance to place within the credentials block of the Terraform CLI configuration file. Defaults to `app.terraform.io`.' + default: 'app.terraform.io' + required: false + tf-cli-config-credentials-token: + description: 'The API token for a HCP Terraform/Terraform Enterprise instance to place within the credentials block of the Terraform CLI configuration file.' + required: false + tf-terraform-version: + description: 'The version of Terraform CLI to install. Instead of full version string you can also specify constraint string starting with "<" (for example `<1.13.0`) to install the latest version satisfying the constraint. A value of `latest` will install the latest version of Terraform CLI. Defaults to `latest`.' + default: 'latest' + required: false + tf-terraform-wrapper: + description: 'Whether or not to install a wrapper to wrap subsequent calls of the `terraform` binary and expose its STDOUT, STDERR, and exit code as outputs named `stdout`, `stderr`, and `exitcode` respectively. Defaults to `true`.' + default: 'true' + required: false + runs: using: 'composite' steps: - name: Install Terraform - uses: hashicorp/setup-terraform@v3 + uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3 + with: + cli_config_credentials_hostname: ${{ inputs.tf-cli-config-credentials-hostname }} + cli_config_credentials_token: ${{ inputs.tf-cli-config-credentials-token }} + terraform_version: ${{ inputs.tf-terraform-version }} + terraform_wrapper: ${{ inputs.tf-terraform-wrapper }} + + - name: Install aws-cli v2 + shell: bash + run: | + sudo rm -rf /usr/local/aws-cli + mkdir -p /tmp/awscli && cd /tmp/awscli + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64-${{ inputs.awscli-version }}.zip" -o "awscliv2.zip" + unzip -qq awscliv2.zip + sudo ./aws/install + cd - && rm -Rf /tmp/awscli - name: Set Terraform variables shell: bash @@ -48,17 +81,19 @@ runs: echo "TFSTATE_KEY=${TFSTATE_KEY}" >> "$GITHUB_OUTPUT" - name: Checkout Repository rosa modules - uses: actions/checkout@v4 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 with: repository: "camunda/camunda-tf-rosa" ref: ${{ inputs.tf-modules-revision }} path: ${{ inputs.tf-modules-path }} + fetch-depth: 0 - name: Terraform Init shell: bash id: init working-directory: "${{ inputs.tf-modules-path }}/modules/rosa-hcp/" run: | + terraform version terraform init -backend-config="bucket=${{ steps.set-terraform-variables.outputs.TFSTATE_BUCKET }}" -backend-config="key=${{ steps.set-terraform-variables.outputs.TFSTATE_KEY }}" -backend-config="region=${{ steps.set-terraform-variables.outputs.TFSTATE_REGION }}" terraform validate -no-color @@ -75,3 +110,14 @@ runs: working-directory: "${{ inputs.tf-modules-path }}/modules/rosa-hcp/" run: | terraform apply -destroy -no-color rosa-destroy.plan + + - name: Clean up cloned modules + shell: bash + if: always() + run: | + rm -rf "${{ inputs.tf-modules-path }}" + + - name: Delete Terraform State + shell: bash + run: | + aws s3 rm s3://${{ steps.set-terraform-variables.outputs.TFSTATE_BUCKET }}/${{ steps.set-terraform-variables.outputs.TFSTATE_KEY }} diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..c0978e3 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,17 @@ +# Add 'feature' label to any PR where the head branch name starts with `feature` or has a `feature` section in the name +feature: + - head-branch: ['^feature', 'feature'] + +# Add 'test' label to any changes within 'test' folder or any subfolders +test: + - changed-files: + - any-glob-to-any-file: + - test/**.go + - test/**/go.mod + - modules/fixtures/** + +terraform: + - changed-files: + - any-glob-to-any-file: + - modules/**.tf + - .tool-versions diff --git a/.github/markdown-links.json b/.github/markdown-links.json deleted file mode 100644 index 6d17351..0000000 --- a/.github/markdown-links.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "projectBaseUrl":"${workspaceFolder}", - "ignorePatterns": [ - { - "pattern": "^http(s?)://localhost" - }, - { - "pattern": "^#" - } - ], - "replacementPatterns": [ - ], - "httpHeaders": [ - ], - "timeout": "20s", - "retryOn429": true, - "retryCount": 5, - "fallbackRetryDelay": "30s", - "aliveStatusCodes": [200, 206] -} diff --git a/.github/renovate.json5 b/.github/renovate.json5 new file mode 100644 index 0000000..57f041c --- /dev/null +++ b/.github/renovate.json5 @@ -0,0 +1,5 @@ +{ + $schema: "https://docs.renovatebot.com/renovate-schema.json", + extends: ["github>camunda/infraex-common-config:default.json5"], + groupName: "mono-update-renovate", // we keep all updates in a single renovate branch in order to save CI tests +} diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000..907942e --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,13 @@ +name: "Pull Request Labeler" +on: + pull_request_target: + schedule: + - cron: "0 1 * * 1" +jobs: + labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5 diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml new file mode 100644 index 0000000..79d7d9b --- /dev/null +++ b/.github/workflows/links.yml @@ -0,0 +1,40 @@ +name: Check external links + +on: + push: + workflow_dispatch: + schedule: + - cron: "0 3 1 * *" + +jobs: + lint: + name: links-check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 + + - name: Get Current Timestamp + id: timestamp + run: echo "TIMESTAMP=$(date +%s)" >> "$GITHUB_ENV" + + - name: Restore lychee cache + uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3 + with: + path: .lycheecache + key: "cache-lychee-${{ env.TIMESTAMP }}" + restore-keys: cache-lychee- + + - name: Link Checker + uses: lycheeverse/lychee-action@2b973e86fc7b1f6b36a93795fe2c9c6ae1118621 # v1.10.0 + with: + fail: true + args: -c ./lychee-links.toml --base . --cache --max-cache-age 1d . --verbose --no-progress '*.md' './**/*.md' + token: "${{ secrets.GITHUB_TOKEN }}" + + - name: Create Issue From File + if: ${{ github.event_name == 'schedule' && env.lychee_exit_code != 0 }} + uses: peter-evans/create-issue-from-file@433e51abf769039ee20ba1293a088ca19d573b7f # v4 + with: + title: Link Checker Report + content-filepath: ./lychee/out.md + labels: report, automated issue diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 161b6a1..19655f6 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -6,7 +6,6 @@ on: push: workflow_dispatch: -# TODO: copy lint logic of eks repo jobs: lint: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 405a597..003c6e8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,9 +1,31 @@ --- name: Cluster creation and destruction test -# TODO: align this with EKS current strategy on: - push: + schedule: + - cron: '0 1 * * 1' # At 01:00 on Monday. + + workflow_dispatch: + inputs: + cluster_name: + description: "Cluster name." + required: false + type: string + delete_cluster: + description: "Whether to delete the cluster." + required: false + type: boolean + default: true + + pull_request: + # the paths should be synced with ../labeler.yml + paths: + - modules/fixtures/**/*.tf + - modules/**.tf + - .tool-versions + - .github/workflows/tests.yml + - .github/actions/**/*.yml + - justfile # limit to a single execution per actor of this workflow concurrency: @@ -13,15 +35,12 @@ env: AWS_PROFILE: "infex" AWS_REGION: "eu-west-2" TF_S3_BUCKET: "camunda-tf-rosa" - CLUSTER_NAME: "mycluster" + OCP_ADMIN_USERNAME: "cluster-admin" + OCP_NAMESPACE: "myns" jobs: - # TODO: implement same logic as EKS - # We can skip some tests using the commit description (skip-tests:NameOfTest1,NameOfTest2) or all tests (skip-tests:all) (see `DEVELOPER.md`) - # If all tests are skipped, the result of this workflow will be `failed` on purpose - # If you want to skip tests and have no error, you need to use `testing-ci-not-necessary` as a label on the PR - configure-tests: + action-test: runs-on: ubuntu-latest steps: - name: Checkout repository @@ -30,6 +49,17 @@ jobs: ref: ${{ github.head_ref }} fetch-depth: 0 + - name: Get OCP Cluster Name + id: commit_info + run: | + if [[ -n "${{ inputs.cluster_name }}" ]]; then + cluster_name="${{ inputs.cluster_name }}" + else + cluster_name="cl-$(git rev-parse --short HEAD)" + fi + + echo "cluster_name=$cluster_name" >> "$GITHUB_OUTPUT" + - name: Import Secrets id: secrets uses: hashicorp/vault-action@d1720f055e0635fd932a1d2a48f87a666a57906c # v3 @@ -55,20 +85,30 @@ jobs: - name: Create Cluster timeout-minutes: 125 uses: ./.github/actions/rosa-create-cluster + id: create_cluster with: rh-token: ${{ steps.secrets.outputs.RH_OPENSHIFT_TOKEN }} - cluster-name: "${{ env.CLUSTER_NAME }}" - admin-password: ${{ env.CI_OPENSHIFT_MAIN_PASSWORD }} + cluster-name: ${{ steps.commit_info.outputs.cluster_name }} + admin-username: ${{ env.OCP_ADMIN_USERNAME }} + admin-password: ${{ steps.secrets.outputs.CI_OPENSHIFT_MAIN_PASSWORD }} aws-region: ${{ env.AWS_REGION }} - namespace: "myns" s3-backend-bucket: ${{ env.TF_S3_BUCKET }} + - name: Create namespace if not exists + shell: bash + run: | + if ! oc get namespace "${{ env.OCP_NAMESPACE }}"; then + oc new-project "${{ env.OCP_NAMESPACE }}" + else + echo "Namespace '${{ env.OCP_NAMESPACE }}' already exists" + fi + - name: Delete Cluster timeout-minutes: 125 - if: always() + if: always() && !(github.event_name == 'workflow_dispatch' && github.event.inputs.delete_cluster == 'false') uses: ./.github/actions/rosa-delete-cluster with: rh-token: ${{ steps.secrets.outputs.RH_OPENSHIFT_TOKEN }} - cluster-name: "${{ env.CLUSTER_NAME }}" + cluster-name: "${{ steps.commit_info.outputs.cluster_name }}" aws-region: ${{ env.AWS_REGION }} s3-backend-bucket: ${{ env.TF_S3_BUCKET }} diff --git a/.lint/terraform_docs/.terraform-docs.yml b/.lint/terraform_docs/.terraform-docs.yml new file mode 100644 index 0000000..31a455d --- /dev/null +++ b/.lint/terraform_docs/.terraform-docs.yml @@ -0,0 +1,42 @@ +--- +# Configuration documentation https://terraform-docs.io/user-guide/configuration/ +formatter: "markdown table" # Required +version: "0.17" + +header-from: main.tf +footer-from: "" + +recursive: + enabled: false + +content: |- + {{ .Modules }} + {{ .Resources }} + {{ .Inputs }} + {{ .Outputs }} +sections: + hide: [] + show: [] + +output-values: + enabled: false + from: "" + +sort: + enabled: true + by: name + +settings: + anchor: true + color: true + default: true + description: true + escape: true + hide-empty: false + html: true + indent: 2 + lockfile: false + read-comments: true + required: true + sensitive: true + type: true diff --git a/.lint/tflint/.tflint.hcl b/.lint/tflint/.tflint.hcl new file mode 100644 index 0000000..9127bc1 --- /dev/null +++ b/.lint/tflint/.tflint.hcl @@ -0,0 +1,25 @@ +# Standard ruleset documentation: https://github.com/terraform-linters/tflint-ruleset-terraform/tree/main/docs/rules + +rule "terraform_naming_convention" { + enabled = true + custom = "^[a-z][a-z0-9_]{0,62}[a-z0-9]$" + module { + custom = "^[a-z][a-z0-9_]{0,70}[a-z0-9]$" + } +} + +rule "terraform_typed_variables" { + enabled = false +} + +rule "terraform_unused_declarations" { + enabled = false +} + +rule "terraform_required_version" { + enabled = false +} + +rule "terraform_required_providers" { + enabled = false +} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2cb623b..c4cd8e1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,9 +34,17 @@ repos: stages: [commit-msg] args: ["--strict" , "--force-scope"] -- repo: https://github.com/tcort/markdown-link-check - rev: v3.12.1 # use tags until renovate supports sha: https://github.com/renovatebot/renovate/issues/22567 +- repo: https://github.com/antonbabenko/pre-commit-terraform + rev: v1.88.4 hooks: - - id: markdown-link-check - args: [-q, -c .github/markdown-links.json] + - id: terraform_fmt + - id: terraform_tflint + args: + - --args=--config=__GIT_WORKING_DIR__/.lint/tflint/.tflint.hcl + - id: terraform_docs + args: + - --hook-config=--path-to-file=README.md + - --hook-config=--create-file-if-not-exist=true + - --hook-config=--add-to-existing-file=true + - --args=--config=.lint/terraform_docs/.terraform-docs.yml ... diff --git a/.tool-versions b/.tool-versions index 81a5490..26c017e 100644 --- a/.tool-versions +++ b/.tool-versions @@ -3,20 +3,18 @@ # check it with # diff <(sed '/^#/d; /^$/d' .tool-versions | sort) <(sed '/^#/d; /^$/d' .tool-versions) && echo ".tool-versions is sorted correctly" || echo ".tool-versions is not sorted correctly" -# renovate: datasource=github-releases depName=aws/aws-cli awscli 2.15.42 -# renovate: datasource=golang-version depName=golang golang 1.22.2 -# renovate: datasource=github-releases depName=casey/just just 1.25.2 -# renovate: datasource=github-releases depName=pre-commit/pre-commit pre-commit 3.7.0 -# renovate: datasource=github-releases depName=hashicorp/terraform terraform 1.8.2 -# TODO: rosa and oc not supported -# TODO: add helm +terraform-docs 0.17.0 + +tflint 0.50.3 + +tfsec 1.28.5 diff --git a/DEVELOPER.md b/DEVELOPER.md new file mode 100644 index 0000000..e563ac0 --- /dev/null +++ b/DEVELOPER.md @@ -0,0 +1,62 @@ +# Developer's Guide + +Welcome to the development reference for Camunda's Terraform Rosa module! This document provides guidance on setting up a testing environment, running tests, and managing releases. + +## Setting up Development Environment + +To start developing or testing the Rosa module, follow these steps: + +1. **Clone the Repository:** + - Clone the repository from [camunda/camunda-tf-rosa](https://github.com/camunda/camunda-tf-rosa) to your local machine. + +2. **Install Dependencies:** + - Ensure you have Terraform, the AWS CLI, and the ROSA CLI installed on your machine. Refer to their respective documentation for installation instructions. + +3. **Configure AWS Credentials:** + - Configure your AWS CLI with the necessary credentials to interact with your AWS account: + ```bash + aws configure + ``` + +4. **Initialize Terraform:** + - Navigate to the module's directory and initialize Terraform: + ```bash + cd modules/rosa-hcp + terraform init + ``` + +5. **Run Terraform Plan and Apply:** + - You can now plan and apply the Terraform configuration to create the ROSA cluster: + ```bash + terraform plan -var "cluster_name=your-cluster-name" -var "replicas=2" -var "htpasswd_password=your-password" -var "htpasswd_username=your-username" -var "offline_access_token=your-token" -var "openshift_version=your-openshift-version" + terraform apply -var "cluster_name=your-cluster-name" -var "replicas=2" -var "htpasswd_password=your-password" -var "htpasswd_username=your-username" -var "offline_access_token=your-token" -var "openshift_version=your-openshift-version" + ``` + +## Tests in the CI + +The tests in the CI can be triggered automatically by modifying Terraform or test files. It will be labeled either `test` or `terraform` automatically by the labeler. + +You can choose to overwrite the name and disable the deletion of the cluster in the workflow dispatch. + +## Releasing a New Version + +We follow Semantic Versioning (SemVer) guidelines for versioning. Follow these steps to release a new version: + +1. **Commit History:** + - Maintain a clear commit history with explicit messages detailing additions and deletions. + +2. **Versioning:** + - Determine the appropriate version number based on the changes made since the last release. + - Follow the format `MAJOR.MINOR.PATCH` as per Semantic Versioning guidelines. + +3. **GitHub Releases:** + - Publish the new version on GitHub Releases. + - Tag the release with the version number and include release notes summarizing changes. + +## Adding new GH actions + +Please pin GitHub action, if you need you can use [pin-github-action](https://github.com/mheap/pin-github-action) cli tool. + +--- + +By following these guidelines, we ensure smooth development iterations, robust testing practices, and clear version management for the Terraform ROSA module. Happy coding! diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..849a5ff --- /dev/null +++ b/LICENSE @@ -0,0 +1,14 @@ +Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH +under one or more contributor license agreements. See the NOTICE file +distributed with this work for additional information regarding copyright +ownership. Camunda licenses this file to you under the Apache License, +Version 2.0; you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md index ae8f9bf..047d3b1 100644 --- a/README.md +++ b/README.md @@ -4,27 +4,37 @@ [![tests](https://github.com/camunda/camunda-tf-rosa/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/camunda/camunda-tf-rosa/actions/workflows/tests.yml) [![License](https://img.shields.io/github/license/camunda/camunda-tf-rosa)](LICENSE) -Terraform module which creates Red Hat OpenShift with Hosted Control Plane on AWS (ROSA HCP) cluster with an opinionated configuration targeting Camunda 8. +This module automates the creation of a ROSA HCP cluster with an opinionated configuration targeting Camunda 8 on AWS using Terraform. -## Documentation +**⚠️ Warning:** This project is not intended for production use but rather for demonstration purposes only. There are no guarantees or warranties provided. -WIP +For more detailed usage and configuration options, please refer to the module's inputs and outputs documentation below. -## Usage +## Requirements -### Requirements +To gather all specifics versions of this project, we use: +- [asdf](https://asdf-vm.com/) version manager (see [installation](https://asdf-vm.com/guide/getting-started.html)). +- [just](https://github.com/casey/just) as a command runner + - install it using asdf: `asdf plugin add just && asdf install just` -* Terraform -* AWS CLI -* ROSA CLI -* OpenShift CLI +Then we will install all the tooling listed in the `.tool-versions` of this root project using just: +```bash +just install-tooling + +# list available recipes +just --list +``` +* Terraform (installed by asdf) +* AWS CLI (installed by asdf) +* ROSA CLI ([installation guide](https://docs.openshift.com/rosa/rosa_install_access_delete_clusters/rosa_getting_started_iam/rosa-installing-rosa.html)) +* OpenShift CLI ([installation guide](https://docs.openshift.com/container-platform/latest/cli_reference/openshift_cli/getting-started-cli.html)) -### Getting started : Create a ROSA HCP cluster +## Getting started : Create a ROSA HCP cluster Base tutorial https://aws.amazon.com/blogs/containers/build-rosa-clusters-with-terraform/ -#### I. Prepare the deployment +### I. Enable ROSA in AWS Marketplace 1. Login onto AWS 2. Check if ELB role exists @@ -49,30 +59,131 @@ rosa verify quota --region="$AWS_REGION" # this may fail due to org policy rosa verify permissions --region="$AWS_REGION" -# TODO: check if this one is required: rosa create account-roles --mode auto ``` 5. Enable HCP ROSA on [AWS MarkePlace](https://docs.openshift.com/rosa/cloud_experts_tutorials/cloud-experts-rosa-hcp-activation-and-account-linking-tutorial.html) - 5.1 Navigate to the ROSA console : https://console.aws.amazon.com/rosa - 5.2 Choose Get started. - 5.3 On the Verify ROSA prerequisites page, select I agree to share my contact information with Red Hat. - 5.4 Choose Enable ROSA + * Navigate to the ROSA console : https://console.aws.amazon.com/rosa + * Choose Get started. + * On the Verify ROSA prerequisites page, select I agree to share my contact information with Red Hat. + * Choose Enable ROSA Please note that **Only a single AWS account that will be used for service billing can be associated with a Red Hat account.** -#### II. Deploy a cluster with terraform +### II. Create the cluster -```bash -export ADMIN_PASS="yourPassword!!138" -export ADMIN_USER="kubeadmin" -export CLUSTER_NAME="rosatest" +#### Terraform + +To use this module with Terraform, follow these steps: + +1. **Create a Terraform configuration file** (e.g., `main.tf`). +2. **Include the ROSA HCP module** in your configuration file. + +Here's an example configuration: + +```hcl +module "rosa_hcp" { + source = "github.com/camunda/camunda-tf-rosa.git//modules/rosa-hcp?ref=main" + + cluster_name = "my-ocp-cluster" + htpasswd_password = "your_password" + offline_access_token = "your_ocm_token" # see below for instructions + openshift_version = "4.15.11" + replicas = "2" +} +``` -terraform init -terraform plan -out rosa.plan -var "cluster_name=$CLUSTER_NAME" -var "htpasswd_password=$ADMIN_PASS" -var "htpasswd_username=$ADMIN_USER" -var "offline_access_token=$RH_TOKEN" -terraform apply rosa.plan +For more details, refer to the [Terraform module ROSA HCP README](https://github.com/camunda/camunda-tf-rosa/blob/main/modules/rosa-hcp/README.md). + + +3. **Initialize Terraform** by running: + ```sh + terraform init + ``` + +4. **Review the execution plan** with: + ```sh + terraform plan + ``` + +5. **Apply the configuration** to create the resources: + ```sh + terraform apply + ``` + +#### GitHub Actions + +You can automate the deployment and deletion of the ROSA HCP cluster using GitHub Actions. Below are examples of GitHub Actions workflows for deploying and deleting the cluster. + +##### Deploy ROSA HCP Cluster + +Create a file in your repository's `.github/workflows` directory, for example `deploy-rosa-hcp.yml`, with the following content: + +```yaml +name: Deploy ROSA HCP Cluster + +on: + pull_request: + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Add profile credentials to ~/.aws/credentials + run: | + aws configure set aws_access_key_id ${{ secrets.AWS_ACCESS_KEY }} --profile ${{ env.AWS_PROFILE }} + aws configure set aws_secret_access_key ${{ secrets.AWS_SECRET_KEY }} --profile ${{ env.AWS_PROFILE }} + aws configure set region ${{ env.AWS_REGION }} --profile ${{ env.AWS_PROFILE }} + + - name: Deploy ROSA HCP Cluster + uses: camunda/camunda-tf-rosa/.github/actions/rosa-create-cluster@main + id: create_cluster + timeout-minutes: 125 # cluster creation can take up to 45 minutes + with: + rh-token: ${{ secrets.RH_OPENSHIFT_TOKEN }} + cluster-name: "my-ocp-cluster" + admin-username: "cluster-admin" + admin-password: ${{ secrets.CI_OPENSHIFT_MAIN_PASSWORD }} + aws-region: "us-west-2" + s3-backend-bucket: ${{ secrets.TF_S3_BUCKET }} + + - name: Use your created cluster + shell: bash + run: | + oc new-project "myns" + oc whoami + oc get pods ``` -#### III. Retrieve cluster informations +For more details, refer to the [Deploy ROSA HCP Cluster Action README](https://github.com/camunda/camunda-tf-rosa/blob/main/.github/actions/rosa-create-cluster/README.md). + +##### Delete ROSA HCP Cluster + +Create another file in your repository's `.github/workflows` directory, for example `delete-rosa-hcp.yml`, with the following content: + +```yaml +name: Delete ROSA HCP Cluster + +on: + workflow_dispatch: + +jobs: + delete: + runs-on: ubuntu-latest + steps: + - name: Delete ROSA HCP Cluster + uses: camunda/camunda-tf-rosa/.github/actions/rosa-delete-cluster@main + timeout-minutes: 125 # cluster deletion can take some time + with: + rh-token: ${{ secrets.RH_OPENSHIFT_TOKEN }} + cluster-name: "my-ocp-cluster" + aws-region: "us-west-2" + s3-backend-bucket: ${{ secrets.TF_S3_BUCKET }} +``` + +For more details, refer to the [Delete ROSA HCP Cluster Action README](https://github.com/camunda/camunda-tf-rosa/blob/main/.github/actions/rosa-delete-cluster/README.md). + + +### III. Retrieve cluster informations 1. In the output, you will have the created cluster id: ```bash @@ -97,8 +208,6 @@ kubectl config use "$CLUSTER_NAME" oc new-project "$NAMESPACE" ``` -TODO: add modules doc - ## Support Please note that the modules have been tested with **[Terraform](https://github.com/hashicorp/terraform)** in the version described in the [.tool-versions](./.tool-versions) of this project. diff --git a/lychee-links.toml b/lychee-links.toml new file mode 100644 index 0000000..8fe7ed8 --- /dev/null +++ b/lychee-links.toml @@ -0,0 +1,19 @@ +# Cache the results of Lychee if ran locally in order to minimise the chance of rate limiting +cache = true +# Ignore all private link (such as localhost) to avoid errors +exclude_all_private = true +# HTTP status code: 429 (Too Many Requests) will also be treated as a valid link if Lychee gets rate limited +accept = ["200", "403"] +# retry +max_retries = 6 +retry_wait_time = 10 +max_concurrency = 3 + +# Exclude all unsupported versioned_docs +exclude_path = [ +] + +# Explicitly exclude some URLs +exclude = [ + "^file:", +] diff --git a/modules/rosa-hcp/vars.tf b/modules/rosa-hcp/vars.tf index 1d0b3e7..572ee2c 100644 --- a/modules/rosa-hcp/vars.tf +++ b/modules/rosa-hcp/vars.tf @@ -8,7 +8,7 @@ variable "cluster_name" { variable "openshift_version" { type = string description = "The version of ROSA to be deployed" - # TODO renovate latest version + # renovate: datasource=endoflife-date depName=red-hat-openshift versioning=semver default = "4.14.21" validation { condition = can(regex("^[0-9]*[0-9]+.[0-9]*[0-9]+.[0-9]*[0-9]+$", var.openshift_version))