diff --git a/.github/workflows/build_test_ci.yml b/.github/workflows/build_test_ci.yml index 3a108b61b..25bd99091 100644 --- a/.github/workflows/build_test_ci.yml +++ b/.github/workflows/build_test_ci.yml @@ -89,6 +89,56 @@ jobs: - name: Nilcheck run: make nilcheck + e2e-test: + needs: [go-build-test, docker-build] + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@v2 + with: + disable-sudo: true + egress-policy: block + allowed-endpoints: > + api.github.com:443 + github.com:443 + gcr.io:443 + proxy.golang.org:443 + sum.golang.org:443 + *.githubusercontent.com:443 + docker.io:443 + registry-1.docker.io:443 + auth.docker.io:443 + production.cloudflare.docker.com:443 + storage.googleapis.com:443 + registry.k8s.io:443 + *.pkg.dev:443 + prod-registry-k8s-io-us-west-1.s3.dualstack.us-west-1.amazonaws.com:443 + *.blob.core.windows.net:443 + quay.io:443 + *.quay.io:443 + api.snapcraft.io:443 + + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 'stable' + + - name: Docker cache + uses: ScribeMD/docker-cache@0.3.7 + with: + key: docker-${{ runner.os }}-${{ hashFiles('Makefile') }}} + + - name: E2E test + run: make e2etest + + - uses: actions/upload-artifact@v4 + if: ${{ always() }} + with: + name: kind-logs + path: .kind/kind-logs-* + docker-build: runs-on: ubuntu-latest steps: @@ -114,7 +164,7 @@ jobs: - name: Docker cache uses: ScribeMD/docker-cache@0.3.7 with: - key: docker-${{ runner.os }}-${{ hashFiles('Dockerfile') }} + key: docker-${{ runner.os }}-${{ hashFiles('Makefile') }} - name: Build the Docker image run: make docker-build diff --git a/.gitignore b/.gitignore index dbc337bf9..938e4bfb2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store .idea bin/* +kind-logs-* cover.out kubeconfig diff --git a/.husky/hooks/pre-push b/.husky/hooks/pre-push index 49e0f6034..b6d65f136 100755 --- a/.husky/hooks/pre-push +++ b/.husky/hooks/pre-push @@ -13,7 +13,7 @@ if git status --short | grep -qv "??"; then trap unstash EXIT fi -make generate manifests +make generate manifests _setImage git diff --exit-code --quiet || (git status && exit 1) make lint gosec nilcheck test diff --git a/ctlptl-config.yaml b/.tilt/ctlptl-config.yaml similarity index 100% rename from ctlptl-config.yaml rename to .tilt/ctlptl-config.yaml diff --git a/Makefile b/Makefile index ac31bbd83..43946e6cc 100644 --- a/Makefile +++ b/Makefile @@ -88,6 +88,13 @@ vulncheck: govulncheck ## Run vulnerability check against code. test: manifests generate fmt vet envtest ## Run tests. KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test -race -timeout 60s ./... -coverprofile cover.out +.PHONY: e2etest +e2etest: kind kuttl kustomize clusterctl manifests generate docker-build + @echo -n "LINODE_TOKEN=$(LINODE_TOKEN)" > config/default/.env.linode + @$(CONTAINER_TOOL) tag ${IMG} capli-controller:e2e + IMG=capli-controller:e2e $(KUTTL) test --config e2e/kuttl-config.yaml + make _setImage + ##@ Build .PHONY: build @@ -140,9 +147,11 @@ install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~ uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. $(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f - -.PHONY: deploy -deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. +_setImage: kustomize cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} + +.PHONY: deploy +deploy: manifests kustomize _setImage ## Deploy controller to the K8s cluster specified in ~/.kube/config. $(KUSTOMIZE) build config/default | $(KUBECTL) apply -f - .PHONY: undeploy @@ -152,8 +161,8 @@ undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/confi .PHONY: tilt-cluster tilt-cluster: ctlptl tilt kind clusterctl @echo -n "LINODE_TOKEN=$(LINODE_TOKEN)" > config/default/.env.linode - $(CTLPTL) apply -f ctlptl-config.yaml - $(TILT) up + $(CTLPTL) apply -f .tilt/ctlptl-config.yaml + $(TILT) up --stream ##@ Build Dependencies @@ -171,6 +180,7 @@ CLUSTERCTL ?= $(LOCALBIN)/clusterctl CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen TILT ?= $(LOCALBIN)/tilt KIND ?= $(LOCALBIN)/kind +KUTTL ?= $(LOCALBIN)/kuttl ENVTEST ?= $(LOCALBIN)/setup-envtest HUSKY ?= $(LOCALBIN)/husky NILAWAY ?= $(LOCALBIN)/nilaway @@ -183,6 +193,7 @@ CLUSTERCTL_VERSION ?= v1.5.3 CONTROLLER_TOOLS_VERSION ?= v0.13.0 TILT_VERSION ?= 0.33.6 KIND_VERSION ?= 0.20.0 +KUTTL_VERSION ?= 0.15.0 HUSKY_VERSION ?= v0.2.16 NILAWAY_VERSION ?= latest GOVULNC_VERSION ?= v1.0.1 @@ -231,6 +242,12 @@ $(KIND): $(LOCALBIN) test -s $(KIND) && $(KIND) version | grep -q $(KIND_VERSION) || \ (cd $(LOCALBIN); curl -Lso ./kind https://github.com/kubernetes-sigs/kind/releases/download/v$(KIND_VERSION)/kind-$(OS)-$(ARCH_SHORT) && chmod +x kind) +.PHONY: kuttl +kuttl: $(KUTTL) ## Download kuttl locally if necessary. If wrong version is installed, it will be overwritten. +$(KUTTL): $(LOCALBIN) + test -s $(KUTTL) && $(KUTTL) version | grep -q $(KUTTL_VERSION) || \ + (cd $(LOCALBIN); curl -Lso ./kuttl https://github.com/kudobuilder/kuttl/releases/download/v$(KUTTL_VERSION)/kubectl-kuttl_$(KUTTL_VERSION)_$(OS)_$(ARCH) && chmod +x kuttl) + .PHONY: envtest envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. $(ENVTEST): $(LOCALBIN) diff --git a/README.md b/README.md index dcac5f330..a95d4a512 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,22 @@ # Cluster API Provider Linode A [Cluster API](https://cluster-api.sigs.k8s.io/) implementation for the [Linode](https://www.linode.com/) to create kubernetes clusters. +## Local development + +### Enable git hooks + +To enable automatic code validation on code push, execute the following commands: + +```bash +PATH="$PWD/bin:$PATH" make husky && husky install +``` + +If you temporary would like to disable git hook, set `SKIP_GIT_PUSH_HOOK` value: + +```bash +SKIP_GIT_PUSH_HOOK=1 git push +``` + ### Local development with Tilt For local development execute the following `make` target: @@ -10,3 +26,15 @@ LINODE_TOKEN= make tilt-cluster ``` This command creates a Kind cluster, and deploys resources via Tilt. You can freely change the code and wait for Tilt to update provider. + +### E2E testing + +For local development execute the following `make` target: + +```bash +LINODE_TOKEN= make e2etest +``` + +This command creates a Kind cluster, and executes all the defined tests. + +> Please ensure you have increased maximum open files on your host: https://kind.sigs.k8s.io/docs/user/known-issues/#pod-errors-due-to-too-many-open-files diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 5c5f0b84c..ad13e96b3 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -1,2 +1,8 @@ resources: - manager.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +images: +- name: controller + newName: controller + newTag: latest diff --git a/config/samples/infrastructure_v1alpha1_linodevpc.yaml b/config/samples/infrastructure_v1alpha1_linodevpc.yaml new file mode 100644 index 000000000..34ed757c4 --- /dev/null +++ b/config/samples/infrastructure_v1alpha1_linodevpc.yaml @@ -0,0 +1,12 @@ +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1 +kind: LinodeVPC +metadata: + labels: + app.kubernetes.io/name: linodevpc + app.kubernetes.io/instance: linodevpc-sample + app.kubernetes.io/part-of: cluster-api-provider-linode + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: cluster-api-provider-linode + name: linodevpc-sample +spec: + region: us-east diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index db7d2f6fa..69a2f69e0 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -4,4 +4,5 @@ resources: - infrastructure_v1alpha1_linodemachine.yaml - infrastructure_v1alpha1_linodemachinetemplate.yaml - infrastructure_v1alpha1_linodeclustertemplate.yaml +- infrastructure_v1alpha1_linodevpc.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/e2e/basic/cluster/00-assert.yaml b/e2e/basic/cluster/00-assert.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/e2e/basic/machine/00-assert.yaml b/e2e/basic/machine/00-assert.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/e2e/basic/vpc/00-assert.yaml b/e2e/basic/vpc/00-assert.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/e2e/kind-config.yaml b/e2e/kind-config.yaml new file mode 100644 index 000000000..93bbb102a --- /dev/null +++ b/e2e/kind-config.yaml @@ -0,0 +1,11 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +name: kuttl +nodes: +- role: control-plane + image: kindest/node:v1.28.0 + extraPortMappings: + - containerPort: 8080 + hostPort: 28080 + - containerPort: 8081 + hostPort: 28081 diff --git a/e2e/kuttl-config.yaml b/e2e/kuttl-config.yaml new file mode 100644 index 000000000..f9ddb49a7 --- /dev/null +++ b/e2e/kuttl-config.yaml @@ -0,0 +1,15 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestSuite +testDirs: +- e2e/basic +kindConfig: e2e/kind-config.yaml +kindContext: kuttl +startKIND: true +kindNodeCache: true +kindContainers: +- capli-controller:e2e +artifactsDir: .kind +timeout: 120 +commands: + - command: clusterctl init + - command: make deploy