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

Commit

Permalink
feat(controller): controller continued (#6)
Browse files Browse the repository at this point in the history
## Description

Continuing work on controller.

---------

Signed-off-by: Mateusz Urbanek <mateusz.urbanek.98@gmail.com>
  • Loading branch information
shanduur committed May 14, 2024
1 parent b96fb2f commit ef26c22
Show file tree
Hide file tree
Showing 32 changed files with 1,868 additions and 126 deletions.
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

0 comments on commit ef26c22

Please sign in to comment.