Skip to content

Commit

Permalink
test: add more unit test and e2e tests
Browse files Browse the repository at this point in the history
Signed-off-by: peefy <[email protected]>
  • Loading branch information
Peefy committed Sep 3, 2024
1 parent 9df5bea commit c027156
Show file tree
Hide file tree
Showing 24 changed files with 3,628 additions and 247 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/backport.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: backport

on:
pull_request_target:
types: [closed, labeled]

permissions:
contents: read

jobs:
pull-request:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
if: github.event.pull_request.state == 'closed' && github.event.pull_request.merged && (github.event_name != 'labeled' || startsWith('backport:', github.event.label.name))
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Create backport PRs
uses: korthout/backport-action@be567af183754f6a5d831ae90f648954763f17f5 # v3.1.0
# xref: https://github.com/korthout/backport-action#inputs
with:
# Use token to allow workflows to be triggered for the created PR
github_token: ${{ secrets.DEPLOY_ACCESS_TOKEN }}
# Match labels with a pattern `backport:<target-branch>`
label_pattern: '^backport:([^ ]+)$'
# A bit shorter pull-request title than the default
pull_title: '[${target_branch}] ${pull_title}'
# Simpler PR description than default
pull_description: |-
Automated backport to `${target_branch}`, triggered by a label in #${pull_number}.
59 changes: 59 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,71 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Setup QEMU
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0
- name: Setup Docker Buildx
id: buildx
uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1
- name: Cache Docker layers
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
id: cache
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-ghcache-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-ghcache-
- name: Setup Go
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
with:
go-version: 1.22
cache-dependency-path: |
**/go.sum
**/go.mod
- name: Setup Kubernetes
uses: helm/kind-action@0025e74a8c7512023d06dc019c617aa3cf561fde # v1.10.0
with:
version: v0.20.0
cluster_name: kind
node_image: kindest/node:v1.27.3@sha256:3966ac761ae0136263ffdb6cfd4db23ef8a83cba8a463690e98317add2c9ba72
- name: Setup Kustomize
uses: fluxcd/pkg/actions/kustomize@main
- name: Enable integration tests
# Only run integration tests for main branch
if: github.ref == 'refs/heads/main'
run: |
echo 'GO_TEST_ARGS=-tags integration' >> $GITHUB_ENV
- name: Run tests
run: make test
- name: Build container image
run: |
make docker-build IMG=test/flux-kcl-controller:latest \
BUILD_PLATFORMS=linux/amd64 \
BUILD_ARGS="--cache-from=type=local,src=/tmp/.buildx-cache \
--cache-to=type=local,dest=/tmp/.buildx-cache-new,mode=max \
--load"
- # Temp fix
# https://github.com/docker/build-push-action/issues/252
# https://github.com/moby/buildkit/issues/1896
name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
- name: Load test image
run: kind load docker-image test/flux-kcl-controller:latest
- name: Install CRDs
run: make install
- name: Run default status test
run: |
kubectl apply -f config/testdata/status-defaults
RESULT=$(kubectl get kclrun status-defaults -o go-template={{.status}})
EXPECTED='map[observedGeneration:-1]'
if [ "${RESULT}" != "${EXPECTED}" ] ; then
echo -e "${RESULT}\n\ndoes not equal\n\n${EXPECTED}"
exit 1
fi
kubectl delete -f config/testdata/status-defaults
- name: Deploy Flux KCL controllers
run: |
make dev-deploy IMG=test/flux-kcl-controller:latest
kubectl -n source-system rollout status deploy/source-controller --timeout=1m
kubectl -n source-system rollout status deploy/kcl-controller --timeout=1m
65 changes: 61 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
IMG ?= ghcr.io/kcl-lang/flux-kcl-controller:v0.1.0
# Produce CRDs that work back to Kubernetes 1.16
CRD_OPTIONS ?= crd:crdVersions=v1
SOURCE_VER ?= $(shell go list -m all | grep github.com/fluxcd/source-controller/api | awk '{print $$2}')

