Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(lifecycle-operator): introduce v1beta1 lifecycle API #2640

Merged
merged 23 commits into from
Dec 21, 2023
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
3,558 changes: 3,176 additions & 382 deletions .github/scripts/.helm-tests/default/result.yaml

Large diffs are not rendered by default.

3,386 changes: 3,090 additions & 296 deletions .github/scripts/.helm-tests/lifecycle-only/result.yaml

Large diffs are not rendered by default.

3,386 changes: 3,090 additions & 296 deletions .github/scripts/.helm-tests/lifecycle-with-certs/result.yaml

Large diffs are not rendered by default.

Large diffs are not rendered by default.

77 changes: 77 additions & 0 deletions lifecycle-operator/PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,80 @@ resources:
path: github.com/keptn/lifecycle-toolkit/lifecycle-operator/apis/lifecycle/v1alpha4
version: v1alpha4
version: "3"
- api:
crdVersion: v1
namespaced: true
domain: keptn.sh
group: lifecycle
kind: KeptnApp
path: github.com/keptn/lifecycle-toolkit/lifecycle-operator/apis/lifecycle/v1beta1
version: v1beta1
- api:
crdVersion: v1
namespaced: true
domain: keptn.sh
group: lifecycle
kind: KeptnAppVersion
path: github.com/keptn/lifecycle-toolkit/lifecycle-operator/apis/lifecycle/v1beta1
version: v1beta1
- api:
crdVersion: v1
namespaced: true
domain: keptn.sh
group: lifecycle
kind: KeptnEvaluation
path: github.com/keptn/lifecycle-toolkit/lifecycle-operator/apis/lifecycle/v1beta1
version: v1beta1
- api:
crdVersion: v1
namespaced: true
domain: keptn.sh
group: lifecycle
kind: KeptnEvaluationDefinition
path: github.com/keptn/lifecycle-toolkit/lifecycle-operator/apis/lifecycle/v1beta1
version: v1beta1
- api:
crdVersion: v1
namespaced: true
domain: keptn.sh
group: lifecycle
kind: KeptnTask
path: github.com/keptn/lifecycle-toolkit/lifecycle-operator/apis/lifecycle/v1beta1
version: v1beta1
- api:
crdVersion: v1
namespaced: true
domain: keptn.sh
group: lifecycle
kind: KeptnTaskDefinition
path: github.com/keptn/lifecycle-toolkit/lifecycle-operator/apis/lifecycle/v1beta1
version: v1beta1
webhooks:
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
domain: keptn.sh
group: lifecycle
kind: KeptnWorkload
path: github.com/keptn/lifecycle-toolkit/lifecycle-operator/apis/lifecycle/v1beta1
version: v1beta1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: keptn.sh
group: lifecycle
kind: KeptnAppCreationRequest
path: github.com/keptn/lifecycle-toolkit/lifecycle-operator/apis/lifecycle/v1beta1
version: v1beta1
- api:
crdVersion: v1
namespaced: true
domain: keptn.sh
group: lifecycle
kind: KeptnWorkloadVersion
path: github.com/keptn/lifecycle-toolkit/lifecycle-operator/apis/lifecycle/v1beta1
version: v1beta1
version: "3"
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type KeptnAppCreationRequestSpec struct {

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:storageversion

// KeptnAppCreationRequest is the Schema for the keptnappcreationrequests API
type KeptnAppCreationRequest struct {
Expand Down
214 changes: 214 additions & 0 deletions lifecycle-operator/apis/lifecycle/v1beta1/common/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
package common

import (
"crypto/sha256"
"encoding/hex"
"errors"
"math/rand"
"strconv"

operatorcommon "github.com/keptn/lifecycle-toolkit/lifecycle-operator/common"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const WorkloadAnnotation = "keptn.sh/workload"
const VersionAnnotation = "keptn.sh/version"
const AppAnnotation = "keptn.sh/app"
const PreDeploymentTaskAnnotation = "keptn.sh/pre-deployment-tasks"
const PostDeploymentTaskAnnotation = "keptn.sh/post-deployment-tasks"
const K8sRecommendedWorkloadAnnotations = "app.kubernetes.io/name"
const K8sRecommendedVersionAnnotations = "app.kubernetes.io/version"
const K8sRecommendedAppAnnotations = "app.kubernetes.io/part-of"
const K8sRecommendedManagedByAnnotations = "app.kubernetes.io/managed-by"
const PreDeploymentEvaluationAnnotation = "keptn.sh/pre-deployment-evaluations"
const PostDeploymentEvaluationAnnotation = "keptn.sh/post-deployment-evaluations"
const SchedulingGateRemoved = "keptn.sh/scheduling-gate-removed"
const TaskNameAnnotation = "keptn.sh/task-name"
const NamespaceEnabledAnnotation = "keptn.sh/lifecycle-toolkit"
const CreateAppTaskSpanName = "create_%s_app_task"
const CreateWorkloadTaskSpanName = "create_%s_deployment_task"
const CreateAppEvalSpanName = "create_%s_app_evaluation"
const CreateWorkloadEvalSpanName = "create_%s_deployment_evaluation"
const AppTypeAnnotation = "keptn.sh/app-type"
const KeptnGate = "keptn-prechecks-gate"
const ContainerNameAnnotation = "keptn.sh/container"

const MinKeptnNameLen = 80
const MaxK8sObjectLength = 253

var ErrCannotCastKeptnAppVersion = errors.New("cannot cast KeptnAppVersion to v1alpha3")
var ErrCannotCastKeptnApp = errors.New("cannot cast KeptnApp to v1alpha3")

type AppType string

const (
AppTypeSingleService AppType = "single-service"
AppTypeMultiService AppType = "multi-service"
)

// KeptnState is a string containing current Phase state (Progressing/Succeeded/Failed/Unknown/Pending/Cancelled)
type KeptnState string

const (
StateProgressing KeptnState = "Progressing"
StateSucceeded KeptnState = "Succeeded"
StateFailed KeptnState = "Failed"
StateUnknown KeptnState = "Unknown"
StatePending KeptnState = "Pending"
StateDeprecated KeptnState = "Deprecated"
// Deprecated: Use StateDeprecated instead. Should only be used in checks for backwards compatibility reasons
)

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

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

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

func (k KeptnState) IsDeprecated() bool {
return k == StateDeprecated
}

func (k KeptnState) IsPending() bool {
return k == StatePending
}

type StatusSummary struct {
Total int
Progressing int
Failed int
Succeeded int
Pending int
Unknown int
Deprecated int
}

func UpdateStatusSummary(status KeptnState, summary StatusSummary) StatusSummary {
switch status {
case StateFailed:
summary.Failed++
case StateDeprecated:
summary.Deprecated++
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 + s.Deprecated
}

func GetOverallState(s StatusSummary) KeptnState {
if s.Failed > 0 || s.Deprecated > 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 {
if len(s) > max {
return s[:max]
}
return s
}

func Hash(num int64) string {
// generate the SHA-256 hash of the bytes
hash := sha256.Sum256([]byte(strconv.FormatInt(num, 10)))
// take the first 4 bytes of the hash and convert to hex
return hex.EncodeToString(hash[:4])
}

type CheckType string

const PreDeploymentCheckType CheckType = "pre"
const PostDeploymentCheckType CheckType = "post"
const PreDeploymentEvaluationCheckType CheckType = "pre-eval"
const PostDeploymentEvaluationCheckType CheckType = "post-eval"

type KeptnMeters struct {
TaskCount metric.Int64Counter
TaskDuration metric.Float64Histogram
DeploymentCount metric.Int64Counter
DeploymentDuration metric.Float64Histogram
AppCount metric.Int64Counter
AppDuration metric.Float64Histogram
EvaluationCount metric.Int64Counter
EvaluationDuration metric.Float64Histogram
}

const (
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")
AppPreviousVersion attribute.Key = attribute.Key("keptn.deployment.app.previousversion")
WorkloadName attribute.Key = attribute.Key("keptn.deployment.workload.name")
WorkloadVersion attribute.Key = attribute.Key("keptn.deployment.workload.version")
WorkloadPreviousVersion attribute.Key = attribute.Key("keptn.deployment.workload.previousversion")
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")
EvaluationStatus attribute.Key = attribute.Key("keptn.deployment.evaluation.status")
EvaluationName attribute.Key = attribute.Key("keptn.deployment.evaluation.name")
EvaluationType attribute.Key = attribute.Key("keptn.deployment.evaluation.type")
)

func GenerateTaskName(checkType CheckType, taskName string) string {
randomId := rand.Intn(99_999-10_000) + 10000
return operatorcommon.CreateResourceName(MaxK8sObjectLength, MinKeptnNameLen, string(checkType), taskName, strconv.Itoa(randomId))
}

func GenerateJobName(taskName string) string {
randomId := rand.Intn(99_999-10_000) + 10000
return operatorcommon.CreateResourceName(MaxK8sObjectLength, MinKeptnNameLen, taskName, strconv.Itoa(randomId))
}

func GenerateEvaluationName(checkType CheckType, evalName string) string {
randomId := rand.Intn(99_999-10_000) + 10000
return operatorcommon.CreateResourceName(MaxK8sObjectLength, MinKeptnNameLen, string(checkType), evalName, strconv.Itoa(randomId))
}

// MergeMaps merges two maps into a new map. If a key exists in both maps, the
// value of the second map is picked.
func MergeMaps(m1 map[string]string, m2 map[string]string) map[string]string {
merged := make(map[string]string, len(m1)+len(m2))
for key, value := range m1 {
merged[key] = value
}
for key, value := range m2 {
merged[key] = value
}
return merged
}

// IsOwnerSupported returns whether the owner of the given object is supported to be considered a KeptnWorkload
func IsOwnerSupported(owner metav1.OwnerReference) bool {
return owner.Kind == "ReplicaSet" || owner.Kind == "Deployment" || owner.Kind == "StatefulSet" || owner.Kind == "DaemonSet" || owner.Kind == "Rollout"
}
Loading
Loading