diff --git a/.github/RELEASE_DRAFTER.yml b/.github/RELEASE_DRAFTER.yml
index 1ae725f..c6af0a0 100644
--- a/.github/RELEASE_DRAFTER.yml
+++ b/.github/RELEASE_DRAFTER.yml
@@ -7,11 +7,25 @@ categories:
- 'enhancement'
- title: 'Bug Fixes'
labels:
- - 'fix'
- - 'bugfix'
- 'bug'
- title: 'Documentation'
label: 'documentation'
+ - title: 'CI'
+ label: 'ci'
+version-resolver:
+ major:
+ labels:
+ - 'major'
+ minor:
+ labels:
+ - 'feature'
+ - 'enhancement'
+ patch:
+ labels:
+ - 'ci'
+ - 'bug'
+ - 'documentation'
+ default: patch
change-template: '- $TITLE, by @$AUTHOR (#$NUMBER)'
template: |
# What's changed
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
index 7c0b1ec..bbbd33f 100644
--- a/.github/workflows/pre-commit.yml
+++ b/.github/workflows/pre-commit.yml
@@ -1,5 +1,8 @@
name: pre-commit
+permissions:
+ contents: read
+
on:
workflow_dispatch:
pull_request:
@@ -8,36 +11,42 @@ on:
- master
env:
+ PYTHON_VERSION: "3.10"
TERRAFORM_DOCS_VERSION: "v0.16.0"
- TFLINT_VERSION: "v0.36.2"
+ TFLINT_VERSION: "v0.40.1"
jobs:
pre-commit:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-python@v2
-
- - name: Install additional pre-commit hooks
- shell: bash
- run: |
- echo "########### Install Checkov ####################"
- pip install checkov
-
- echo "########### Install Terraform-docs #############"
- wget https://github.com/terraform-docs/terraform-docs/releases/download/${{ env.TERRAFORM_DOCS_VERSION }}/terraform-docs-${{ env.TERRAFORM_DOCS_VERSION }}-linux-amd64.tar.gz
- tar xvzf terraform-docs-${{ env.TERRAFORM_DOCS_VERSION }}-linux-amd64.tar.gz
- mkdir -p ~/terraform-docs/bin/
- install terraform-docs ~/terraform-docs/bin/
- echo '~/terraform-docs/bin/' >> $GITHUB_PATH
-
- echo "########### Install Terraform-linters ##########"
- wget https://github.com/terraform-linters/tflint/releases/download/${{ env.TFLINT_VERSION }}/tflint_linux_amd64.zip
- unzip tflint_linux_amd64.zip
- mkdir -p ~/tflint/bin/
- echo '~/tflint/bin/' >> $GITHUB_PATH
- install tflint ~/tflint/bin/
- ~/tflint/bin/tflint --init
-
- - name: Run pre-commit
- uses: pre-commit/action@v2.0.3
+ - uses: actions/checkout@v3
+ - uses: actions/setup-python@v4
+ with:
+ python-version: ${{ env.PYTHON_VERSION }}
+ cache: pip
+
+ - name: Install Python dependencies
+ run: pip install -r requirements.txt
+
+ - name: Install terraform-docs
+ uses: jaxxstorm/action-install-gh-release@v1.9.0
+ with:
+ repo: terraform-docs/terraform-docs
+ tag: ${{ env.TERRAFORM_DOCS_VERSION }}
+ cache: enable
+
+ - name: TFLint cache
+ uses: actions/cache@v3
+ with:
+ path: ~/.tflint.d/plugins
+ key: ${{ runner.os }}-tflint-${{ hashFiles('.tflint.hcl') }}
+
+ - name: Install TFLint
+ uses: terraform-linters/setup-tflint@v2
+ with:
+ tflint_version: ${{ env.TFLINT_VERSION }}
+
+ - name: Run pre-commit
+ uses: pre-commit/action@v3.0.0
diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml
index 7cae11f..9528a7a 100644
--- a/.github/workflows/release-drafter.yml
+++ b/.github/workflows/release-drafter.yml
@@ -15,7 +15,7 @@ on:
jobs:
update_release_draft:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
steps:
- uses: release-drafter/release-drafter@v5
with:
diff --git a/.github/workflows/validate.yaml b/.github/workflows/validate.yaml
index 2d3f60e..2b9e3e7 100644
--- a/.github/workflows/validate.yaml
+++ b/.github/workflows/validate.yaml
@@ -1,5 +1,8 @@
name: Terraform validate
+permissions:
+ contents: read
+
on:
workflow_dispatch:
pull_request:
@@ -10,11 +13,11 @@ on:
jobs:
versionExtract:
name: Extract min/max Terraform versions
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Extract Terraform min/max versions
id: minMax
@@ -26,7 +29,7 @@ jobs:
maxVersion: ${{ steps.minMax.outputs.maxVersion }}
terraform-validate:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
needs: versionExtract
strategy:
matrix:
@@ -35,7 +38,7 @@ jobs:
- ${{ needs.versionExtract.outputs.maxVersion }}
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- uses: hashicorp/setup-terraform@v2
with:
terraform_version: ${{ matrix.tf_ver }}
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index b105c2c..5ce50e2 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.2.0
+ rev: v4.3.0
hooks:
- id: trailing-whitespace
- id: check-merge-conflict
@@ -10,23 +10,18 @@ repos:
- id: end-of-file-fixer
- repo: https://github.com/antonbabenko/pre-commit-terraform
- rev: v1.71.0
+ rev: v1.75.0
hooks:
- - id: terraform_fmt
- - id: terraform_tflint
- - id: terraform_validate
- - id: terraform_checkov
- - id: terraform_docs
- args:
- - '--args=--hide providers --sort-by required'
-
- - repo: https://github.com/pecigonzalo/pre-commit-terraform-vars
- rev: v1.0.0
- hooks:
- - id: terraform-vars
+ - id: terraform_fmt
+ - id: terraform_tflint
+ - id: terraform_validate
+ - id: terraform_checkov
+ - id: terraform_docs
+ args:
+ - '--args=--config=.terraform-docs.yml'
- repo: https://github.com/Yelp/detect-secrets
- rev: v1.2.0
+ rev: v1.3.0
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
diff --git a/.secrets.baseline b/.secrets.baseline
index 62fe8c6..eaf7047 100644
--- a/.secrets.baseline
+++ b/.secrets.baseline
@@ -1,20 +1,18 @@
{
- "custom_plugin_paths": [],
- "exclude": {
- "files": null,
- "lines": null
- },
- "generated_at": "2020-09-21T15:31:24Z",
+ "version": "1.3.0",
"plugins_used": [
+ {
+ "name": "ArtifactoryDetector"
+ },
{
"name": "AWSKeyDetector"
},
{
- "name": "ArtifactoryDetector"
+ "name": "AzureStorageKeyDetector"
},
{
- "base64_limit": 4.5,
- "name": "Base64HighEntropyString"
+ "name": "Base64HighEntropyString",
+ "limit": 4.5
},
{
"name": "BasicAuthDetector"
@@ -23,8 +21,11 @@
"name": "CloudantDetector"
},
{
- "hex_limit": 3,
- "name": "HexHighEntropyString"
+ "name": "GitHubTokenDetector"
+ },
+ {
+ "name": "HexHighEntropyString",
+ "limit": 3.0
},
{
"name": "IbmCloudIamDetector"
@@ -36,21 +37,30 @@
"name": "JwtTokenDetector"
},
{
- "keyword_exclude": null,
- "name": "KeywordDetector"
+ "name": "KeywordDetector",
+ "keyword_exclude": ""
},
{
"name": "MailchimpDetector"
},
+ {
+ "name": "NpmDetector"
+ },
{
"name": "PrivateKeyDetector"
},
+ {
+ "name": "SendGridDetector"
+ },
{
"name": "SlackDetector"
},
{
"name": "SoftlayerDetector"
},
+ {
+ "name": "SquareOAuthDetector"
+ },
{
"name": "StripeDetector"
},
@@ -58,10 +68,46 @@
"name": "TwilioKeyDetector"
}
],
+ "filters_used": [
+ {
+ "path": "detect_secrets.filters.allowlist.is_line_allowlisted"
+ },
+ {
+ "path": "detect_secrets.filters.common.is_baseline_file",
+ "filename": ".secrets.baseline"
+ },
+ {
+ "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
+ "min_level": 2
+ },
+ {
+ "path": "detect_secrets.filters.heuristic.is_indirect_reference"
+ },
+ {
+ "path": "detect_secrets.filters.heuristic.is_likely_id_string"
+ },
+ {
+ "path": "detect_secrets.filters.heuristic.is_lock_file"
+ },
+ {
+ "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
+ },
+ {
+ "path": "detect_secrets.filters.heuristic.is_potential_uuid"
+ },
+ {
+ "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
+ },
+ {
+ "path": "detect_secrets.filters.heuristic.is_sequential_string"
+ },
+ {
+ "path": "detect_secrets.filters.heuristic.is_swagger_file"
+ },
+ {
+ "path": "detect_secrets.filters.heuristic.is_templated_secret"
+ }
+ ],
"results": {},
- "version": "0.14.3",
- "word_list": {
- "file": null,
- "hash": null
- }
+ "generated_at": "2022-07-28T10:50:47Z"
}
diff --git a/.terraform-docs.yml b/.terraform-docs.yml
new file mode 100644
index 0000000..cb998c2
--- /dev/null
+++ b/.terraform-docs.yml
@@ -0,0 +1,15 @@
+formatter: markdown table
+
+output:
+ mode: inject
+ template: |-
+
+ {{ .Content }}
+
+
+sections:
+ hide:
+ - providers
+
+sort:
+ by: required
diff --git a/.tflint.hcl b/.tflint.hcl
new file mode 100644
index 0000000..372282e
--- /dev/null
+++ b/.tflint.hcl
@@ -0,0 +1,11 @@
+plugin "terraform" {
+ enabled = true
+ version = "0.1.1"
+ source = "github.com/terraform-linters/tflint-ruleset-terraform"
+ preset = "recommended"
+}
+plugin "aws" {
+ enabled = true
+ version = "0.17.0"
+ source = "github.com/terraform-linters/tflint-ruleset-aws"
+}
diff --git a/README.md b/README.md
index c689e86..4e2332a 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
-# AWS EKS cluster autoscaler Terraform module
+# AWS EKS Cluster Autoscaler Terraform module
-[![labyrinth labs logo](ll-logo.png)](https://lablabs.io/)
+[](https://lablabs.io/)
-We help companies build, run, deploy and scale software and infrastructure by embracing the right technologies and principles. Check out our website at https://lablabs.io/
+We help companies build, run, deploy and scale software and infrastructure by embracing the right technologies and principles. Check out our website at
[| no | -| [argo\_kubernetes\_manifest\_computed\_fields](#input\_argo\_kubernetes\_manifest\_computed\_fields) | List of paths of fields to be handled as "computed". The user-configured value for the field will be overridden by any different value returned by the API after apply. | `list(string)` |
{
"name": "terraform",
"value": "true"
}
]
[| no | +| [argo\_helm\_wait\_backoff\_limit](#input\_argo\_helm\_wait\_backoff\_limit) | Backoff limit for ArgoCD Application Helm release wait job | `number` | `6` | no | +| [argo\_helm\_wait\_timeout](#input\_argo\_helm\_wait\_timeout) | Timeout for ArgoCD Application Helm release wait job | `string` | `"10m"` | no | +| [argo\_info](#input\_argo\_info) | ArgoCD info manifest parameter |
"metadata.labels",
"metadata.annotations"
]
list(object({|
name = string
value = string
}))
[| no | +| [argo\_kubernetes\_manifest\_computed\_fields](#input\_argo\_kubernetes\_manifest\_computed\_fields) | List of paths of fields to be handled as "computed". The user-configured value for the field will be overridden by any different value returned by the API after apply. | `list(string)` |
{
"name": "terraform",
"value": "true"
}
]
[| no | | [argo\_kubernetes\_manifest\_field\_manager\_force\_conflicts](#input\_argo\_kubernetes\_manifest\_field\_manager\_force\_conflicts) | Forcibly override any field manager conflicts when applying the kubernetes manifest resource | `bool` | `false` | no | | [argo\_kubernetes\_manifest\_field\_manager\_name](#input\_argo\_kubernetes\_manifest\_field\_manager\_name) | The name of the field manager to use when applying the kubernetes manifest resource. Defaults to Terraform | `string` | `"Terraform"` | no | | [argo\_kubernetes\_manifest\_wait\_fields](#input\_argo\_kubernetes\_manifest\_wait\_fields) | A map of fields and a corresponding regular expression with a pattern to wait for. The provider will wait until the field matches the regular expression. Use * for any value. | `map(string)` | `{}` | no | -| [argo\_metadata](#input\_argo\_metadata) | ArgoCD Application metadata configuration. Override or create additional metadata parameters | `map` |
"metadata.labels",
"metadata.annotations",
"metadata.finalizers"
]
{| no | +| [argo\_metadata](#input\_argo\_metadata) | ArgoCD Application metadata configuration. Override or create additional metadata parameters | `any` |
"finalizers": [
"resources-finalizer.argocd.argoproj.io"
]
}
{| no | | [argo\_namespace](#input\_argo\_namespace) | Namespace to deploy ArgoCD application CRD to | `string` | `"argo"` | no | | [argo\_project](#input\_argo\_project) | ArgoCD Application project | `string` | `"default"` | no | -| [argo\_spec](#input\_argo\_spec) | ArgoCD Application spec configuration. Override or create additional spec parameters | `map` | `{}` | no | -| [argo\_sync\_policy](#input\_argo\_sync\_policy) | ArgoCD syncPolicy manifest parameter | `map` | `{}` | no | +| [argo\_spec](#input\_argo\_spec) | ArgoCD Application spec configuration. Override or create additional spec parameters | `any` | `{}` | no | +| [argo\_sync\_policy](#input\_argo\_sync\_policy) | ArgoCD syncPolicy manifest parameter | `any` | `{}` | no | | [enabled](#input\_enabled) | Variable indicating whether deployment is enabled | `bool` | `true` | no | | [helm\_atomic](#input\_helm\_atomic) | If set, installation process purges chart on fail. The wait flag will be set automatically if atomic is used | `bool` | `false` | no | | [helm\_chart\_name](#input\_helm\_chart\_name) | Helm chart name to be installed | `string` | `"cluster-autoscaler"` | no | @@ -135,17 +143,17 @@ No modules. | [helm\_wait\_for\_jobs](#input\_helm\_wait\_for\_jobs) | If wait is enabled, will wait until all helm Jobs have been completed before marking the release as successful. It will wait for as long as timeout | `bool` | `false` | no | | [irsa\_additional\_policies](#input\_irsa\_additional\_policies) | Map of the additional policies to be attached to default role. Where key is arbitrary id and value is policy arn. | `map(string)` | `{}` | no | | [irsa\_assume\_role\_arn](#input\_irsa\_assume\_role\_arn) | Assume role arn. Assume role must be enabled. | `string` | `""` | no | -| [irsa\_assume\_role\_enabled](#input\_irsa\_assume\_role\_enabled) | Whether IRSA is allowed to assume role defined by assume\_role\_arn. | `bool` | `false` | no | +| [irsa\_assume\_role\_enabled](#input\_irsa\_assume\_role\_enabled) | Whether IRSA is allowed to assume role defined by irsa\_assume\_role\_arn. | `bool` | `false` | no | | [irsa\_policy\_enabled](#input\_irsa\_policy\_enabled) | Whether to create opinionated policy to allow operations on specified zones in `policy_allowed_zone_ids`. | `bool` | `true` | no | | [irsa\_role\_create](#input\_irsa\_role\_create) | Whether to create IRSA role and annotate service account | `bool` | `true` | no | -| [irsa\_role\_name\_prefix](#input\_irsa\_role\_name\_prefix) | The IRSA role name prefix for vector | `string` | `"cluster-autoscaler-irsa"` | no | +| [irsa\_role\_name\_prefix](#input\_irsa\_role\_name\_prefix) | The IRSA role name prefix for <$addon-name> | `string` | `"cluster-autoscaler-irsa"` | no | | [irsa\_tags](#input\_irsa\_tags) | IRSA resources tags | `map(string)` | `{}` | no | | [namespace](#input\_namespace) | The K8s namespace in which the node-problem-detector service account has been created | `string` | `"cluster-autoscaler"` | no | | [rbac\_create](#input\_rbac\_create) | Whether to create and use RBAC resources | `bool` | `true` | no | | [service\_account\_create](#input\_service\_account\_create) | Whether to create Service Account | `bool` | `true` | no | -| [service\_account\_name](#input\_service\_account\_name) | The k8s cluster-autoscaler service account name | `string` | `"cluster-autoscaler"` | no | -| [settings](#input\_settings) | Additional helm sets which will be passed to the Helm chart values, see https://hub.helm.sh/charts/stable/cluster-autoscaler | `map(any)` | `{}` | no | -| [values](#input\_values) | Additional yaml encoded values which will be passed to the Helm chart, see https://hub.helm.sh/charts/stable/cluster-autoscaler | `string` | `""` | no | +| [service\_account\_name](#input\_service\_account\_name) | The k8s <$addon-name> service account name | `string` | `"cluster-autoscaler"` | no | +| [settings](#input\_settings) | Additional helm sets which will be passed to the Helm chart values, see https://hub.helm.sh/charts/stable/<$addon-name> | `map(any)` | `{}` | no | +| [values](#input\_values) | Additional yaml encoded values which will be passed to the Helm chart, see https://hub.helm.sh/charts/stable/<$addon-name> | `string` | `""` | no | ## Outputs @@ -153,7 +161,7 @@ No modules. |------|-------------| | [helm\_release\_application\_metadata](#output\_helm\_release\_application\_metadata) | Argo application helm release attributes | | [helm\_release\_metadata](#output\_helm\_release\_metadata) | Helm release attributes | -| [iam\_role\_attributes](#output\_iam\_role\_attributes) | Vector IAM role atributes | +| [iam\_role\_attributes](#output\_iam\_role\_attributes) | Cluster Autoscaler IAM role attributes | | [kubernetes\_application\_attributes](#output\_kubernetes\_application\_attributes) | Argo kubernetes manifest attributes | diff --git a/argo-helm.tf b/argo-helm.tf new file mode 100644 index 0000000..7ce67a0 --- /dev/null +++ b/argo-helm.tf @@ -0,0 +1,149 @@ +locals { + helm_argo_application_enabled = var.enabled && var.argo_enabled && var.argo_helm_enabled + helm_argo_application_wait_enabled = local.helm_argo_application_enabled && length(keys(var.argo_kubernetes_manifest_wait_fields)) > 0 + helm_argo_application_values = [ + one(data.utils_deep_merge_yaml.argo_helm_values[*].output), + var.argo_helm_values + ] +} + +data "utils_deep_merge_yaml" "argo_helm_values" { + count = local.helm_argo_application_enabled ? 1 : 0 + + input = compact([ + yamlencode({ + "apiVersion" : var.argo_apiversion + }), + yamlencode({ + "spec" : local.argo_application_values + }), + yamlencode({ + "spec" : var.argo_spec + }), + yamlencode( + local.argo_application_metadata + ) + ]) +} + +resource "helm_release" "argo_application" { + count = local.helm_argo_application_enabled ? 1 : 0 + + chart = "${path.module}/helm/argocd-application" + name = var.helm_release_name + namespace = var.argo_namespace + + values = local.helm_argo_application_values +} + +resource "kubernetes_role" "helm_argo_application_wait" { + count = local.helm_argo_application_wait_enabled ? 1 : 0 + + metadata { + name = "${var.helm_release_name}-argo-application-wait" + namespace = var.argo_namespace + labels = local.argo_application_metadata.labels + annotations = local.argo_application_metadata.annotations + } + + rule { + api_groups = ["argoproj.io"] + resources = ["applications"] + verbs = ["get", "list", "watch"] + } +} + +resource "kubernetes_role_binding" "helm_argo_application_wait" { + count = local.helm_argo_application_wait_enabled ? 1 : 0 + + metadata { + name = "${var.helm_release_name}-argo-application-wait" + namespace = var.argo_namespace + labels = local.argo_application_metadata.labels + annotations = local.argo_application_metadata.annotations + } + + role_ref { + api_group = "rbac.authorization.k8s.io" + kind = "Role" + name = one(kubernetes_role.helm_argo_application_wait[*].metadata[0].name) + } + + subject { + kind = "ServiceAccount" + name = one(kubernetes_service_account.helm_argo_application_wait[*].metadata[0].name) + namespace = one(kubernetes_service_account.helm_argo_application_wait[*].metadata[0].namespace) + } +} + +resource "kubernetes_service_account" "helm_argo_application_wait" { + count = local.helm_argo_application_wait_enabled ? 1 : 0 + + metadata { + name = "${var.helm_release_name}-argo-application-wait" + namespace = var.argo_namespace + labels = local.argo_application_metadata.labels + annotations = local.argo_application_metadata.annotations + } +} + +resource "kubernetes_job" "helm_argo_application_wait" { + count = local.helm_argo_application_wait_enabled ? 1 : 0 + + metadata { + generate_name = "${var.helm_release_name}-argo-application-wait" + namespace = var.argo_namespace + labels = local.argo_application_metadata.labels + annotations = local.argo_application_metadata.annotations + } + + spec { + template { + metadata { + labels = local.argo_application_metadata.labels + annotations = local.argo_application_metadata.annotations + } + + spec { + service_account_name = one(kubernetes_service_account.helm_argo_application_wait[*].metadata[0].name) + + dynamic "container" { + for_each = var.argo_kubernetes_manifest_wait_fields + + content { + name = "${lower(replace(container.key, ".", "-"))}-${md5(jsonencode(local.helm_argo_application_values))}" # md5 suffix is a workaround for https://github.com/hashicorp/terraform-provider-kubernetes/issues/1325 + image = "bitnami/kubectl:latest" + command = ["/bin/bash", "-ecx"] + # Waits for ArgoCD Application to be "Healthy", see https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#wait + # i.e. kubectl wait --for=jsonpath='{.status.sync.status}'=Healthy application.argoproj.io <$addon-name> + args = [ + <<-EOT + kubectl wait \ + --namespace ${var.argo_namespace} \ + --for=jsonpath='{.${container.key}}'=${container.value} \ + --timeout=${var.argo_helm_wait_timeout} \ + application.argoproj.io ${var.helm_release_name} + EOT + ] + } + } + + # ArgoCD Application status fields might not be available immediately after creation + restart_policy = "OnFailure" + } + } + + backoff_limit = var.argo_helm_wait_backoff_limit + } + + wait_for_completion = true + + timeouts { + create = var.argo_helm_wait_timeout + update = var.argo_helm_wait_timeout + } + + depends_on = [ + helm_release.argo_application + ] +} diff --git a/argo.tf b/argo.tf index a952837..0ce0334 100644 --- a/argo.tf +++ b/argo.tf @@ -25,39 +25,6 @@ locals { } } -data "utils_deep_merge_yaml" "argo_helm_values" { - count = var.enabled && var.argo_enabled && var.argo_helm_enabled ? 1 : 0 - input = compact([ - yamlencode({ - "apiVersion" : var.argo_apiversion - }), - yamlencode({ - "spec" : local.argo_application_values - }), - yamlencode({ - "spec" : var.argo_spec - }), - yamlencode( - local.argo_application_metadata - ) - ]) -} - - -resource "helm_release" "argo_application" { - count = var.enabled && var.argo_enabled && var.argo_helm_enabled ? 1 : 0 - - chart = "${path.module}/helm/argocd-application" - name = var.helm_release_name - namespace = var.argo_namespace - - values = [ - data.utils_deep_merge_yaml.argo_helm_values[0].output, - var.argo_helm_values - ] -} - - resource "kubernetes_manifest" "this" { count = var.enabled && var.argo_enabled && !var.argo_helm_enabled ? 1 : 0 manifest = { diff --git a/examples/basic/README.md b/examples/basic/README.md index 918d18a..49f360a 100644 --- a/examples/basic/README.md +++ b/examples/basic/README.md @@ -5,18 +5,24 @@ The code in this example shows how to use the module with basic configuration an ## Requirements -No requirements. +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 4.19.0 | +| [helm](#requirement\_helm) | >= 2.6.0 | +| [kubernetes](#requirement\_kubernetes) | >= 2.16.0 | ## Modules | Name | Source | Version | |------|--------|---------| -| [cluster-autoscaler\_argo\_helm](#module\_cluster-autoscaler\_argo\_helm) | ../../ | n/a | -| [cluster-autoscaler\_argo\_manifests](#module\_cluster-autoscaler\_argo\_manifests) | ../../ | n/a | -| [cluster-autoscaler\_helm](#module\_cluster-autoscaler\_helm) | ../../ | n/a | -| [eks\_cluster](#module\_eks\_cluster) | cloudposse/eks-cluster/aws | 0.43.2 | -| [eks\_node\_group](#module\_eks\_node\_group) | cloudposse/eks-node-group/aws | 0.25.0 | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | 3.6.0 | +| [addon\_installation\_argo\_helm](#module\_addon\_installation\_argo\_helm) | ../../ | n/a | +| [addon\_installation\_argo\_kubernetes](#module\_addon\_installation\_argo\_kubernetes) | ../../ | n/a | +| [addon\_installation\_disabled](#module\_addon\_installation\_disabled) | ../../ | n/a | +| [addon\_installation\_helm](#module\_addon\_installation\_helm) | ../../ | n/a | +| [eks\_cluster](#module\_eks\_cluster) | cloudposse/eks-cluster/aws | 2.3.0 | +| [eks\_node\_group](#module\_eks\_node\_group) | cloudposse/eks-node-group/aws | 2.4.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | 4.0.0 | ## Resources diff --git a/examples/basic/base.tf b/examples/basic/base.tf new file mode 100644 index 0000000..25ad652 --- /dev/null +++ b/examples/basic/base.tf @@ -0,0 +1,33 @@ +module "vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "4.0.0" + + name = "<$addon-name>-vpc" + cidr = "10.0.0.0/16" + azs = ["eu-central-1a", "eu-central-1b"] + public_subnets = ["10.0.101.0/24", "10.0.102.0/24"] + enable_nat_gateway = true +} + +module "eks_cluster" { + source = "cloudposse/eks-cluster/aws" + version = "2.3.0" + + region = "eu-central-1" + subnet_ids = module.vpc.public_subnets + vpc_id = module.vpc.vpc_id + name = "basic-example" +} + +module "eks_node_group" { + source = "cloudposse/eks-node-group/aws" + version = "2.4.0" + + cluster_name = module.eks_cluster.eks_cluster_id + instance_types = ["t3.medium"] + subnet_ids = module.vpc.public_subnets + min_size = 1 + desired_size = 1 + max_size = 2 + depends_on = [module.eks_cluster.kubernetes_config_map_id] +} diff --git a/examples/basic/main.tf b/examples/basic/main.tf index 64c925d..0a2c3c4 100644 --- a/examples/basic/main.tf +++ b/examples/basic/main.tf @@ -1,38 +1,14 @@ -module "vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "3.6.0" - - name = "cluster-autoscaler-vpc" - cidr = "10.0.0.0/16" - azs = ["eu-central-1a", "eu-central-1b"] - public_subnets = ["10.0.101.0/24", "10.0.102.0/24"] - enable_nat_gateway = true -} - -module "eks_cluster" { - source = "cloudposse/eks-cluster/aws" - version = "0.43.2" - - region = "eu-central-1" - subnet_ids = module.vpc.public_subnets - vpc_id = module.vpc.vpc_id - name = "cluster-autoscaler" -} +module "addon_installation_disabled" { + source = "../../" -module "eks_node_group" { - source = "cloudposse/eks-node-group/aws" - version = "0.25.0" + enabled = false - cluster_name = "cluster-autoscaler" - instance_types = ["t3.medium"] - subnet_ids = module.vpc.public_subnets - min_size = 1 - desired_size = 1 - max_size = 2 - depends_on = [module.eks_cluster.kubernetes_config_map_id] + cluster_name = module.eks_cluster.eks_cluster_id + cluster_identity_oidc_issuer = module.eks_cluster.eks_cluster_identity_oidc_issuer + cluster_identity_oidc_issuer_arn = module.eks_cluster.eks_cluster_identity_oidc_issuer_arn } -module "cluster-autoscaler_helm" { +module "addon_installation_helm" { source = "../../" enabled = true @@ -44,18 +20,12 @@ module "cluster-autoscaler_helm" { cluster_identity_oidc_issuer_arn = module.eks_cluster.eks_cluster_identity_oidc_issuer_arn values = yamlencode({ - "image" : { - "tag" : "v1.21.2" - } + # insert sample values here }) - - argo_sync_policy = { - "automated" : {} - "syncOptions" = ["CreateNamespace=true"] - } } -module "cluster-autoscaler_argo_manifests" { +# Please, see README.md and Argo Kubernetes deployment method for implications of using Kubernetes installation method +module "addon_installation_argo_kubernetes" { source = "../../" enabled = true @@ -67,9 +37,7 @@ module "cluster-autoscaler_argo_manifests" { cluster_identity_oidc_issuer_arn = module.eks_cluster.eks_cluster_identity_oidc_issuer_arn values = yamlencode({ - "image" : { - "tag" : "v1.21.2" - } + # insert sample values here }) argo_sync_policy = { @@ -78,8 +46,7 @@ module "cluster-autoscaler_argo_manifests" { } } - -module "cluster-autoscaler_argo_helm" { +module "addon_installation_argo_helm" { source = "../../" enabled = true @@ -90,12 +57,6 @@ module "cluster-autoscaler_argo_helm" { cluster_identity_oidc_issuer = module.eks_cluster.eks_cluster_identity_oidc_issuer cluster_identity_oidc_issuer_arn = module.eks_cluster.eks_cluster_identity_oidc_issuer_arn - values = yamlencode({ - "image" : { - "tag" : "v1.21.2" - } - }) - argo_sync_policy = { "automated" : {} "syncOptions" = ["CreateNamespace=true"] diff --git a/examples/basic/providers.tf b/examples/basic/providers.tf index e8369d1..f18aaaa 100644 --- a/examples/basic/providers.tf +++ b/examples/basic/providers.tf @@ -10,10 +10,16 @@ data "aws_eks_cluster_auth" "this" { name = module.eks_cluster.eks_cluster_id } +provider "kubernetes" { + host = data.aws_eks_cluster.this.endpoint + token = data.aws_eks_cluster_auth.this.token + cluster_ca_certificate = base64decode(data.aws_eks_cluster.this.certificate_authority[0].data) +} + provider "helm" { kubernetes { host = data.aws_eks_cluster.this.endpoint token = data.aws_eks_cluster_auth.this.token - cluster_ca_certificate = base64decode(data.aws_eks_cluster.this.certificate_authority.0.data) + cluster_ca_certificate = base64decode(data.aws_eks_cluster.this.certificate_authority[0].data) } } diff --git a/examples/basic/versions.tf b/examples/basic/versions.tf new file mode 100644 index 0000000..b19337f --- /dev/null +++ b/examples/basic/versions.tf @@ -0,0 +1,18 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.19.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.16.0" + } + helm = { + source = "hashicorp/helm" + version = ">= 2.6.0" + } + } +} diff --git a/iam.tf b/iam.tf index 7d0b8be..71fcd26 100644 --- a/iam.tf +++ b/iam.tf @@ -20,13 +20,13 @@ data "aws_iam_policy_document" "this" { "eks:DescribeNodegroup" ] + #checkov:skip=CKV_AWS_111: Ensure IAM policies does not allow write access without constraints resources = [ "*", ] effect = "Allow" } - } data "aws_iam_policy_document" "this_assume" { @@ -87,7 +87,7 @@ resource "aws_iam_role" "this" { } resource "aws_iam_role_policy_attachment" "this" { - count = local.irsa_role_create ? 1 : 0 + count = local.irsa_role_create && var.irsa_policy_enabled ? 1 : 0 role = aws_iam_role.this[0].name policy_arn = aws_iam_policy.this[0].arn } diff --git a/ll-logo.png b/ll-logo.png deleted file mode 100644 index 8aa2c6a..0000000 Binary files a/ll-logo.png and /dev/null differ diff --git a/outputs.tf b/outputs.tf index 39b56a3..20a3d23 100644 --- a/outputs.tf +++ b/outputs.tf @@ -10,10 +10,10 @@ output "helm_release_application_metadata" { output "kubernetes_application_attributes" { description = "Argo kubernetes manifest attributes" - value = try(kubernetes_manifest.this, {}) + value = try(kubernetes_manifest.this[0], {}) } output "iam_role_attributes" { - description = "Vector IAM role atributes" + description = "Cluster Autoscaler IAM role attributes" value = try(aws_iam_role.this[0], {}) } diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..41a7bea --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +checkov==2.2.158 diff --git a/variables.tf b/variables.tf index e74b3a7..d84fa4d 100644 --- a/variables.tf +++ b/variables.tf @@ -36,6 +36,7 @@ variable "helm_release_name" { default = "cluster-autoscaler" description = "Helm release name" } + variable "helm_repo_url" { type = string default = "https://kubernetes.github.io/autoscaler" @@ -54,6 +55,20 @@ variable "namespace" { description = "The K8s namespace in which the node-problem-detector service account has been created" } +variable "settings" { + type = map(any) + default = {} + description = "Additional helm sets which will be passed to the Helm chart values, see https://hub.helm.sh/charts/stable/<$addon-name>" +} + +variable "values" { + type = string + default = "" + description = "Additional yaml encoded values which will be passed to the Helm chart, see https://hub.helm.sh/charts/stable/<$addon-name>" +} + +# ================ IRSA variables (optional) ================ + variable "rbac_create" { type = bool default = true @@ -66,6 +81,12 @@ variable "service_account_create" { description = "Whether to create Service Account" } +variable "service_account_name" { + type = string + default = "cluster-autoscaler" + description = "The k8s <$addon-name> service account name" +} + variable "irsa_role_create" { type = bool default = true @@ -81,10 +102,11 @@ variable "irsa_policy_enabled" { variable "irsa_assume_role_enabled" { type = bool default = false - description = "Whether IRSA is allowed to assume role defined by assume_role_arn." + description = "Whether IRSA is allowed to assume role defined by irsa_assume_role_arn." } variable "irsa_assume_role_arn" { + type = string default = "" description = "Assume role arn. Assume role must be enabled." } @@ -98,37 +120,16 @@ variable "irsa_additional_policies" { variable "irsa_role_name_prefix" { type = string default = "cluster-autoscaler-irsa" - description = "The IRSA role name prefix for vector" + description = "The IRSA role name prefix for <$addon-name>" } -variable "service_account_name" { - default = "cluster-autoscaler" - description = "The k8s cluster-autoscaler service account name" -} - -variable "settings" { - type = map(any) - default = {} - description = "Additional helm sets which will be passed to the Helm chart values, see https://hub.helm.sh/charts/stable/cluster-autoscaler" -} - -variable "helm_set_sensitive" { - type = map(any) +variable "irsa_tags" { + type = map(string) default = {} - description = "Value block with custom sensitive values to be merged with the values yaml that won't be exposed in the plan's diff" + description = "IRSA resources tags" } -variable "helm_postrender" { - type = map(any) - default = {} - description = "Value block with a path to a binary file to run after helm renders the manifest which can alter the manifest contents" -} - -variable "values" { - type = string - default = "" - description = "Additional yaml encoded values which will be passed to the Helm chart, see https://hub.helm.sh/charts/stable/cluster-autoscaler" -} +# ================ argo variables (required) ================ variable "argo_namespace" { type = string @@ -148,6 +149,18 @@ variable "argo_helm_enabled" { description = "If set to true, the ArgoCD Application manifest will be deployed using Kubernetes provider as a Helm release. Otherwise it'll be deployed as a Kubernetes manifest. See Readme for more info" } +variable "argo_helm_wait_timeout" { + type = string + default = "10m" + description = "Timeout for ArgoCD Application Helm release wait job" +} + +variable "argo_helm_wait_backoff_limit" { + type = number + default = 6 + description = "Backoff limit for ArgoCD Application Helm release wait job" +} + variable "argo_destination_server" { type = string default = "https://kubernetes.default.svc" @@ -161,6 +174,10 @@ variable "argo_project" { } variable "argo_info" { + type = list(object({ + name = string + value = string + })) default = [{ "name" = "terraform" "value" = "true" @@ -169,10 +186,67 @@ variable "argo_info" { } variable "argo_sync_policy" { + type = any description = "ArgoCD syncPolicy manifest parameter" default = {} } +variable "argo_metadata" { + type = any + default = { + "finalizers" : [ + "resources-finalizer.argocd.argoproj.io" + ] + } + description = "ArgoCD Application metadata configuration. Override or create additional metadata parameters" +} + +variable "argo_apiversion" { + type = string + default = "argoproj.io/v1alpha1" + description = "ArgoCD Appliction apiVersion" +} + +variable "argo_spec" { + type = any + default = {} + description = "ArgoCD Application spec configuration. Override or create additional spec parameters" +} + +variable "argo_helm_values" { + type = string + default = "" + description = "Value overrides to use when deploying argo application object with helm" +} + +# ================ argo kubernetes manifest variables (required) ================ + +variable "argo_kubernetes_manifest_computed_fields" { + type = list(string) + default = ["metadata.labels", "metadata.annotations", "metadata.finalizers"] + description = "List of paths of fields to be handled as \"computed\". The user-configured value for the field will be overridden by any different value returned by the API after apply." +} + +variable "argo_kubernetes_manifest_field_manager_name" { + type = string + default = "Terraform" + description = "The name of the field manager to use when applying the kubernetes manifest resource. Defaults to Terraform" +} + +variable "argo_kubernetes_manifest_field_manager_force_conflicts" { + type = bool + default = false + description = "Forcibly override any field manager conflicts when applying the kubernetes manifest resource" +} + +variable "argo_kubernetes_manifest_wait_fields" { + type = map(string) + default = {} + description = "A map of fields and a corresponding regular expression with a pattern to wait for. The provider will wait until the field matches the regular expression. Use * for any value." +} + +# ================ helm release variables (required) ================ + variable "helm_repo_key_file" { type = string default = "" @@ -329,56 +403,14 @@ variable "helm_lint" { description = "Run the helm chart linter during the plan" } -variable "argo_metadata" { - default = { - "finalizers" : [ - "resources-finalizer.argocd.argoproj.io" - ] - } - description = "ArgoCD Application metadata configuration. Override or create additional metadata parameters" -} - -variable "argo_apiversion" { - default = "argoproj.io/v1alpha1" - description = "ArgoCD Appliction apiVersion" -} - -variable "argo_spec" { - default = {} - description = "ArgoCD Application spec configuration. Override or create additional spec parameters" -} - -variable "argo_helm_values" { - type = string - default = "" - description = "Value overrides to use when deploying argo application object with helm" -} - -variable "argo_kubernetes_manifest_computed_fields" { - type = list(string) - default = ["metadata.labels", "metadata.annotations"] - description = "List of paths of fields to be handled as \"computed\". The user-configured value for the field will be overridden by any different value returned by the API after apply." -} - -variable "argo_kubernetes_manifest_field_manager_name" { - default = "Terraform" - description = "The name of the field manager to use when applying the kubernetes manifest resource. Defaults to Terraform" -} - -variable "argo_kubernetes_manifest_field_manager_force_conflicts" { - type = bool - default = false - description = "Forcibly override any field manager conflicts when applying the kubernetes manifest resource" -} - -variable "argo_kubernetes_manifest_wait_fields" { - type = map(string) +variable "helm_set_sensitive" { + type = map(any) default = {} - description = "A map of fields and a corresponding regular expression with a pattern to wait for. The provider will wait until the field matches the regular expression. Use * for any value." + description = "Value block with custom sensitive values to be merged with the values yaml that won't be exposed in the plan's diff" } -variable "irsa_tags" { - type = map(string) +variable "helm_postrender" { + type = map(any) default = {} - description = "IRSA resources tags" + description = "Value block with a path to a binary file to run after helm renders the manifest which can alter the manifest contents" } diff --git a/versions.tf b/versions.tf index ea8c3a1..0fe7fd2 100644 --- a/versions.tf +++ b/versions.tf @@ -8,7 +8,7 @@ terraform { } kubernetes = { source = "hashicorp/kubernetes" - version = ">= 2.11.0" + version = ">= 2.16.0" } helm = { source = "hashicorp/helm"
"finalizers": [
"resources-finalizer.argocd.argoproj.io"
]
}