# Use the same version of SOPS already referenced on go.mod
SOPS_VER := $(shell go list -m all | grep github.com/getsops/sops | awk '{print $$2}')

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
Expand All @@ -10,19 +14,35 @@ else
GOBIN=$(shell go env GOBIN)
endif

# Allows for defining additional Go test args, e.g. '-tags integration'.
GO_TEST_ARGS ?=
# Allows for defining additional Docker buildx arguments, e.g. '--push'.
BUILD_ARGS ?=
# Architectures to build images for.
BUILD_PLATFORMS ?= linux/amd64

# Architecture to use envtest with
ENVTEST_ARCH ?= amd64
# Paths to download the CRD dependencies at.
GITREPO_CRD ?= config/crd/bases/gitrepositories.yaml
BUCKET_CRD ?= config/crd/bases/buckets.yaml
OCIREPO_CRD ?= config/crd/bases/ocirepositories.yaml

# Keep a record of the version of the downloaded source CRDs. It is used to
# detect and download new CRDs when the SOURCE_VER changes.
SOURCE_CRD_VER=bin/.src-crd-$(SOURCE_VER)

PACKAGE ?= github.com/kcl-lang/flux-kcl-controller
INPUT_DIRS := $(PACKAGE)/api/v1alpha1
BOILERPLATE_PATH := ${PWD}/hack/boilerplate.go.txt

# API (doc) generation utilities
GEN_API_REF_DOCS_VERSION ?= e327d0730470cbd61b06300f81c5fcf91c23c113

all: manager

# Run tests
KUBEBUILDER_ASSETS?="$(shell $(ENVTEST) --arch=$(ENVTEST_ARCH) use -i $(ENVTEST_KUBERNETES_VERSION) --bin-dir=$(ENVTEST_ASSETS_DIR) -p path)"
test: generate tidy fmt vet manifests install-envtest
test: generate tidy fmt vet manifests download-crd-deps install-envtest $(SOPS)
KUBEBUILDER_ASSETS=$(KUBEBUILDER_ASSETS) go test ./... -coverprofile cover.out

# Build manager binary
Expand All @@ -33,6 +53,24 @@ manager: generate fmt vet
run: generate fmt vet manifests
go run ./cmd/main.go

# Delete previously downloaded CRDs and record the new version of the source
# CRDs.
$(SOURCE_CRD_VER):
rm -f bin/.src-crd*
$(MAKE) cleanup-crd-deps
if ! test -d "bin"; then mkdir -p bin; fi
touch $(SOURCE_CRD_VER)

# Download the CRDs the controller depends on FluxCD GitRepo, OCIRepo and Bucket.
download-crd-deps: $(SOURCE_CRD_VER)
curl -s https://raw.githubusercontent.com/fluxcd/source-controller/${SOURCE_VER}/config/crd/bases/source.toolkit.fluxcd.io_gitrepositories.yaml -o $(GITREPO_CRD)
curl -s https://raw.githubusercontent.com/fluxcd/source-controller/${SOURCE_VER}/config/crd/bases/source.toolkit.fluxcd.io_buckets.yaml -o $(BUCKET_CRD)
curl -s https://raw.githubusercontent.com/fluxcd/source-controller/${SOURCE_VER}/config/crd/bases/source.toolkit.fluxcd.io_ocirepositories.yaml -o $(OCIREPO_CRD)

# Delete the downloaded CRD dependencies.
cleanup-crd-deps:
rm -f $(GITREPO_CRD) $(BUCKET_CRD) $(OCIREPO_CRD)

# Install CRDs into a cluster
install: manifests
kustomize build config/crd | kubectl apply -f -
Expand All @@ -46,14 +84,22 @@ deploy: manifests
cd config/manager && kustomize edit set image kcl-controller=${IMG}
kustomize build config/default | kubectl apply -f -

# Deploy controller dev image in the configured Kubernetes cluster in ~/.kube/config
dev-deploy: manifests
mkdir -p config/dev && cp config/default/* config/dev
cd config/dev && kustomize edit set image fluxcd/kustomize-controller=${IMG}
kustomize build config/dev | kubectl apply -f -
rm -rf config/dev

# Undeploy controller in the configured Kubernetes cluster in ~/.kube/config
undeploy:
cd config/manager && kustomize edit set image kcl-controller=${IMG}
kustomize build config/default | kubectl delete -f -

# Generate manifests e.g. CRD, RBAC etc.
manifests: controller-gen
manifests: controller-gen deepcopy-gen
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=source-reader webhook paths="./..." output:crd:artifacts:config=config/crd/bases
$(DEEPCOPY_GEN) --input-dirs=$(INPUT_DIRS) --output-file-base=zz_generated.deepcopy --go-header-file=${BOILERPLATE_PATH}

# Run go tidy to cleanup go.mod
tidy:
Expand All @@ -72,8 +118,9 @@ build:
go build ./...

# Generate code
generate: controller-gen
generate: controller-gen deepcopy-gen
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
$(DEEPCOPY_GEN) --input-dirs=$(INPUT_DIRS) --output-file-base=zz_generated.deepcopy --go-header-file=${BOILERPLATE_PATH}

# Build the docker image
docker-build:
Expand Down Expand Up @@ -101,12 +148,22 @@ CONTROLLER_GEN_VERSION ?= v0.16.1
controller-gen: ## Download controller-gen locally if necessary.
$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_GEN_VERSION))

DEEPCOPY_GEN = $(shell pwd)/bin/deepcopy-gen
DEEPCOPY_GEN_VERSION ?= v0.29.0
.PHONY: deepcopy-gen
deepcopy-gen: ## Download controller-gen locally if necessary.
$(call go-install-tool,$(DEEPCOPY_GEN),k8s.io/code-generator/cmd/deepcopy-gen@$(DEEPCOPY_GEN_VERSION))

ENVTEST_ASSETS_DIR=$(shell pwd)/testbin
ENVTEST_KUBERNETES_VERSION?=latest
install-envtest: setup-envtest
mkdir -p ${ENVTEST_ASSETS_DIR}
$(ENVTEST) use $(ENVTEST_KUBERNETES_VERSION) --arch=$(ENVTEST_ARCH) --bin-dir=$(ENVTEST_ASSETS_DIR)

SOPS = $(GOBIN)/sops
$(SOPS): ## Download latest sops binary if none is found.
$(call go-install-tool,$(SOPS),github.com/getsops/sops/v3/cmd/sops@$(SOPS_VER))

ENVTEST = $(shell pwd)/bin/setup-envtest
.PHONY: envtest
setup-envtest: ## Download envtest-setup locally if necessary.
Expand Down
26 changes: 10 additions & 16 deletions api/v1alpha1/kclrun_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@ package v1alpha1
import (
"time"

kc "github.com/fluxcd/kustomize-controller/api/v1"
"github.com/fluxcd/pkg/apis/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)

const (
KCLRunKind = "KCLRun"
KCLRunFinalizer = "finalizers.fluxcd.io"
KCLRunFinalizer = "finalizers.krm.kcl.dev.fluxcd"
MaxConditionMessageLength = 20000
EnabledValue = "enabled"
DisabledValue = "disabled"
Expand Down Expand Up @@ -119,10 +117,6 @@ type KCLRunSpec struct {
// +optional
Path string `json:"path,omitempty" yaml:"path,omitempty"`

// Params are the parameters in key-value pairs format.
// +optional
Params map[string]runtime.RawExtension `json:"params,omitempty" yaml:"params,omitempty"`

// Config is the KCL compile config.
// +optional
Config *ConfigSpec `json:"config,omitempty" yaml:"config,omitempty"`
Expand All @@ -147,7 +141,7 @@ type KCLRunSpec struct {

// Reference of the source where the kcl file is.
// +required
SourceRef kc.CrossNamespaceSourceReference `json:"sourceRef"`
SourceRef CrossNamespaceSourceReference `json:"sourceRef"`

// This flag tells the controller to suspend subsequent kustomize executions,
// it does not apply to already started executions. Defaults to false.
Expand Down Expand Up @@ -274,26 +268,26 @@ func init() {
}

// GetConditions returns the status conditions of the object.
func (in KCLRun) GetConditions() []metav1.Condition {
func (in *KCLRun) GetConditions() []metav1.Condition {
return in.Status.Conditions
}

// SetConditions sets the status conditions on the object.
func (in KCLRun) SetConditions(conditions []metav1.Condition) {
func (in *KCLRun) SetConditions(conditions []metav1.Condition) {
in.Status.Conditions = conditions
}

// GetReleaseNamespace returns the configured TargetNamespace, or the namespace
// of the KCLRun.
func (in KCLRun) GetReleaseNamespace() string {
func (in *KCLRun) GetReleaseNamespace() string {
if in.Spec.TargetNamespace != "" {
return in.Spec.TargetNamespace
}
return in.Namespace
}

// GetTimeout returns the configured Timeout, or the default of 300s.
func (in KCLRun) GetTimeout() time.Duration {
func (in *KCLRun) GetTimeout() time.Duration {
duration := in.Spec.Interval.Duration - 30*time.Second
if in.Spec.Timeout != nil {
duration = in.Spec.Timeout.Duration
Expand All @@ -305,7 +299,7 @@ func (in KCLRun) GetTimeout() time.Duration {
}

// GetRetryInterval returns the retry interval
func (in KCLRun) GetRetryInterval() time.Duration {
func (in *KCLRun) GetRetryInterval() time.Duration {
if in.Spec.RetryInterval != nil {
return in.Spec.RetryInterval.Duration
}
Expand All @@ -314,18 +308,18 @@ func (in KCLRun) GetRetryInterval() time.Duration {

// GetRequeueAfter returns the duration after which the KCLRun must be
// reconciled again.
func (in KCLRun) GetRequeueAfter() time.Duration {
func (in *KCLRun) GetRequeueAfter() time.Duration {
return in.Spec.Interval.Duration
}

// GetDependsOn returns the list of dependencies across-namespaces.
func (in KCLRun) GetDependsOn() []meta.NamespacedObjectReference {
func (in *KCLRun) GetDependsOn() []meta.NamespacedObjectReference {
return in.Spec.DependsOn
}

// UsePersistentClient returns the configured PersistentClient, or the default
// of true.
func (in KCLRun) UsePersistentClient() bool {
func (in *KCLRun) UsePersistentClient() bool {
if in.Spec.PersistentClient == nil {
return true
}
Expand Down
14 changes: 14 additions & 0 deletions api/v1alpha1/kclrun_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"os"
"testing"

"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/runtime/conditions"
"github.com/stretchr/testify/assert"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/yaml"
Expand Down Expand Up @@ -39,3 +41,15 @@ func TestKCLRunDeserialize(t *testing.T) {
assert.Equal(t, "ConfigMap", kclRun.Spec.ArgumentsReferences[0].Kind)
assert.Equal(t, "config-map-reference", kclRun.Spec.ArgumentsReferences[0].Name)
}

func TestKCLRunConditions(t *testing.T) {
obj := &KCLRun{}
// Mark the object as ready.
conditions.MarkTrue(
obj,
meta.ReadyCondition,
meta.ReconciliationSucceededReason,
"Set ready condition is true",
)
assert.True(t, conditions.IsTrue(obj, meta.ReadyCondition))
}
Loading

0 comments on commit c027156

Please sign in to comment.