Skip to content

Commit

Permalink
feat(verification): add promotion verification mechanisms based on ro…
Browse files Browse the repository at this point in the history
…llouts analysis templates (#1259)

Signed-off-by: Kent <kent.rancourt@gmail.com>
Signed-off-by: Kent Rancourt <kent.rancourt@gmail.com>
  • Loading branch information
krancour authored Dec 20, 2023
1 parent 4eb8d9c commit b5cca09
Show file tree
Hide file tree
Showing 34 changed files with 5,202 additions and 294 deletions.
41 changes: 20 additions & 21 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
SHELL ?= /bin/bash

ARGO_CD_CHART_VERSION := 5.51.6
ARGO_ROLLOUTS_CHART_VERSION := 2.32.8
BUF_LINT_ERROR_FORMAT ?= text
GO_LINT_ERROR_FORMAT ?= colored-line-number
CERT_MANAGER_CHART_VERSION := 1.11.5
Expand Down Expand Up @@ -225,7 +226,7 @@ hack-k3d-down:
ctlptl delete -f hack/k3d/cluster.yaml

.PHONY: hack-install-prereqs
hack-install-prereqs: hack-install-cert-manager hack-install-argocd
hack-install-prereqs: hack-install-cert-manager hack-install-argocd hack-install-argo-rollouts

.PHONY: hack-install-cert-manager
hack-install-cert-manager:
Expand All @@ -250,10 +251,27 @@ hack-install-argocd:
--set 'configs.params."application\.namespaces"=*' \
--set server.service.type=NodePort \
--set server.service.nodePortHttp=30080 \
--set server.extensions.enabled=true \
--set server.extensions.contents[0].name=argo-rollouts \
--set server.extensions.contents[0].url=https://github.com/argoproj-labs/rollout-extension/releases/download/v0.3.3/extension.tar \
--wait

.PHONY: hack-install-argo-rollouts
hack-install-argo-rollouts:
helm upgrade rollouts argo-rollouts \
--repo https://argoproj.github.io/argo-helm \
--version $(ARGO_ROLLOUTS_CHART_VERSION) \
--install \
--create-namespace \
--namespace rollouts \
--wait

.PHONY: hack-uninstall-prereqs
hack-uninstall-prereqs: hack-uninstall-argocd hack-uninstall-cert-manager
hack-uninstall-prereqs: hack-uninstall-argo-rollouts hack-uninstall-argocd hack-uninstall-cert-manager

.PHONY: hack-uninstall-argo-rollouts
hack-uninstall-argo-rollouts:
helm delete rollouts --namespace rollouts

.PHONY: hack-uninstall-argocd
hack-uninstall-argocd:
Expand All @@ -262,22 +280,3 @@ hack-uninstall-argocd:
.PHONY: hack-uninstall-cert-manager
hack-uninstall-cert-manager:
helm delete cert-manager --namespace cert-manager

.PHONY: hack-add-rollouts
hack-add-rollouts:
helm upgrade argocd argo-cd \
--repo https://argoproj.github.io/argo-helm \
--version $(ARGO_CD_CHART_VERSION) \
--namespace argocd \
--reuse-values \
--set server.extensions.enabled=true \
--set server.extensions.contents[0].name=argo-rollouts \
--set server.extensions.contents[0].url=https://github.com/argoproj-labs/rollout-extension/releases/download/v0.2.0/extension.tar \
--wait
helm upgrade argo-rollouts argo-rollouts \
--repo https://argoproj.github.io/argo-helm \
--version 2.20.0 \
--install \
--create-namespace \
--namespace argo-rollouts \
--wait
6 changes: 4 additions & 2 deletions api/v1alpha1/labels.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package v1alpha1

const (
AliasLabelKey = "kargo.akuity.io/alias"
LabelProjectKey = "kargo.akuity.io/project"
FreightLabelKey = "kargo.akuity.io/freight"
ShardLabelKey = "kargo.akuity.io/shard"
StageLabelKey = "kargo.akuity.io/stage"

LabelTrueValue = "true"

AliasLabelKey = "kargo.akuity.io/alias"
)
83 changes: 83 additions & 0 deletions api/v1alpha1/stage_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type StagePhase string

const (
// StagePhaseNotApplicable denotes a Stage that has no Freight.
StagePhaseNotApplicable StagePhase = "NotApplicable"
// StagePhaseSteady denotes a Stage that has Freight and is not currently
// being promoted or verified.
StagePhaseSteady StagePhase = "Steady"
// StagePhasePromoting denotes a Stage that is currently being promoted.
StagePhasePromoting StagePhase = "Promoting"
// StagePhaseVerifying denotes a Stage that is currently being verified.
StagePhaseVerifying StagePhase = "Verifying"
)

// +kubebuilder:validation:Enum={ImageAndTag,Tag,ImageAndDigest,Digest}
type ImageUpdateValueType string

Expand Down Expand Up @@ -63,6 +77,7 @@ const (
//+kubebuilder:subresource:status
//+kubebuilder:printcolumn:name=Current Freight,type=string,JSONPath=`.status.currentFreight.id`
//+kubebuilder:printcolumn:name=Health,type=string,JSONPath=`.status.health.status`
//+kubebuilder:printcolumn:name=Phase,type=string,JSONPath=`.status.phase`
//+kubebuilder:printcolumn:name=Age,type=date,JSONPath=`.metadata.creationTimestamp`

// Stage is the Kargo API's main type.
Expand Down Expand Up @@ -97,6 +112,9 @@ type StageSpec struct {
// single upstream Stage where they may otherwise have subscribed to multiple
// upstream Stages.
PromotionMechanisms *PromotionMechanisms `json:"promotionMechanisms,omitempty"`
// Verification describes how to verify a Stage's current Freight is fit for
// promotion downstream.
Verification *Verification `json:"verification,omitempty"`
}

// Subscriptions describes a Stage's sources of Freight.
Expand Down Expand Up @@ -416,6 +434,8 @@ type ArgoCDHelmImageUpdate struct {
// StageStatus describes a Stages's current and recent Freight, health, and
// more.
type StageStatus struct {
// Phase describes where the Stage currently is in its lifecycle.
Phase StagePhase `json:"phase,omitempty"`
// CurrentFreight is a simplified representation of the Stage's current
// Freight describing what is currently deployed to the Stage.
CurrentFreight *SimpleFreight `json:"currentFreight,omitempty"`
Expand Down Expand Up @@ -447,6 +467,9 @@ type SimpleFreight struct {
Images []Image `json:"images,omitempty"`
// Charts describes specific versions of specific Helm charts.
Charts []Chart `json:"charts,omitempty"`
// VerificationInfo is information about any verification process that was
// associated with this Freight for this Stage.
VerificationInfo *VerificationInfo `json:"verificationResult,omitempty"`
}

type SimpleFreightStack []SimpleFreight
Expand Down Expand Up @@ -586,3 +609,63 @@ type PromotionInfo struct {
// Freight is the freight being promoted
Freight SimpleFreight `json:"freight"`
}

// Verification describes how to verify that a Promotion has been successful
// using Argo Rollouts AnalysisTemplates.
type Verification struct {
// AnalysisTemplates is a list of AnalysisTemplates from which AnalysisRuns
// should be created to verify a Stage's current Freight is fit to be promoted
// downstream.
AnalysisTemplates []AnalysisTemplateReference `json:"analysisTemplates,omitempty"`
// AnalysisRunMetadata is contains optional metadata that should be applied to
// all AnalysisRuns.
AnalysisRunMetadata *AnalysisRunMetadata `json:"analysisRunMetadata,omitempty"`
// Args lists arguments that should be added to all AnalysisRuns.
Args []AnalysisRunArgument `json:"args,omitempty"`
}

// AnalysisTemplateReference is a reference to an AnalysisTemplate.
type AnalysisTemplateReference struct {
// Name is the name of the AnalysisTemplate in the same project/namespace as
// the Stage.
//
//+kubebuilder:validation:Required
Name string `json:"name"`
}

// AnalysisRunMetadata contains optional metadata that should be applied to all
// AnalysisRuns.
type AnalysisRunMetadata struct {
// Additional labels to apply to an AnalysisRun.
Labels map[string]string `json:"labels,omitempty"`
// Additional annotations to apply to an AnalysisRun.
Annotations map[string]string `json:"annotations,omitempty"`
}

// AnalysisRunArgument represents an argument to be added to an AnalysisRun.
type AnalysisRunArgument struct {
// Name is the name of the argument.
//
//+kubebuilder:validation:Required
Name string `json:"name"`
// Value is the value of the argument.
//
//+kubebuilder:validation:Required
Value string `json:"value,omitempty"`
}

// VerificationInfo contains information about the currently running
// Verification process.
type VerificationInfo struct {
AnalysisRun AnalysisRunReference `json:"analysisRun"`
}

// AnalysisRunReference is a reference to an AnalysisRun.
type AnalysisRunReference struct {
// Namespace is the namespace of the AnalysisRun.
Namespace string `json:"namespace"`
// Name is the name of the AnalysisRun.
Name string `json:"name"`
// Phase is the last observed phase of the AnalysisRun referenced by Name.
Phase string `json:"phase"`
}
33 changes: 33 additions & 0 deletions api/v1alpha1/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ message StageList {
message StageSpec {
Subscriptions subscriptions = 1 [json_name = "subscriptions"];
PromotionMechanisms promotion_mechanisms = 2 [json_name = "promotionMechanisms"];
optional Verification verification = 3 [json_name = "verification"];
}

message Freight {
Expand Down Expand Up @@ -243,6 +244,7 @@ message SimpleFreight {
repeated GitCommit commits = 4 [json_name = "commits"];
repeated Image images = 5 [json_name = "images"];
repeated Chart charts = 6 [json_name = "charts"];
optional VerificationInfo verification_info = 7 [json_name = "verificationInfo"];
}

message StageStatus {
Expand All @@ -251,6 +253,7 @@ message StageStatus {
string error = 4 [json_name = "error"];
optional Health health = 5 [json_name = "health"];
optional PromotionInfo current_promotion = 6 [json_name = "currentPromotion"];
string phase = 7 [json_name = "phase"];
}

message StageSubscription {
Expand Down Expand Up @@ -278,3 +281,33 @@ message WarehouseStatus {
string error = 1 [json_name = "error"];
int64 observed_generation = 2 [json_name = "observedGeneration"];
}

message Verification {
repeated AnalysisTemplateReference analysis_templates = 1 [json_name = "analysisTemplates"];
optional AnalysisRunMetadata analysis_run_metadata = 2 [json_name = "analysisRunMetadata"];
repeated AnalysisRunArgument args = 3 [json_name = "args"];
}

message AnalysisTemplateReference {
string name = 1 [json_name = "name"];
}

message AnalysisRunMetadata {
map<string, string> labels = 1 [json_name = "labels"];
map<string, string> annotations = 2 [json_name = "annotations"];
}

message AnalysisRunArgument {
string name = 1 [json_name = "name"];
string value = 2 [json_name = "value"];
}

message VerificationInfo {
AnalysisRunReference analysis_run = 1 [json_name = "analysisRun"];
}

message AnalysisRunReference {
string namespace = 1 [json_name = "namespace"];
string name = 2 [json_name = "name"];
string phase = 3 [json_name = "phase"];
}
Loading

0 comments on commit b5cca09

Please sign in to comment.