All Projects → oboukili → terraform-provider-argocd

oboukili / terraform-provider-argocd

Licence: MPL-2.0 license
Terraform provider for ArgoCD

Programming Languages

go
31211 projects - #10 most used programming language

Projects that are alternatives of or similar to terraform-provider-argocd

Terraform Provider Cloudflare
Cloudflare Terraform Provider
Stars: ✭ 208 (-15.1%)
Mutual labels:  terraform-provider
terraform-provider-tsuru
Terraform provider for tsuru
Stars: ✭ 17 (-93.06%)
Mutual labels:  terraform-provider
terraform-provider-twitter
No description or website provided.
Stars: ✭ 24 (-90.2%)
Mutual labels:  terraform-provider
Terraform Provider Openstack
Terraform OpenStack provider
Stars: ✭ 225 (-8.16%)
Mutual labels:  terraform-provider
Terraform Provider Vault
Terraform Vault provider
Stars: ✭ 244 (-0.41%)
Mutual labels:  terraform-provider
terraform-provider-external
Utility provider that exists to provide an interface between Terraform and external programs. Useful for integrating Terraform with a system for which a first-class provider does not exist.
Stars: ✭ 136 (-44.49%)
Mutual labels:  terraform-provider
Terraform Provider Sops
A Terraform provider for reading Mozilla sops files
Stars: ✭ 206 (-15.92%)
Mutual labels:  terraform-provider
terraform-provider-scaleway
Terraform Scaleway provider
Stars: ✭ 171 (-30.2%)
Mutual labels:  terraform-provider
Terraform Provider Auth0
Auth0 Terraform Provider
Stars: ✭ 252 (+2.86%)
Mutual labels:  terraform-provider
terraform-provider-logicmonitor
Terraform LogicMonitor provider.
Stars: ✭ 19 (-92.24%)
Mutual labels:  terraform-provider
Terraform Provider Keycloak
Terraform provider for Keycloak
Stars: ✭ 230 (-6.12%)
Mutual labels:  terraform-provider
Terraform Provider Unifi
Terraform provider for Unifi 📡
Stars: ✭ 239 (-2.45%)
Mutual labels:  terraform-provider
terraform-provider-hcp
Terraform provider for HashiCorp Cloud Platform.
Stars: ✭ 36 (-85.31%)
Mutual labels:  terraform-provider
Terraform Provider Datadog
Terraform Datadog provider
Stars: ✭ 213 (-13.06%)
Mutual labels:  terraform-provider
terraform-provider-commercetools
Terraform provider for commercetools
Stars: ✭ 58 (-76.33%)
Mutual labels:  terraform-provider
Terraform Provider Ibm
Terraform on IBM provider https://cloud.ibm.com/docs/ibm-cloud-provider-for-terraform?topic=ibm-cloud-provider-for-terraform-getting-started
Stars: ✭ 210 (-14.29%)
Mutual labels:  terraform-provider
terraform-provider-mysql
Terraform MySQL provider – This Terraform provider is archived per our provider archiving process: https://terraform.io/docs/internals/archiving.html
Stars: ✭ 59 (-75.92%)
Mutual labels:  terraform-provider
terraform-provider-circleci
Terraform provider for CircleCI
Stars: ✭ 94 (-61.63%)
Mutual labels:  terraform-provider
terraform-provider-rancher
Terraform Rancher provider
Stars: ✭ 35 (-85.71%)
Mutual labels:  terraform-provider
terraform-provider-oneview
Automates the provisioning of physical infrastructure from a private cloud using templates from HPE OneView with Terraform
Stars: ✭ 46 (-81.22%)
Mutual labels:  terraform-provider

Terraform Provider for ArgoCD

Tests


Compatibility promise

This provider is compatible with at least the last 2 minor releases of ArgoCD (e.g, ranging from 1.(n).m, to 1.(n-1).0, where n is the latest available minor version).

Older releases are not supported and some resources may not work as expected.


Requirements


Motivations

I thought ArgoCD already allowed for 100% declarative configuration?

While that is true through the use of ArgoCD Kubernetes Custom Resources, there are some resources that simply cannot be managed using Kubernetes manifests, such as project roles JWTs whose respective lifecycles are better handled by a tool like Terraform. Even more so when you need to export these JWTs to another external system using Terraform, like a CI platform.

Wouldn't using a Kubernetes provider to handle ArgoCD configuration be enough?

Existing Kubernetes providers do not patch arrays of objects, losing project role JWTs when doing small project changes just happen.

