Skip to content
This repository has been archived by the owner on Jul 17, 2024. It is now read-only.

feat(controller): controller continued #6

Merged
merged 5 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .chainsaw.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Configuration
metadata:
name: config
spec:
timeouts:
apply: 45s
assert: 300s
cleanup: 45s
delete: 25s
error: 10s
exec: 45s
skipDelete: false
failFast: true
parallel: 4
28 changes: 28 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
; https://editorconfig.org/
root = true

[*]
charset = utf-8
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[boilerplate.go.txt]
insert_final_newline = false

[{Makefile,go.mod,go.sum,*.go,.gitmodules}]
indent_size = 4
indent_style = tab

[*.md]
indent_size = 4
trim_trailing_whitespace = false
eclint_indent_style = unset

[*.py]
indent_size = 4
indent_style = space

[Dockerfile]
indent_size = 4
64 changes: 64 additions & 0 deletions .github/workflows/commands.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: commands

on: [issue_comment]

jobs:
test-e2e:
runs-on: ubuntu-latest
if: ${{ startsWith(github.event.comment.body, '/ok-to-test') && github.event.issue.pull_request }}
steps:
- uses: TheModdingInquisition/actions-team-membership@v1.0
with:
organization: anza-labs
team: core
token: ${{ secrets.READ_ORG }}
comment: ":red_circle: I'm sorry @${{ github.event.comment.user.login }}, I'm afraid I can't do that."
exit: true
- uses: actions/checkout@v2
- env:
GH_TOKEN: ${{ github.token }}
run: |
gh pr checkout ${{ github.event.issue.number }}
- uses: actions/setup-go@v5
with:
go-version-file: ./go.mod
cache: false
- uses: actions/setup-python@v5
with:
python-version: '3.x'
check-latest: true
- run: |
pip install poetry
poetry install
- uses: helm/kind-action@v1
with:
cluster_name: e2e
- uses: docker/build-push-action@v5
with:
tags: lke-operator:e2e
build-args: VERSION=e2e
- run: |
kind load docker-image --name=e2e lke-operator:e2e
kubectl create namespace test-shared
kubectl create secret generic \
--namespace=test-shared \
--from-literal='LINODE_TOKEN=${{ secrets.LINODE_TOKEN }}' \
test-token
- run: |
make install deploy IMG=lke-operator:e2e
- run: |
test-e2e CHAINSAW_ARGS='--report-format=XML'
id: e2e
continue-on-error: true
- run: |
{
echo 'markdown<<EOF'
poetry run report
echo 'EOF'
} >> "${GITHUB_OUTPUT}"
if: ${{ success() || failure() }}
id: report
- uses: marocchino/sticky-pull-request-comment@v2
with:
message: ${{ steps.report.outputs.markdown }}
number: ${{ github.event.issue.number }}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: linters
name: linters-tests

on:
pull_request:
Expand Down Expand Up @@ -46,3 +46,14 @@ jobs:
with:
dockerfile: Dockerfile
recursive: true

tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: ./go.mod
cache: false
- run: |
make test
14 changes: 8 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Image URL to use all building/pushing image targets
IMG ?= gchr.io/anza-labs/lke-operator:canary
IMG ?= ghcr.io/anza-labs/lke-operator:main
PLATFORM ?= linux/$(shell go env GOARCH)
CHAINSAW_ARGS ?=

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
Expand Down Expand Up @@ -69,11 +70,11 @@ vet: ## Run go vet against code.

.PHONY: test
test: manifests generate fmt vet ## Run tests.
go test ./...
go test -cover -race -covermode=atomic ./...

.PHONY: test-e2e
test-e2e: ## Run the e2e tests against a k8s instance using Kyverno Chainsaw.
$(CHAINSAW) test
test-e2e: chainsaw ## Run the e2e tests against a k8s instance using Kyverno Chainsaw.
$(CHAINSAW) test ${CHAINSAW_ARGS}

.PHONY: lint
lint: golangci-lint ## Run golangci-lint linter & yamllint
Expand All @@ -98,7 +99,7 @@ docker-push: ## Push docker image with the manager.
.PHONY: build-installer
build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment.
mkdir -p dist
cd config/manager && $(KUSTOMIZE) edit set image ghcr.io/anza-labs/lke-operator:canary=${IMG}
cd config/manager && $(KUSTOMIZE) edit set image ghcr.io/anza-labs/lke-operator:main=${IMG}
$(KUSTOMIZE) build config/default > dist/install.yaml

##@ Deployment
Expand All @@ -117,8 +118,9 @@ uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified

.PHONY: deploy
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
cd config/manager && $(KUSTOMIZE) edit set image ghcr.io/anza-labs/lke-operator:main=${IMG}
$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -
$(KUBECTL) wait --for=condition=Available -n=lke-operator-system deployments.apps/lke-operator-controller-manager

