Skip to content

Commit

Permalink
feat(operator): Add KeptnApplication controller (#137)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Implementation of the KeptnApp CRD and Controller. This modifies the behaviour of the KeptnWorkloadInstance and Keptn MutatingWebhook
  • Loading branch information
RealAnna authored Oct 13, 2022
1 parent 1639009 commit 271f5a8
Show file tree
Hide file tree
Showing 48 changed files with 1,903 additions and 499 deletions.
36 changes: 21 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,30 @@ TAG := $(TAG)
RELEASE_REGISTRY?=ghcr.io/keptn-sandbox
ARCH?=amd64

.PHONY: build-and-push-dev-images
build-and-push-dev-images:
RELEASE_TAG=$(TAG)
.PHONY: cleanup-manifests
cleanup-manifests:
rm -rf manifests

.PHONY: build-deploy-operator
build-deploy-operator: deploy-cert-manager
$(MAKE) -C operator release-local.$(ARCH) TAG=$(TAG)
$(MAKE) -C scheduler release-local.$(ARCH) TAG=$(TAG)
$(MAKE) -C operator push-local TAG=$(TAG)
$(MAKE) -C scheduler push-local TAG=$(TAG)

.PHONY: build-dev-manifests
build-dev-manifests:
$(MAKE) -C operator release-manifests TAG=$(TAG) ARCH=$(ARCH)

kubectl apply -f operator/config/rendered/release.yaml

.PHONY: build-deploy-scheduler
build-deploy-scheduler:
$(MAKE) -C scheduler release-local.$(ARCH) TAG=$(TAG)
$(MAKE) -C scheduler push-local TAG=$(TAG)
$(MAKE) -C scheduler release-manifests TAG=$(TAG) ARCH=$(ARCH)
if [[ ! -d manifests ]]; then mkdir manifests; fi
cat operator/config/rendered/release.yaml > manifests/dev.yaml
echo "---" >> manifests/dev.yaml
cat scheduler/config/rendered/release.yaml >> manifests/dev.yaml
kubectl create namespace keptn-lifecycle-controller-system --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f scheduler/config/rendered/release.yaml

.PHONY: build-deploy-dev-environment
build-deploy-dev-environment: build-and-push-dev-images build-dev-manifests
.PHONY: deploy-cert-manager
deploy-cert-manager:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml
kubectl apply -f manifests/dev.yaml

.PHONY: build-deploy-dev-environment
build-deploy-dev-environment: build-deploy-operator build-deploy-scheduler
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml
2 changes: 1 addition & 1 deletion examples/podtatohead-deployment/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
### Create Secret for Slack here

```
kubectl create secret generic slack-notification --from-literal=SECURE_DATA='{"slack_hook":"<WebHook>","text":"Deployed PodTatoHead Entry Service"}' -n podtato-kubectl -oyaml --dry-run > slack-secret.yaml
kubectl create secret generic slack-notification --from-literal=SECURE_DATA='{"slack_hook":"<WebHook>","text":"Deployed PodTatoHead Application"}' -n podtato-kubectl -oyaml --dry-run > slack-secret.yaml
```
22 changes: 22 additions & 0 deletions examples/podtatohead-deployment/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
apiVersion: lifecycle.keptn.sh/v1alpha1
kind: KeptnApp
metadata:
name: podtato-head
namespace: podtato-kubectl
spec:
version: "1.3"
workloads:
- name: podtato-head-left-arm
version: 0.1.0
- name: podtato-head-left-leg
version: 0.1.0
- name: podtato-head-entry
version: 0.1.0
- name: podtato-head-right-arm
version: 0.1.0
- name: podtato-head-left-arm
version: 0.1.0
- name: podtato-head-hat
version: 0.1.0
postDeploymentTasks:
- post-deployment-hello
1 change: 0 additions & 1 deletion examples/podtatohead-deployment/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ spec:
keptn.sh/app: podtato-head
keptn.sh/workload: podtato-head-entry
keptn.sh/version: 0.1.0
keptn.sh/post-deployment-tasks: post-deployment-hello
spec:
terminationGracePeriodSeconds: 5
initContainers:
Expand Down
4 changes: 2 additions & 2 deletions examples/single-service/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ spec:
app: test
annotations:
keptn.sh/workload: waiter
keptn.sh/version: "0.2"
keptn.sh/app: waiter
keptn.sh/version: "0.4"
keptn.sh/pre-deployment-tasks: pre-deployment-hello
keptn.sh/post-deployment-tasks: pre-deployment-hello

spec:
Expand Down
2 changes: 1 addition & 1 deletion examples/taskonly-hello-keptn/http/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ metadata:
spec:
taskDefinition: hello-keptn-http
workload: my-workload
workloadVersion: "1.0"
version: "1.0"
application: my-app
parameters:
map:
Expand Down
2 changes: 1 addition & 1 deletion examples/taskonly-hello-keptn/inline/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ metadata:
spec:
taskDefinition: hello-keptn-inline
workload: my-workload
workloadVersion: "1.0"
version: "1.0"
application: my-app
parameters:
map:
Expand Down
2 changes: 1 addition & 1 deletion examples/taskonly-hello-keptn/upstream/task.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ metadata:
spec:
taskDefinition: hello-keptn-upstream
workload: my-workload
workloadVersion: "1.0"
version: "1.0"
application: my-app
9 changes: 9 additions & 0 deletions operator/PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,13 @@ resources:
kind: KeptnWorkloadInstance
path: github.com/keptn-sandbox/lifecycle-controller/operator/api/v1alpha1
version: v1alpha1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: keptn.sh
group: lifecycle
kind: KeptnAppVersion
path: github.com/keptn-sandbox/lifecycle-controller/operator/api/v1alpha1
version: v1alpha1
version: "3"
93 changes: 79 additions & 14 deletions operator/api/v1alpha1/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package common

import (
"fmt"
"math/rand"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric/instrument/syncfloat64"
Expand All @@ -25,17 +26,70 @@ const MaxVersionLength = 12
type KeptnState string

const (
StateRunning KeptnState = "Running"
StateSucceeded KeptnState = "Succeeded"
StateFailed KeptnState = "Failed"
StateUnknown KeptnState = "Unknown"
StatePending KeptnState = "Pending"
StateProgressing KeptnState = "Progressing"
StateSucceeded KeptnState = "Succeeded"
StateFailed KeptnState = "Failed"
StateUnknown KeptnState = "Unknown"
StatePending KeptnState = "Pending"
)

var ErrTooLongAnnotations = fmt.Errorf("too long annotations, maximum length for app and workload is 25 characters, for version 12 characters")

func (k KeptnState) IsCompleted() bool {
return k == StateSucceeded || k == StateFailed || k == StateUnknown
return k == StateSucceeded || k == StateFailed
}

func (k KeptnState) IsSucceeded() bool {
return k == StateSucceeded
}

func (k KeptnState) IsFailed() bool {
return k == StateFailed
}

type StatusSummary struct {
Total int
progressing int
failed int
succeeded int
pending int
unknown int
}

func UpdateStatusSummary(status KeptnState, summary StatusSummary) StatusSummary {
switch status {
case StateFailed:
summary.failed++
case StateSucceeded:
summary.succeeded++
case StateProgressing:
summary.progressing++
case StatePending, "":
summary.pending++
case StateUnknown:
summary.unknown++
}
return summary
}

func (s StatusSummary) GetTotalCount() int {
return s.failed + s.succeeded + s.progressing + s.pending + s.unknown
}

func GetOverallState(s StatusSummary) KeptnState {
if s.failed > 0 {
return StateFailed
}
if s.progressing > 0 {
return StateProgressing
}
if s.pending > 0 {
return StatePending
}
if s.unknown > 0 || s.GetTotalCount() != s.Total {
return StateUnknown
}
return StateSucceeded
}

func TruncateString(s string, max int) string {
Expand All @@ -57,15 +111,26 @@ type KeptnMeters struct {
DeploymentCount syncint64.Counter
DeploymentDuration syncfloat64.Histogram
DeploymentActive syncint64.UpDownCounter
AppCount syncint64.Counter
AppDuration syncfloat64.Histogram
AppActive syncint64.UpDownCounter
}

const (
ApplicationName attribute.Key = attribute.Key("keptn.deployment.app_name")
Workload attribute.Key = attribute.Key("keptn.deployment.workload")
Version attribute.Key = attribute.Key("keptn.deployment.version")
Namespace attribute.Key = attribute.Key("keptn.deployment.namespace")
DeploymentStatus attribute.Key = attribute.Key("keptn.deployment.status")
TaskStatus attribute.Key = attribute.Key("keptn.deployment.task.status")
TaskName attribute.Key = attribute.Key("keptn.deployment.task.name")
TaskType attribute.Key = attribute.Key("keptn.deployment.taks.type")
AppName attribute.Key = attribute.Key("keptn.deployment.app.name")
AppVersion attribute.Key = attribute.Key("keptn.deployment.app.version")
AppNamespace attribute.Key = attribute.Key("keptn.deployment.app.namespace")
AppStatus attribute.Key = attribute.Key("keptn.deployment.app.status")
WorkloadName attribute.Key = attribute.Key("keptn.deployment.workload.name")
WorkloadVersion attribute.Key = attribute.Key("keptn.deployment.workload.version")
WorkloadNamespace attribute.Key = attribute.Key("keptn.deployment.workload.namespace")
WorkloadStatus attribute.Key = attribute.Key("keptn.deployment.workload.status")
TaskStatus attribute.Key = attribute.Key("keptn.deployment.task.status")
TaskName attribute.Key = attribute.Key("keptn.deployment.task.name")
TaskType attribute.Key = attribute.Key("keptn.deployment.task.type")
)

func GenerateTaskName(checkType CheckType, taskName string) string {
randomId := rand.Intn(99_999-10_000) + 10000
return fmt.Sprintf("%s-%s-%d", checkType, TruncateString(taskName, 32), randomId)
}
17 changes: 17 additions & 0 deletions operator/api/v1alpha1/common/phases.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package common

type KeptnPhase KeptnPhaseType

type KeptnPhaseType struct {
LongName string
ShortName string
}

var (
PhaseWorkloadPreDeployment = KeptnPhaseType{LongName: "Workload Pre-Deployment", ShortName: "WorkloadPreDeploy"}
PhaseWorkloadPostDeployment = KeptnPhaseType{LongName: "Workload Post-Deployment", ShortName: "WorkloadPostDeploy"}
PhaseWorkloadDeployment = KeptnPhaseType{LongName: "Workload Deployment", ShortName: "WorkloadDeploy"}
PhaseAppPreDeployment = KeptnPhaseType{LongName: "App Pre-Deployment", ShortName: "AppPreDeploy"}
PhaseAppPostDeployment = KeptnPhaseType{LongName: "App Post-Deployment", ShortName: "AppPostDeploy"}
PhaseAppDeployment = KeptnPhaseType{LongName: "App Deployment", ShortName: "AppDeploy"}
)
22 changes: 17 additions & 5 deletions operator/api/v1alpha1/keptnapp_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ limitations under the License.
package v1alpha1

import (
"github.com/keptn-sandbox/lifecycle-controller/operator/api/v1alpha1/common"
"strings"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand All @@ -26,14 +27,21 @@ import (

// KeptnAppSpec defines the desired state of KeptnApp
type KeptnAppSpec struct {
Workloads []KeptnWorkload `json:"workloads,omitempty"`
PreDeploymentTasks []string `json:"preDeploymentTasks,omitempty"`
PostDeploymentTasks []string `json:"postDeploymentTasks,omitempty"`
Version string `json:"version"`
Workloads []KeptnWorkloadRef `json:"workloads,omitempty"`
PreDeploymentTasks []string `json:"preDeploymentTasks,omitempty"`
PostDeploymentTasks []string `json:"postDeploymentTasks,omitempty"`
PreDeploymentAnalysis []string `json:"preDeploymentAnalysis,omitempty"`
PostDeploymentAnalysis []string `json:"postDeploymentAnalysis,omitempty"`
}

// KeptnAppStatus defines the observed state of KeptnApp
type KeptnAppStatus struct {
Status common.KeptnState `json:"status"`
}

type KeptnWorkloadRef struct {
Name string `json:"name"`
Version string `json:"version"`
}

//+kubebuilder:object:root=true
Expand All @@ -60,3 +68,7 @@ type KeptnAppList struct {
func init() {
SchemeBuilder.Register(&KeptnApp{}, &KeptnAppList{})
}

func (w KeptnApp) GetAppVersionName() string {
return strings.ToLower(w.Name + "-" + w.Spec.Version)
}
Loading

0 comments on commit 271f5a8

Please sign in to comment.