From 8c389639f8f2b90b16fc00bf7fbd154a3c3cf756 Mon Sep 17 00:00:00 2001 From: joshuasimon-taulia Date: Thu, 20 Oct 2022 19:32:52 -0700 Subject: [PATCH] feat: argocd rough draft --- README.md | 1 + main.tf | 31 ++++++- modules/argocd/README.md | 30 +++++++ modules/argocd/main.tf | 135 +++++++++++++++++++++++++++++++ modules/argocd/outputs.tf | 7 ++ modules/argocd/serviceaccount.tf | 47 +++++++++++ modules/argocd/variables.tf | 45 +++++++++++ modules/cluster/main.tf | 2 +- modules/cluster/variables.tf | 6 ++ variables.tf | 6 ++ 10 files changed, 305 insertions(+), 5 deletions(-) create mode 100644 modules/argocd/README.md create mode 100644 modules/argocd/main.tf create mode 100644 modules/argocd/outputs.tf create mode 100644 modules/argocd/serviceaccount.tf create mode 100644 modules/argocd/variables.tf diff --git a/README.md b/README.md index 5d68a1f..4f247ce 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,7 @@ The following two paragraphs provide the full list of configuration and output v | gcp\_project | The name of the GCP project to use | `string` | n/a | yes | | git\_owner\_requirement\_repos | The git id of the owner for the requirement repositories | `string` | `""` | no | | gsm | Enables Google Secrets Manager, not available with JX2 | `bool` | `false` | no | +| argocd | Enables gitops sync via ArgoCD instead of git-operator | `bool` | `false` | no | | ip\_range\_pods | The IP range in CIDR notation to use for pods. Set to /netmask (e.g. /18) to have a range chosen with a specific netmask. Enables VPC-native | `string` | `""` | no | | ip\_range\_services | The IP range in CIDR notation use for services. Set to /netmask (e.g. /21) to have a range chosen with a specific netmask. Enables VPC-native | `string` | `""` | no | | jenkins\_x\_namespace | Kubernetes namespace to install Jenkins X in | `string` | `"jx"` | no | diff --git a/main.tf b/main.tf index 34df8ba..6458bc7 100644 --- a/main.tf +++ b/main.tf @@ -171,6 +171,7 @@ module "cluster" { jx_git_operator_version = var.jx_git_operator_version kuberhealthy = var.kuberhealthy + argocd = var.argocd } // ---------------------------------------------------------------------------- @@ -178,7 +179,7 @@ module "cluster" { // See https://github.com/banzaicloud/bank-vaults // ---------------------------------------------------------------------------- module "vault" { - count = !var.gsm ? 1 : 0 + count = ! var.gsm ? 1 : 0 source = "./modules/vault" gcp_project = var.gcp_project @@ -196,7 +197,7 @@ module "vault" { // See https://cloud.google.com/secret-manager // ---------------------------------------------------------------------------- module "gsm" { - count = var.gsm && !var.jx2 ? 1 : 0 + count = var.gsm && ! var.jx2 ? 1 : 0 source = "./modules/gsm" gcp_project = var.gcp_project @@ -249,7 +250,29 @@ module "dns" { module "jx-boot" { source = "./modules/jx-boot" depends_on = [module.cluster] - install_vault = !var.gsm ? true : false + install_vault = ! var.gsm ? true : false +} + +module "argocd" { + count = var.argocd ? 1 : 0 + source = "./modules/argocd" + depends_on = [module.cluster] + + gcp_project = var.gcp_project + cluster_name = local.cluster_name + apex_domain = var.apex_domain != "" ? var.apex_domain : var.parent_domain + cluster_location = local.location + cluster_network = var.cluster_network + cluster_subnetwork = var.cluster_subnetwork + cluster_id = random_id.random.hex + jenkins_x_namespace = var.jenkins_x_namespace + + content = local.content + + jx_git_url = var.jx_git_url + jx_bot_username = var.jx_bot_username + jx_bot_token = var.jx_bot_token + jx_git_operator_version = var.jx_git_operator_version } // ---------------------------------------------------------------------------- @@ -277,7 +300,7 @@ locals { vault_name = length(module.vault) > 0 ? module.vault[0].vault_name : "" vault_sa = length(module.vault) > 0 ? module.vault[0].vault_sa : "" vault_url = var.vault_url - vault_installed = !var.gsm ? true : false + vault_installed = ! var.gsm ? true : false // Velero enable_backup = var.enable_backup velero_sa = module.backup.velero_sa diff --git a/modules/argocd/README.md b/modules/argocd/README.md new file mode 100644 index 0000000..9b45b17 --- /dev/null +++ b/modules/argocd/README.md @@ -0,0 +1,30 @@ +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| google | n/a | +| helm | n/a | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| apex\_domain | The apex domain to be allocated to the cluster | `string` | n/a | yes | +| cluster\_name | Name of the Kubernetes cluster | `string` | n/a | yes | +| gcp\_project | The name of the GCP project | `string` | n/a | yes | +| helm\_values | Additional settings which will be passed to the Helm chart values, see https://artifacthub.io/packages/helm/argo/argo-cd | `map(any)` | `{}` | no | +| jx\_bot\_token | Bot token used to interact with the Jenkins X cluster git repository | `string` | `""` | no | +| jx\_bot\_username | Bot username used to interact with the Jenkins X cluster git repository | `string` | `""` | no | +| jx\_git\_url | URL for the Jenins X cluster git repository | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| argocd\_sa\_email | n/a | +| argocd\_sa\_name | n/a | + diff --git a/modules/argocd/main.tf b/modules/argocd/main.tf new file mode 100644 index 0000000..8539bb1 --- /dev/null +++ b/modules/argocd/main.tf @@ -0,0 +1,135 @@ +// ---------------------------------------------------------------------------- +// Create and configure the Argo CD installation +// +// ---------------------------------------------------------------------------- +locals {} + +resource "helm_release" "bootstrap" { + provider = helm + name = "argocd" + chart = "argo-cd" + namespace = "argocd" + repository = "https://argoproj.github.io/argo-helm" + version = "5.6.1" + create_namespace = true + values = [ + jsonencode( + { + "controller" : { + "serviceAccount" : { + "annotations" : { + "iam.gke.io/gcp-service-account" : "argocd-${var.cluster_name}@${var.gcp_project}.iam.gserviceaccount.com" + } + }, + }, + "repoServer" : { + "autoscaling" : { + "enabled" : true, + "minReplicas" : 2 + }, + "initContainers" : [ + { + "name" : "download-tools", + "image" : "ghcr.io/helmfile/helmfile:v0.147.0", + "command" : [ + "sh", + "-c" + ], + "args" : [ + "wget -qO /custom-tools/argo-cd-helmfile.sh https://raw.githubusercontent.com/travisghansen/argo-cd-helmfile/master/src/argo-cd-helmfile.sh && chmod +x /custom-tools/argo-cd-helmfile.sh && mv /usr/local/bin/helmfile /custom-tools/helmfile" + ], + "volumeMounts" : [ + { + "mountPath" : "/custom-tools", + "name" : "custom-tools" + } + ] + } + ], + "serviceAccount" : { + "annotations" : { + "iam.gke.io/gcp-service-account" : "argocd-${var.cluster_name}@${var.gcp_project}.iam.gserviceaccount.com" + } + }, + "volumes" : [ + { + "name" : "custom-tools", + "emptyDir" : {} + } + ], + "volumeMounts" : [ + { + "mountPath" : "/usr/local/bin/argo-cd-helmfile.sh", + "name" : "custom-tools", + "subPath" : "argo-cd-helmfile.sh" + }, + { + "mountPath" : "/usr/local/bin/helmfile", + "name" : "custom-tools", + "subPath" : "helmfile" + } + ] + }, + "server" : { + "autoscaling" : { + "enabled" : true, + "minReplicas" : 2 + } + "ingress" : { + "enabled" : true, + "annotations" : { + "nginx.ingress.kubernetes.io/backend-protocol" : "HTTPS", + "nginx.ingress.kubernetes.io/force-ssl-redirect" : "true", + "nginx.ingress.kubernetes.io/ssl-passthrough" : "true" + }, + "hosts" : [ + "argocd.${var.apex_domain}" + ], + "serviceAccount" : { + "annotations" : { + "iam.gke.io/gcp-service-account" : "argocd-${var.cluster_name}@${var.gcp_project}.iam.gserviceaccount.com" + } + } + } + } + } + ) + ] + + set { + name = "server.config.configManagementPlugins" + value = <<-EOT + - name: helmfile + init: # Optional command to initialize application source directory + command: ["argo-cd-helmfile.sh"] + args: ["init"] + generate: # Command to generate manifests YAML + command: ["argo-cd-helmfile.sh"] + args: ["generate"] + EOT + } + set { + name = "configs.credentialTemplates.https-creds.url" + value = regex("\\w+://\\w+\\.\\w+", var.jx_git_url) + } + set_sensitive { + name = "configs.credentialTemplates.https-creds.username" + value = var.jx_bot_username + } + set_sensitive { + name = "configs.credentialTemplates.https-creds.password" + value = var.jx_bot_token + } + + dynamic "set" { + for_each = var.helm_values + content { + name = set.key + value = set.value + } + } + + lifecycle { + # ignore_changes = all + } +} diff --git a/modules/argocd/outputs.tf b/modules/argocd/outputs.tf new file mode 100644 index 0000000..1fc1179 --- /dev/null +++ b/modules/argocd/outputs.tf @@ -0,0 +1,7 @@ +output "argocd_sa_email" { + value = google_service_account.argocd_sa.email +} + +output "argocd_sa_name" { + value = google_service_account.argocd_sa.name +} diff --git a/modules/argocd/serviceaccount.tf b/modules/argocd/serviceaccount.tf new file mode 100644 index 0000000..26cc576 --- /dev/null +++ b/modules/argocd/serviceaccount.tf @@ -0,0 +1,47 @@ +// ---------------------------------------------------------------------------- +// Setup GCloud Service Accounts +// +// https://www.terraform.io/docs/providers/google/r/google_service_account.html +// https://www.terraform.io/docs/providers/google/r/google_project_iam.html#google_project_iam_member +// ---------------------------------------------------------------------------- +// argocd +resource "google_service_account" "argocd_sa" { + provider = google + account_id = "argocd-${var.cluster_name}" + display_name = substr("ArgoCD service account for cluster ${var.cluster_name}", 0, 100) +} + +resource "google_project_iam_member" "argocd_sa_secret_manager_admin_binding" { + project = var.gcp_project + provider = google + role = "roles/secretmanager.admin" + member = "serviceAccount:${google_service_account.argocd_sa.email}" +} + +resource "google_project_iam_member" "argocd_sa_container_developer_binding" { + project = var.gcp_project + provider = google + role = "roles/container.developer" + member = "serviceAccount:${google_service_account.argocd_sa.email}" +} + +resource "google_service_account_iam_member" "argocd_app_controller_sa_workload_identity_user" { + provider = google + service_account_id = google_service_account.argocd_sa.name + role = "roles/iam.workloadIdentityUser" + member = "serviceAccount:${var.gcp_project}.svc.id.goog[argocd/argocd-application-controller]" +} + +resource "google_service_account_iam_member" "argocd_repo_server_sa_workload_identity_user" { + provider = google + service_account_id = google_service_account.argocd_sa.name + role = "roles/iam.workloadIdentityUser" + member = "serviceAccount:${var.gcp_project}.svc.id.goog[argocd/argocd-repo-server]" +} + +resource "google_service_account_iam_member" "argocd_server_sa_workload_identity_user" { + provider = google + service_account_id = google_service_account.argocd_sa.name + role = "roles/iam.workloadIdentityUser" + member = "serviceAccount:${var.gcp_project}.svc.id.goog[argocd/argocd-server]" +} diff --git a/modules/argocd/variables.tf b/modules/argocd/variables.tf new file mode 100644 index 0000000..b1a7394 --- /dev/null +++ b/modules/argocd/variables.tf @@ -0,0 +1,45 @@ +// ---------------------------------------------------------------------------- +// Required Variables +// ---------------------------------------------------------------------------- +variable "gcp_project" { + description = "The name of the GCP project" + type = string +} + +variable "cluster_name" { + description = "Name of the Kubernetes cluster" + type = string +} + +variable "apex_domain" { + description = "The apex domain to be allocated to the cluster" + type = string +} + +// ---------------------------------------------------------------------------- +// Optional Variables +// ---------------------------------------------------------------------------- + +variable "jx_git_url" { + description = "URL for the Jenins X cluster git repository" + type = string + default = "" +} + +variable "jx_bot_username" { + description = "Bot username used to interact with the Jenkins X cluster git repository" + type = string + default = "" +} + +variable "jx_bot_token" { + description = "Bot token used to interact with the Jenkins X cluster git repository" + type = string + default = "" +} + +variable "helm_values" { + type = map(any) + description = "Additional settings which will be passed to the Helm chart values, see https://artifacthub.io/packages/helm/argo/argo-cd" + default = {} +} diff --git a/modules/cluster/main.tf b/modules/cluster/main.tf index 1db743a..9bc9324 100644 --- a/modules/cluster/main.tf +++ b/modules/cluster/main.tf @@ -177,7 +177,7 @@ resource "kubernetes_config_map" "jenkins_x_requirements" { } resource "helm_release" "jx-git-operator" { - count = var.jx2 || var.jx_git_url == "" ? 0 : 1 + count = var.jx2 || var.argocd || var.jx_git_url == "" ? 0 : 1 provider = helm name = "jx-git-operator" diff --git a/modules/cluster/variables.tf b/modules/cluster/variables.tf index 85510ee..cdd7300 100644 --- a/modules/cluster/variables.tf +++ b/modules/cluster/variables.tf @@ -483,6 +483,12 @@ variable "kuberhealthy" { default = true } +variable "argocd" { + description = "Enables Argo CD instead of jx-git-operator" + type = bool + default = false +} + variable "content" { description = "Interpolated jx-requirements.yml" type = string diff --git a/variables.tf b/variables.tf index 653bf8d..9de6c93 100644 --- a/variables.tf +++ b/variables.tf @@ -297,6 +297,12 @@ variable "gsm" { default = false } +variable "argocd" { + description = "Enables Argo CD instead of jx-git-operator" + type = bool + default = false +} + variable "jx_git_url" { description = "URL for the Jenins X cluster git repository" type = string