ArgoCD Kubernetes admission webhook controller is not as exhaustive as ArgoCD API validation, this can be seen with RBAC policies, where no validation occur when creating/patching a project.

Using Terraform to manage Kubernetes Custom Resource becomes increasingly difficult the further you use HCL2 DSL to merge different data structures and want to preserve type safety.

Whatever the Kubernetes CRD provider you are using, you will probably end up using locals and the yamlencode function which does not preserve the values' type. In these cases, not only the readability of your Terraform plan will worsen, but you will also be losing some safeties that Terraform provides in the process.


Installation

  • From Terraform Public Registry (TF >= 0.13.0)

    https://registry.terraform.io/providers/oboukili/argocd/latest

      terraform {
        required_providers {
          argocd = {
            source = "oboukili/argocd"
            version = "0.4.7"
          }
        }
      }
    
      provider "argocd" {
        # Configuration options
      }
  • From binary releases (TF >= 0.12.0, < 0.13): Get the latest release, or adapt and run the following:

    curl -LO https://github.com/oboukili/terraform-provider-argocd/releases/download/v0.1.0/terraform-provider-argocd_v0.1.0_linux_amd64.gz
    gunzip -N terraform-provider-argocd_v0.1.0_linux_amd64.gz
    mv terraform-provider-argocd_v0.1.0 ~/.terraform.d/plugins/linux_amd64/
    chmod +x ~/.terraform.d/plugins/linux_amd64/terraform-provider-argocd_v0.1.0
  • From source: Follow the 'contributing' build instructions.

Usage

provider "argocd" {
  server_addr = "argocd.local:443" # env ARGOCD_SERVER
  auth_token  = "1234..."          # env ARGOCD_AUTH_TOKEN
  # username  = "admin"            # env ARGOCD_AUTH_USERNAME
  # password  = "foo"              # env ARGOCD_AUTH_PASSWORD
  insecure    = false              # env ARGOCD_INSECURE
}

resource "argocd_cluster" "kubernetes" {
  server = "https://1.2.3.4:12345"
  name   = "mycluster"

  config {
    bearer_token = "eyJhbGciOiJSUzI..."

    tls_client_config {
      ca_data = base64encode(file("path/to/ca.pem"))
      // insecure = true
    }
  }
}

resource "argocd_repository_credentials" "private" {
  url             = "[email protected]"
  username        = "git"
  ssh_private_key = "-----BEGIN OPENSSH PRIVATE KEY-----\nfoo\nbar\n-----END OPENSSH PRIVATE KEY-----"
}

// Uses previously defined repository credentials
resource "argocd_repository" "private" {
  repo     = "[email protected]:somerepo.git"
  // insecure = true
}

resource "argocd_repository" "public_nginx_helm" {
  repo = "https://helm.nginx.com/stable"
  name = "nginx-stable"
  type = "helm"
}

resource "argocd_project" "myproject" {
  metadata {
    name      = "myproject"
    namespace = "argocd"
    labels = {
      acceptance = "true"
    }
    annotations = {
      "this.is.a.really.long.nested.key" = "yes, really!"
    }
  }

  spec {
    description  = "simple project"
    source_repos = ["*"]

    destination {
      server    = "https://kubernetes.default.svc"
      namespace = "default"
    }
    destination {
      server    = "https://kubernetes.default.svc"
      namespace = "foo"
    }
    cluster_resource_blacklist {
      group = "*"
      kind  = "*"
    }
    cluster_resource_whitelist {
      group = "rbac.authorization.k8s.io"
      kind  = "ClusterRoleBinding"
    }
    cluster_resource_whitelist {
      group = "rbac.authorization.k8s.io"
      kind  = "ClusterRole"
    }
    namespace_resource_blacklist {
      group = "networking.k8s.io"
      kind  = "Ingress"
    }
    namespace_resource_whitelist {
      group = "*"
      kind  = "*"
    }
    orphaned_resources {
      warn = true

      ignore {
        group = "apps/v1"
        kind  = "Deployment"
        name  = "ignored1"
      }
      ignore {
        group = "apps/v1"
        kind  = "Deployment"
        name  = "ignored2"
      }
    }
    role {
      name = "testrole"
      policies = [
        "p, proj:myproject:testrole, applications, override, myproject/*, allow",
        "p, proj:myproject:testrole, applications, sync, myproject/*, allow",
      ]
    }
    role {
      name = "anotherrole"
      policies = [
        "p, proj:myproject:testrole, applications, get, myproject/*, allow",
        "p, proj:myproject:testrole, applications, sync, myproject/*, deny",
      ]
    }
    sync_window {
      kind         = "allow"
      applications = ["api-*"]
      clusters     = ["*"]
      namespaces   = ["*"]
      duration     = "3600s"
      schedule     = "10 1 * * *"
      manual_sync  = true
    }
    sync_window {
      kind         = "deny"
      applications = ["foo"]
      clusters     = [
        "in-cluster",
        argocd_cluster.cluster.name,
      ]
      namespaces   = ["default"]
      duration     = "12h"
      schedule     = "22 1 5 * *"
      manual_sync  = false
    }
    signature_keys = [
      "4AEE18F83AFDEB23",
      "07E34825A909B250"
    ]
  }
}

resource "argocd_project_token" "secret" {
  count        = 20
  project      = argocd_project.myproject.metadata.0.name
  role         = "foobar"
  description  = "short lived token"
  expires_in   = "1h"
  renew_before = "30m"
}

resource "argocd_application" "kustomize" {
  metadata {
    name      = "kustomize-app"
    namespace = "argocd"
    labels = {
      test = "true"
    }
  }

  spec {
    project = argocd_project.myproject.metadata.0.name

    source {
      repo_url        = "https://github.com/kubernetes-sigs/kustomize"
      path            = "examples/helloWorld"
      target_revision = "release-kustomize-v3.7"
      kustomize {
        name_prefix = "foo-"
        name_suffix = "-bar"
        images      = ["hashicorp/terraform:light"]
        common_labels = {
          "this.is.a.common" = "la-bel"
          "another.io/one"   = "true" 
        }
      }
    }

    destination {
      server    = "https://kubernetes.default.svc"
      namespace = "foo"
    }

    sync_policy {
      automated {
        prune     = true
        self_heal = true
      }
      # Only available from ArgoCD 1.5.0 onwards
      sync_options = ["Validate=false"]
    }

    ignore_difference {
      group         = "apps"
      kind          = "Deployment"
      json_pointers = ["/spec/replicas"]
    }

    ignore_difference {
      group         = "apps"
      kind          = "StatefulSet"
      name          = "someStatefulSet"
      json_pointers = [
        "/spec/replicas",
        "/spec/template/spec/metadata/labels/bar",
      ]
    }
  }
}

resource "argocd_application" "helm" {
  metadata {
    name      = "helm-app"
    namespace = "argocd"
    labels = {
      test = "true"
    }
  }

  spec {
    source {
      repo_url        = "https://some.chart.repo.io"
      chart           = "mychart"
      target_revision = "1.2.3"
      helm {
        parameter {
          name  = "image.tag"
          value = "1.2.3"
        }
        parameter {
          name  = "someotherparameter"
          value = "true"
        }
        value_files = ["values-test.yml"]
        values      = <<EOT
someparameter:
  enabled: true
  someArray:
  - foo
  - bar    
EOT
        release_name = "testing"
      }
    }

    destination {
      server    = "https://kubernetes.default.svc"
      namespace = "default"
    }
  }
}

Contributing

Contributions are welcome! You'll first need a working installation of Go 1.14+. Just as a reminder. you will also need to correctly setup a GOPATH.

Building

Clone the repository within your GOPATH

mkdir -p $GOPATH/src/github.com/oboukili; cd $GOPATH/src/github.com/oboukili
git clone [email protected]:oboukili/terraform-provider-argocd

Then build the provider

cd $GOPATH/src/github.com/oboukili/terraform-provider-argocd
go build

Running tests

The acceptance tests run against a disposable ArgoCD installation within a Kind cluster. Other requirements are having a Docker daemon running and Kustomize installed.

make testacc_prepare_env
make testacc
make testacc_clean_env

Note: to speed up testing environment setup, it is highly recommended you pull all needed container images into your local registry first, as the setup tries to sideload the images within the Kind cluster upon cluster creation.

For example if you use Docker as your local container runtime:

docker pull quay.io/argoproj/argocd:v2.5.0
docker pull ghcr.io/dexidp/dex:v2.27.0
docker pull redis:6.2.4-alpine
docker pull alpine:3

Troubleshooting during local development


Credits

  • Thanks to JetBrains for providing a GoLand open source license to support the development of this provider.
  • Thanks to Keplr for allowing me to contribute to this side-project of mine during paid work hours.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].