Skip to content

Commit 20963e2

Browse files
authored
init argocd_project resource (#6)
feature: argocd_project_resource
1 parent 9b48b14 commit 20963e2

22 files changed

+1794
-213
lines changed

.github/workflows/acceptance.yml

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ jobs:
88
acceptance_tests:
99
name: Acceptance Tests
1010
runs-on: [ubuntu-latest]
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
argocd_version: ["v1.5.2", "v1.4.3"]
1115
steps:
1216
- uses: actions/checkout@v1
1317
- uses: actions/setup-go@v1
@@ -22,37 +26,17 @@ jobs:
2226
restore-keys: |
2327
${{ runner.os }}-go-
2428
25-
- name: Install bitnami/bcrypt-cli
26-
run: GO111MODULE=on go get github.com/bitnami/bcrypt-cli
27-
2829
- name: Install Kind
2930
run: GO111MODULE=on go get sigs.k8s.io/kind
3031

31-
- name: Create Kind cluster
32-
run: PATH=$(go env GOPATH)/bin:$PATH kind create cluster --name argocd
33-
34-
- name: Run Kind sanity checks
35-
run: |
36-
kubectl get nodes -o wide
37-
kubectl get pods --all-namespaces -o wide
38-
kubectl get services --all-namespaces -o wide
39-
40-
- name: Set up ArgoCD 1.5.0
32+
- name: Set up ArgoCD ${{ matrix.argocd_version }}
33+
env:
34+
ARGOCD_VERSION: ${{ matrix.argocd_version }}
4135
run: |
42-
export PATH=${PATH}:$(go env GOPATH)/bin &&
43-
kubectl create namespace argocd &&
44-
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v1.5.0/manifests/install.yaml &&
45-
kubectl patch -n argocd secret/argocd-secret --type merge -p '{"stringData":{"admin.password":"'$(echo -n acceptancetesting|bcrypt-cli)'"}}' &&
46-
kubectl apply -n argocd -f manifests/argocd-project.yml &&
47-
kubectl wait --for=condition=available --timeout=600s deployment/argocd-server -n argocd &&
36+
sh scripts/testacc_prepare_env.sh
4837
kubectl port-forward -n argocd service/argocd-server --address 127.0.0.1 8080:443&
4938
until $(nc -z 127.0.0.1 8080); do sleep 2;done
5039
netstat -tulpn
5140
5241
- name: Run acceptance tests
53-
run: >
54-
ARGOCD_INSECURE=true
55-
ARGOCD_SERVER=127.0.0.1:8080
56-
ARGOCD_AUTH_USERNAME=admin
57-
ARGOCD_AUTH_PASSWORD=acceptancetesting
58-
TF_ACC=1 go test $(go list ./... |grep -v 'vendor') -v -timeout 5m
42+
run: sh scripts/testacc.sh

GNUmakefile

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,10 @@ test: fmt
1515
xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4
1616

1717
testacc_prepare_env:
18-
kind create cluster --name argocd && \
19-
kubectl create namespace argocd && \
20-
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v1.5.0/manifests/install.yaml && \
21-
kubectl patch -n argocd secret/argocd-secret --type merge -p '{"stringData":{"admin.password":"$$2a$10$Oc4i/CTPPCrbbeAIrwgmzeCg.wzEtCZd2HQz5gZOnPNlBekm.FVta"}}' && \
22-
kubectl apply -n argocd -f manifests/argocd-project.yml && \
23-
kubectl wait --for=condition=available --timeout=300s deployment/argocd-server -n argocd && \
24-
export KPF_PID=$(kubectl port-forward -n argocd service/argocd-server --address 127.0.0.1 8080:443)
18+
sh scripts/testacc_prepare_env.sh
2519

2620
testacc:
27-
ARGOCD_INSECURE=true ARGOCD_SERVER=localhost:8080 \
28-
ARGOCD_AUTH_USERNAME=admin ARGOCD_AUTH_PASSWORD=acceptancetesting \
29-
TF_ACC=1 go test $(TEST) -v -timeout 5m
21+
sh scripts/testacc.sh
3022

3123
testacc_clean_env:
3224
kind delete cluster --name argocd

README.md

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,31 @@
99
- [Terraform](https://www.terraform.io/downloads.html) 0.12.x
1010
- [Go](https://golang.org/doc/install) 1.14+
1111

12+
---
13+
14+
## Motivations
15+
16+
### *I thought ArgoCD already allowed for 100% declarative configuration?*
17+
18+
While that is true through the use of ArgoCD Kubernetes Custom Resources,
19+
there are some resources that simply cannot be managed using Kubernetes manifests,
20+
such as project roles JWTs whose respective lifecycles are better handled by a tool like Terraform.
21+
Even more so when you need to export these JWTs to another external system using Terraform, like a CI platform.
22+
23+
### *Wouldn't using a Kubernetes provider to handle ArgoCD configuration be enough?*
24+
25+
Existing Kubernetes providers do not patch arrays of objects, losing project role JWTs when doing small project changes just happen.
26+
27+
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.
28+
29+
Using Terraform to manage Kubernetes Custom Resource becomes increasingly difficult
30+
the further you use HCL2 DSL to merge different data structures *and* want to preserve type safety.
31+
32+
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**.
33+
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.
34+
35+
---
36+
1237
## Building
1338

1439
Clone the repository within your `GOPATH`
@@ -36,11 +61,72 @@ provider "argocd" {
3661
insecure = false # env ARGOCD_INSECURE
3762
}
3863
64+
resource "argocd_project" "myproject" {
65+
metadata {
66+
name = "myproject"
67+
namespace = "argocd"
68+
labels = {
69+
acceptance = "true"
70+
}
71+
annotations = {
72+
"this.is.a.really.long.nested.key" = "yes, really!"
73+
}
74+
}
75+
76+
spec {
77+
description = "simple project"
78+
source_repos = ["*"]
79+
80+
destination {
81+
server = "https://kubernetes.default.svc"
82+
namespace = "default"
83+
}
84+
destination {
85+
server = "https://kubernetes.default.svc"
86+
namespace = "foo"
87+
}
88+
cluster_resource_whitelist {
89+
group = "rbac.authorization.k8s.io"
90+
kind = "ClusterRoleBinding"
91+
}
92+
cluster_resource_whitelist {
93+
group = "rbac.authorization.k8s.io"
94+
kind = "ClusterRole"
95+
}
96+
namespace_resource_blacklist {
97+
group = "networking.k8s.io"
98+
kind = "Ingress"
99+
}
100+
orphaned_resources = {
101+
warn = true
102+
}
103+
sync_window {
104+
kind = "allow"
105+
applications = ["api-*"]
106+
clusters = ["*"]
107+
namespaces = ["*"]
108+
duration = "3600s"
109+
schedule = "10 1 * * *"
110+
manual_sync = true
111+
}
112+
sync_window {
113+
kind = "deny"
114+
applications = ["foo"]
115+
clusters = ["in-cluster"]
116+
namespaces = ["default"]
117+
duration = "12h"
118+
schedule = "22 1 5 * *"
119+
manual_sync = false
120+
}
121+
}
122+
}
123+
39124
resource "argocd_project_token" "secret" {
40-
project = "myproject"
41-
role = "bar"
125+
count = 20
126+
project = argocd_project.myproject.metadata.0.name
127+
role = "foobar"
42128
description = "short lived token"
43-
expires_in = "3600"
129+
expires_in = 3600
44130
}
45131
```
46132

argocd/provider.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func Provider() terraform.ResourceProvider {
3535
},
3636
AtLeastOneOf: []string{
3737
"password",
38+
"auth_token",
3839
},
3940
},
4041
"password": {
@@ -46,6 +47,7 @@ func Provider() terraform.ResourceProvider {
4647
},
4748
AtLeastOneOf: []string{
4849
"username",
50+
"auth_token",
4951
},
5052
},
5153
"cert_file": {
@@ -58,8 +60,9 @@ func Provider() terraform.ResourceProvider {
5860
Default: false,
5961
},
6062
"context": {
61-
Type: schema.TypeString,
62-
Optional: true,
63+
Type: schema.TypeString,
64+
Optional: true,
65+
DefaultFunc: schema.EnvDefaultFunc("ARGOCD_CONTEXT", nil),
6366
},
6467
"user_agent": {
6568
Type: schema.TypeString,
@@ -90,6 +93,7 @@ func Provider() terraform.ResourceProvider {
9093
},
9194

9295
ResourcesMap: map[string]*schema.Resource{
96+
"argocd_project": resourceArgoCDProject(),
9397
"argocd_project_token": resourceArgoCDProjectToken(),
9498
},
9599

argocd/provider_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import (
88
)
99

1010
var testAccProviders map[string]terraform.ResourceProvider
11+
var testAccProviderFactories func(providers *[]*schema.Provider) map[string]terraform.ResourceProviderFactory
1112
var testAccProvider *schema.Provider
13+
var testAccProviderFunc func() *schema.Provider
1214

1315
func init() {
1416
testAccProvider = Provider().(*schema.Provider)

0 commit comments

Comments
 (0)