Skip to content

Commit

Permalink
feat: Allow specifying API Key via reference to an external Secret (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
ekampf authored Dec 19, 2023
1 parent 982e747 commit a028068
Show file tree
Hide file tree
Showing 14 changed files with 737 additions and 9 deletions.
13 changes: 12 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ jobs:
with:
dockerfile: Dockerfile

helm-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Go 1.21.x
uses: actions/setup-go@v4
with:
go-version: 1.21.x
- name: Run Helm Chart Golden Tests
run: go test -v ./...

unit-tests:
runs-on: ubuntu-latest
name: Unit tests
Expand Down Expand Up @@ -138,7 +149,7 @@ jobs:
release_dev:
runs-on: ubuntu-latest
name: Release dev
needs: [dockerfile-lint, unit-tests, e2e-tests, build]
needs: [dockerfile-lint, helm-tests, unit-tests, e2e-tests, build]
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
python 3.11.6
poetry 1.6.1
golang 1.21.3
golang 1.21.4
83 changes: 83 additions & 0 deletions deploy/golden_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package golden

import (
"flag"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"testing"

"github.com/gruntwork-io/terratest/modules/helm"
"gopkg.in/yaml.v2"
)

var update = flag.Bool("update", false, "update golden test output files")

type ChartYaml struct {
Name string `yaml:"name"`
Version string `yaml:"version"`
}

func GetChartYaml(t *testing.T) ChartYaml {
chartYamlFile, err := os.ReadFile("./twingate-operator/Chart.yaml")
if err != nil {
t.Fatalf("Error reading Chart.yaml: %v", err)
}

var chartYaml ChartYaml

if err := yaml.Unmarshal(chartYamlFile, &chartYaml); err != nil {
t.Fatalf("Error unmarshaling YAML data: %v", err)
}

return chartYaml
}

func TestHelmRender(t *testing.T) {
files, err := os.ReadDir("./test/golden")
if err != nil {
t.Fatal(err)
}

chartYaml := GetChartYaml(t)

for _, f := range files {
if !f.IsDir() && strings.HasSuffix(f.Name(), ".yaml") && !strings.HasSuffix(f.Name(), ".golden.yaml") {
// Render this values.yaml file
output := helm.RenderTemplate(t,
&helm.Options{
ValuesFiles: []string{"test/golden/" + f.Name()},
},
"./twingate-operator",
"test",
nil,
)

goldenFile := "test/golden/" + strings.TrimSuffix(f.Name(), filepath.Ext(".yaml")) + ".golden.yaml"

// Replace `cn.chart` helper value with a stable value for testing
regex := regexp.MustCompile(fmt.Sprintf("%s-%s", chartYaml.Name, chartYaml.Version))
bytes := regex.ReplaceAll([]byte(output), []byte(fmt.Sprintf("%s-major.minor.patch-test", chartYaml.Name)))
output = fmt.Sprintf("%s\n", string(bytes))

if *update {
err := os.WriteFile(goldenFile, []byte(output), 0644)
if err != nil {
t.Fatal(err)
}
}

expected, err := os.ReadFile(goldenFile)
if err != nil {
t.Fatal(err)
}

if string(expected) != output {
t.Fatalf("Expected %s, but got %s\n. Update golden files by running `go test -v ./... -update`", string(expected), output)
}
}

}
}
141 changes: 141 additions & 0 deletions deploy/test/golden/apikey.golden.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
---
# Source: twingate-operator/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: test-twingate-operator
namespace: default
labels:
helm.sh/chart: twingate-operator-major.minor.patch-test
app.kubernetes.io/name: twingate-operator
app.kubernetes.io/instance: test
app.kubernetes.io/managed-by: Helm
---
# Source: twingate-operator/templates/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: test-twingate-operator
namespace: default
labels:
helm.sh/chart: twingate-operator-major.minor.patch-test
app.kubernetes.io/name: twingate-operator
app.kubernetes.io/instance: test
app.kubernetes.io/managed-by: Helm
data:
TWINGATE_API_KEY: PGFwaSBrZXk+
---
# Source: twingate-operator/templates/clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: test-twingate-operator-role-cluster
rules:
# Framework: runtime observation of namespaces & CRDs (addition/deletion).
- apiGroups: [apiextensions.k8s.io]
resources: [customresourcedefinitions]
verbs: [list, watch]
- apiGroups: [""]
resources: [namespaces]
verbs: [list, watch]
- apiGroups: ["", "events.k8s.io"]
resources: [events]
verbs: ['*']

# Framework: admission webhook configuration management.
- apiGroups: [admissionregistration.k8s.io/v1, admissionregistration.k8s.io/v1beta1]
resources: [validatingwebhookconfigurations, mutatingwebhookconfigurations]
verbs: [create, patch]

# Application
- apiGroups: [twingate.com]
resources: [twingateresources, twingateresourceaccesses, twingateconnectors]
verbs: [list, watch, patch, get]
- apiGroups: ["*"]
resources: [pods, services, secrets]
verbs: [list, watch, patch, get]
---
# Source: twingate-operator/templates/clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: test-twingate-operator-rolebinding-cluster
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: test-twingate-operator-role-cluster
subjects:
- kind: ServiceAccount
name: test-twingate-operator
namespace: default
---
# Source: twingate-operator/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-twingate-operator
namespace: default
labels:
helm.sh/chart: twingate-operator-major.minor.patch-test
app.kubernetes.io/name: twingate-operator
app.kubernetes.io/instance: test
app.kubernetes.io/managed-by: Helm
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: twingate-operator
app.kubernetes.io/instance: test
template:
metadata:
labels:
app.kubernetes.io/name: twingate-operator
app.kubernetes.io/instance: test
spec:
serviceAccountName: test-twingate-operator
securityContext:
{}
containers:
- name: twingate-operator
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
image: "twingate/kubernetes-operator:latest"
imagePullPolicy: IfNotPresent
command:
- kopf
- run
- ./main.py
- "-A"
- "--standalone"
- "--verbose"
- "--liveness=http://0.0.0.0:8080/healthz"
- "--log-format=full"
env:
- name: TWINGATE_API_KEY
valueFrom:
secretKeyRef:
name: test-twingate-operator
key: TWINGATE_API_KEY
- name: TWINGATE_NETWORK
value: <network slug>
- name: TWINGATE_HOST
value: twingate.com
- name: TWINGATE_REMOTE_NETWORK_ID
value: <remote network id>
livenessProbe:
httpGet:
path: /healthz
port: 8080
readinessProbe:
httpGet:
path: /healthz
port: 8080
resources:
{}
4 changes: 4 additions & 0 deletions deploy/test/golden/apikey.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
twingateOperator:
apiKey: "<api key>"
network: "<network slug>"
remoteNetworkId: "<remote network id>"
127 changes: 127 additions & 0 deletions deploy/test/golden/existingAPIKeySecret.golden.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
---
# Source: twingate-operator/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: test-twingate-operator
namespace: default
labels:
helm.sh/chart: twingate-operator-major.minor.patch-test
app.kubernetes.io/name: twingate-operator
app.kubernetes.io/instance: test
app.kubernetes.io/managed-by: Helm
---
# Source: twingate-operator/templates/clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: test-twingate-operator-role-cluster
rules:
# Framework: runtime observation of namespaces & CRDs (addition/deletion).
- apiGroups: [apiextensions.k8s.io]
resources: [customresourcedefinitions]
verbs: [list, watch]
- apiGroups: [""]
resources: [namespaces]
verbs: [list, watch]
- apiGroups: ["", "events.k8s.io"]
resources: [events]
verbs: ['*']

# Framework: admission webhook configuration management.
- apiGroups: [admissionregistration.k8s.io/v1, admissionregistration.k8s.io/v1beta1]
resources: [validatingwebhookconfigurations, mutatingwebhookconfigurations]
verbs: [create, patch]

# Application
- apiGroups: [twingate.com]
resources: [twingateresources, twingateresourceaccesses, twingateconnectors]
verbs: [list, watch, patch, get]
- apiGroups: ["*"]
resources: [pods, services, secrets]
verbs: [list, watch, patch, get]
---
# Source: twingate-operator/templates/clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: test-twingate-operator-rolebinding-cluster
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: test-twingate-operator-role-cluster
subjects:
- kind: ServiceAccount
name: test-twingate-operator
namespace: default
---
# Source: twingate-operator/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-twingate-operator
namespace: default
labels:
helm.sh/chart: twingate-operator-major.minor.patch-test
app.kubernetes.io/name: twingate-operator
app.kubernetes.io/instance: test
app.kubernetes.io/managed-by: Helm
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: twingate-operator
app.kubernetes.io/instance: test
template:
metadata:
labels:
app.kubernetes.io/name: twingate-operator
app.kubernetes.io/instance: test
spec:
serviceAccountName: test-twingate-operator
securityContext:
{}
containers:
- name: twingate-operator
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
image: "twingate/kubernetes-operator:latest"
imagePullPolicy: IfNotPresent
command:
- kopf
- run
- ./main.py
- "-A"
- "--standalone"
- "--verbose"
- "--liveness=http://0.0.0.0:8080/healthz"
- "--log-format=full"
env:
- name: TWINGATE_API_KEY
valueFrom:
secretKeyRef:
name: my-secret
key: MY_TWINGATE_API_KEY
- name: TWINGATE_NETWORK
value: <network slug>
- name: TWINGATE_HOST
value: twingate.com
- name: TWINGATE_REMOTE_NETWORK_ID
value: <remote network id>
livenessProbe:
httpGet:
path: /healthz
port: 8080
readinessProbe:
httpGet:
path: /healthz
port: 8080
resources:
{}
6 changes: 6 additions & 0 deletions deploy/test/golden/existingAPIKeySecret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
twingateOperator:
existingAPIKeySecret:
name: my-secret
key: MY_TWINGATE_API_KEY
network: "<network slug>"
remoteNetworkId: "<remote network id>"
Loading

0 comments on commit a028068

Please sign in to comment.