From 78485350dda935a1470f5eb6f1856216e7f237e6 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 --- modules/argocd/README.md | 38 +++++++++ modules/argocd/main.tf | 135 +++++++++++++++++++++++++++++++ modules/argocd/outputs.tf | 7 ++ modules/argocd/serviceaccount.tf | 47 +++++++++++ modules/argocd/variables.tf | 90 +++++++++++++++++++++ 5 files changed, 317 insertions(+) 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/modules/argocd/README.md b/modules/argocd/README.md new file mode 100644 index 0000000..ce7c423 --- /dev/null +++ b/modules/argocd/README.md @@ -0,0 +1,38 @@ +## 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\_id | A random generated to uniqly name cluster resources | `string` | n/a | yes | +| cluster\_location | The location (region or zone) in which the cluster master will be created. If you specify a zone (such as us-central1-a), the cluster will be a zonal cluster with a single cluster master. If you specify a region (such as us-west1), the cluster will be a regional cluster with multiple masters spread across zones in the region | `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 | +| jenkins\_x\_namespace | Kubernetes namespace to install Jenkins X in | `string` | n/a | yes | +| cluster\_network | The name of the network (VPC) to which the cluster is connected | `string` | `"default"` | no | +| cluster\_subnetwork | The name of the subnetwork to which the cluster is connected. Leave blank when using the 'default' vpc to generate a subnet for your cluster | `string` | `""` | no | +| content | Interpolated jx-requirements.yml | `string` | `""` | no | +| helm\_settings | 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\_operator\_version | The jx-git-operator helm chart version | `string` | `"0.0.192"` | no | +| jx\_git\_url | URL for the Jenins X cluster git repository | `string` | `""` | no | +| kuberhealthy | Enable Kuberhealthy helm installation | `bool` | `true` | 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..4f6721e --- /dev/null +++ b/modules/argocd/variables.tf @@ -0,0 +1,90 @@ +// ---------------------------------------------------------------------------- +// Required Variables +// ---------------------------------------------------------------------------- +variable "gcp_project" { + description = "The name of the GCP project" + type = string +} + +variable "cluster_location" { + description = "The location (region or zone) in which the cluster master will be created. If you specify a zone (such as us-central1-a), the cluster will be a zonal cluster with a single cluster master. If you specify a region (such as us-west1), the cluster will be a regional cluster with multiple masters spread across zones in the region" + type = string +} + +variable "cluster_network" { + description = "The name of the network (VPC) to which the cluster is connected" + type = string + default = "default" +} + +variable "cluster_subnetwork" { + description = "The name of the subnetwork to which the cluster is connected. Leave blank when using the 'default' vpc to generate a subnet for your cluster" + type = string + default = "" +} + +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 +} + +variable "jenkins_x_namespace" { + description = "Kubernetes namespace to install Jenkins X in" + type = string +} + +variable "cluster_id" { + description = "A random generated to uniqly name cluster resources" + 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 "jx_git_operator_version" { + description = "The jx-git-operator helm chart version" + type = string + default = "0.0.192" +} + +variable "kuberhealthy" { + description = "Enable Kuberhealthy helm installation" + type = bool + default = true +} + +variable "content" { + description = "Interpolated jx-requirements.yml" + 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 = {} +}