.PHONY: undeploy
undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
Expand Down
70 changes: 57 additions & 13 deletions api/v1alpha1/lkeclusterconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ import (
// LKEClusterConfigSpec defines the desired state of an LKEClusterConfig resource.
type LKEClusterConfigSpec struct {
// Region is the geographical region where the LKE cluster will be provisioned.
// +required
// +kubebuilder:validation:required
Region string `json:"region"`

// TokenSecretRef references the Kubernetes secret that stores the Linode API token.
// If not provided, then default token will be used.
// +kubebuilder:validation:required
TokenSecretRef SecretRef `json:"tokenSecretRef"`

// HighAvailability specifies whether the LKE cluster should be configured for high
Expand All @@ -37,8 +38,9 @@ type LKEClusterConfigSpec struct {
HighAvailability *bool `json:"highAvailability,omitempty"`

// NodePools contains the specifications for each node pool within the LKE cluster.
// +kubebuilder:validation:MinItems=1
NodePools []LKENodePool `json:"nodePools"`
// +kubebuilder:validation:required
// +kubebuilder:validation:minProperties=1
NodePools map[string]LKENodePool `json:"nodePools"`

// KubernetesVersion indicates the Kubernetes version of the LKE cluster.
// +kubebuilder:validation:optional
Expand All @@ -55,28 +57,50 @@ type SecretRef struct {
// LKENodePool represents a pool of nodes within the LKE cluster.
type LKENodePool struct {
// NodeCount specifies the number of nodes in the node pool.
// +kubebuilder:default=3
// +kubebuilder:validation:required
NodeCount int `json:"nodeCount"`

// LinodeType specifies the Linode instance type for the nodes in the pool.
// +kubebuilder:default=g6-standard-1
// +kubebuilder:validation:required
LinodeType string `json:"linodeType"`

// Autoscaler specifies the autoscaling configuration for the node pool.
// +kubebuilder:validation:optional
Autoscaler *LKENodePoolAutoscaler `json:"autoscaler,omitempty"`
}

func (l LKENodePool) IsEqual(cmp LKENodePool) bool {
if l.NodeCount != cmp.NodeCount {
return false
}

if l.LinodeType != cmp.LinodeType {
return false
}

if l.Autoscaler == nil && cmp.Autoscaler == nil {
return true
}

if l.Autoscaler == nil || cmp.Autoscaler == nil {
return false
}

return l.Autoscaler.Min == cmp.Autoscaler.Min && l.Autoscaler.Max == cmp.Autoscaler.Max
}

// LKENodePoolAutoscaler represents the autoscaler configuration for a node pool.
type LKENodePoolAutoscaler struct {
// Min specifies the minimum number of nodes in the pool.
// +kubebuilder:validation:Minimum=0
// +kubebuilder:validation:Maximum=100
// +kubebuilder:validation:required
// +kubebuilder:validation:minimum=0
// +kubebuilder:validation:maximum=100
Min int `json:"min"`

// Max specifies the maximum number of nodes in the pool.
// +kubebuilder:validation:Minimum=3
// +kubebuilder:validation:Maximum=100
// +kubebuilder:validation:required
// +kubebuilder:validation:minimum=3
// +kubebuilder:validation:maximum=100
Max int `json:"max"`
}

Expand All @@ -91,15 +115,30 @@ type LKEClusterConfigStatus struct {
// +kubebuilder:validation:optional
ClusterID *int `json:"clusterID,omitempty"`

// NodePoolsIDs contains the IDs of the provisioned node pools within the LKE cluster.
// NodePoolStatuses contains the Status of the provisioned node pools within the LKE cluster.
// +kubebuilder:validation:optional
NodePoolsIDs []int `json:"nodePoolIDs,omitempty"`
NodePoolStatuses map[string]NodePoolStatus `json:"nodePoolStatuses,omitempty"`

// FailureMessage contains an optional failure message for the LKE cluster.
// +kubebuilder:validation:optional
FailureMessage *string `json:"failureMessage,omitempty"`
}

// NodePoolStatus
type NodePoolStatus struct {
// ID
// +kubebuilder:validation:optional
ID *int `json:"id,omitempty"`

// NodePoolDetails
// +kubebuilder:validation:required
NodePoolDetails LKENodePool `json:"details"`
}

func (n NodePoolStatus) IsEqual(cmp NodePoolStatus) bool {
return n.NodePoolDetails.IsEqual(cmp.NodePoolDetails)
}

// +kubebuilder:validation:Enum=Active;Deleting;Provisioning;Unknown;Updating
type Phase string

Expand All @@ -111,9 +150,14 @@ const (
PhaseUnknown Phase = "Unknown"
)

//+kubebuilder:object:root=true
// +kubebuilder:object:root=true

// LKEClusterConfig is the Schema for the lkeclusterconfigs API.
// +kubebuilder:resource:shortName=lkecc
// +kubebuilder:printcolumn:name=Region,type=string,JSONPath=`.spec.region`
// +kubebuilder:printcolumn:name=K8sVersion,type=string,JSONPath=`.spec.kubernetesVersion`
// +kubebuilder:printcolumn:name=Phase,type=string,JSONPath=`.status.phase`
// +kubebuilder:printcolumn:name=FailureMessage,type=string,JSONPath=`.status.failureMessage`
type LKEClusterConfig struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand All @@ -122,7 +166,7 @@ type LKEClusterConfig struct {
Status LKEClusterConfigStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true
// +kubebuilder:object:root=true

// LKEClusterConfigList contains a list of LKEClusterConfig
type LKEClusterConfigList struct {
Expand Down
37 changes: 30 additions & 7 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading