Skip to content

Commit

Permalink
add approval to the rollout
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Zhang committed Aug 15, 2024
1 parent 2b716ba commit 7fd558b
Show file tree
Hide file tree
Showing 8 changed files with 626 additions and 78 deletions.
2 changes: 1 addition & 1 deletion apis/cluster/v1beta1/zz_generated.deepcopy.go

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

205 changes: 176 additions & 29 deletions apis/placement/v1alpha1/stagerollout_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@ package v1alpha1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)

// +genclient
// +genclient:nonNamespaced
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope="Cluster",categories={fleet,fleet-placement}
// +kubebuilder:resource:scope="Namespaced",categories={fleet,fleet-placement}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// StageRollout defines a stage by stage rollout policy that is applied to the ClusterResourcePlacement of the same name.
// StageRollout defines a stage by stage rollout policy that is applied to the ClusterResourcePlacement it tracks.
type StageRollout struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand All @@ -33,17 +32,24 @@ type StageRollout struct {

// StageRolloutSpec defines the desired the rollout sequence stage by stage.
type StageRolloutSpec struct {
// Stage rollout configurations for each rollout stage.
// The name of the CRP that this rollout is applied to.
// There can only be one active rollout for each ClusterResourcePlacement,
// we will fail the rollout if there is already an active rollout.
// +required
Stages []StageRolloutConfig `json:"stages"`
ParentCRPName string `json:"parentCRPName"`

// The wait time between each stage is completed.
// The resource snapshot index that this rollout is based on.
// The rollout will use the latest resource snapshot if this is empty.
// +optional
WaitTimeBetweenStage *metav1.Duration `json:"waitTimeBetweenStage,omitempty"`
ResourceSnapShotIndex string `json:"resourceSnapShotIndex,omitempty"`

// TODO: Add alerting configuration.
// Stage rollout configurations for each rollout stage.
// +required
Stages []StageRolloutConfig `json:"stages"`

// TODO: Add health-check configuration.
// The common post rollout tasks that ALL stages needs to be completed before moving to the next stage.
// +optional
PostRolloutTasks PostRolloutTask `json:"postRolloutTasks,omitempty"`
}

// StageRolloutConfig describes a single rollout stage group configuration.
Expand All @@ -63,15 +69,25 @@ type StageRolloutConfig struct {
// +optional
SortingLabelKey *string `json:"sortingLabelKey,omitempty"`

// The maximum number of clusters that can be updated simultaneously within this stage.
// Note that an unsuccessful update cluster counts as one of the parallel updates which means
// the rollout will stuck if the number of failed clusters is equal to the MaxParallel.
// default is 1.
// The post rollout tasks that this stage needs to complete before moving to the next stage in-addition to
// the common post rollout tasks. This setting will override the common post rollout tasks if there are
// duplicate type of tasks with different settings.
// +optional
MaxParallel *intstr.IntOrString `json:"maxParallel,omitempty"`
PostRolloutTasks PostRolloutTask `json:"postRolloutTasks,omitempty"`

// TODO: Add alerting configuration.

// The wait time after all the clusters in this stage are updated.
// This will override the global waitTimeBetweenStage for this specific stage
}

// PostRolloutTask is the collection of post rollout tasks that ALL need to be completed before we can move to the next stage.
type PostRolloutTask struct {
// The name of the RolloutApprovalRequest we need to create to get the approval for the next stage.
// An RolloutApprovalRequest object will be created if this is not empty.
// +optional
ApprovalRequestName string `json:"approvalTask,omitempty"`

// The time to wait after all the clusters in the current stage complete the update
// before we move to the next stage.
// +optional
WaitTime *metav1.Duration `json:"waitTime,omitempty"`
}
Expand All @@ -96,42 +112,92 @@ type StageRolloutStatus struct {
// We take a new snapshot of the selected resources whenever the selection or their content change.
// Each snapshot has a different resource index.
// Each time the resource index is updated, the rollout will restart from the first stage.
// +optional
// +required
ResourceSnapshotIndex string `json:"resourceSnapshotIndex"`

// the clusters that are actively updating. It can be empty if the rollout is stopped.
// +optional
CurrentUpdatingClusters []string `json:"currentUpdatingClusters,omitempty"`

// The status of the post rollout tasks that are associated with current stage.
// +optional
CurrentPostRolloutTaskStatus []PostRolloutTaskStatus `json:"currentPostRolloutTaskStatus,omitempty"`

// +patchMergeKey=type
// +patchStrategy=merge
// +listType=map
// +listMapKey=type
//
// Conditions is an array of current observed conditions for StageRollout.
// Known conditions are "RollingOut".
// +optional
Conditions []metav1.Condition `json:"conditions"`
}

type PostRolloutTaskStatus struct {
// The type of the post rollout task.
// +required
Type PostRolloutTaskType `json:"type"`

// +patchMergeKey=type
// +patchStrategy=merge
// +listType=map
// +listMapKey=type
//
// Conditions is an array of current observed conditions for the specific type of post rollout task.
// Known conditions are "ApprovalRequestCreated", "WaitTimeElapsed", and "ApprovalRequestApproved".
// +optional
Conditions []metav1.Condition `json:"conditions"`
}

// PostRolloutTaskType identifies a specific type of the PostRolloutTask.
// +enum
type PostRolloutTaskType string

const (
// PostRolloutTaskSTypeTimedWait indicates the post rollout task is a timed wait.
PostRolloutTaskSTypeTimedWait PostRolloutTaskType = "TimedWait"

// PostRolloutTaskSTypeManualApproval indicates the post rollout task is a manual approval.
PostRolloutTaskSTypeManualApproval PostRolloutTaskType = "ManualApproval"
)

// PostRolloutTaskConditionType identifies a specific condition of the PostRolloutTask.
// +enum
type PostRolloutTaskConditionType string

const (
// PostRolloutTaskConditionApprovalRequestCreated indicates whether the approval request is created.
// Its condition status can be one of the following:
// - "True" means the approval request is created.
// - "False" means the approval request is not created.
PostRolloutTaskConditionApprovalRequestCreated PostRolloutTaskConditionType = "ApprovalRequestCreated"

// PostRolloutTaskConditionApprovalRequestApproved indicates whether the approval request is approved.
// Its condition status can be one of the following:
// - "True" means the approval request is approved.
// - "False" means the approval request is not approved.
PostRolloutTaskConditionApprovalRequestApproved PostRolloutTaskConditionType = "ApprovalRequestApproved"

// PostRolloutTaskConditionApprovalWaitTimeElapsed indicates whether the wait time after each stage is elapsed.
// We will fill the message of the condition of the remaining wait time if the status is "False".
// Its condition status can be one of the following:
// - "True" means the wait time is elapsed.
// - "False" means the wait time is not elapsed.
PostRolloutTaskConditionApprovalWaitTimeElapsed PostRolloutTaskConditionType = "WaitTimeElapsed"
)

// StageRolloutConditionType identifies a specific condition of the StageRollout.
// +enum
type StageRolloutConditionType string

const (
// StageRollingOut indicates whether the stage is rolling out normally.
// StageRolloutConditionRollingOut indicates whether the stage is rolling out normally.
// Its condition status can be one of the following:
// - "True" means the stage is rolling out.
// - "False" means the stage rolling out is not progressing.
// - "Unknown" means it is unknown.
StageRollingOut StageRolloutConditionType = "StageRollingOut"

// StageRolloutWaiting indicates whether the stage is waiting to be rolled out.
// Its condition status can be one of the following:
// - "True" means the staging is waiting to start to be rolled out.
// - "False" means the staging is not waiting to start rollout.
// - "Unknown" means it is unknown.
StageRolloutWaiting StageRolloutConditionType = "RolloutWaiting"

// TODO: add verification condition
StageRolloutConditionRollingOut StageRolloutConditionType = "RollingOut"

// TODO: add alerting condition
)
Expand All @@ -145,8 +211,89 @@ type StageRolloutList struct {
Items []StageRollout `json:"items"`
}

// +genclient
// +genclient:nonNamespaced
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope="Namespaced",categories={fleet,fleet-placement}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// RolloutApprovalRequest defines a stage by stage rollout policy that is applied to the ClusterResourcePlacement of the same name.
// Each snapshot MUST have the following labels:
// - `ParentStageRollout` which points to its owner stage rollout.
// - `TargetStage` which is the name of the stage that this approval request is for.
// - `IsLatestRolloutApproval` which indicates whether this approval request is the latest one related to this rollout
type RolloutApprovalRequest struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// The desired state of StageRollout.
// +required
Spec RolloutApprovalRequestSpec `json:"spec"`

// The desired state of StageRollout.
// +required
Status RolloutApprovalRequestStatus `json:"status"`
}

// RolloutApprovalRequestSpec defines the desired the rollout approval request.
// The entire spec is immutable.
type RolloutApprovalRequestSpec struct {
// The name of the rollout stage that this approval request is for.
// +required
ParentStageRollout string `json:"parentStageRollout"`

// The name of the rollout stage that this approval request is for.
// +required
TargetStage string `json:"targetStage"`

// The resource snapshot index that this approval request is based on.
// +required
ResourceSnapshotIndex string `json:"resourceSnapshotIndex"`
}

// RolloutApprovalRequestStatus defines the observed state of the RolloutApprovalRequest.
type RolloutApprovalRequestStatus struct {
// +patchMergeKey=type
// +patchStrategy=merge
// +listType=map
// +listMapKey=type
//
// Conditions is an array of current observed conditions for the specific type of post rollout task.
// Known conditions are "Approved", and "ApprovalAccepted".
// +optional
Conditions []metav1.Condition `json:"conditions"`
}

// RolloutApprovalConditionType identifies a specific condition of the RolloutApprovalRequest.
type RolloutApprovalConditionType string

const (
// RolloutApprovalConditionApproved indicates the request was approved.
// Its condition status can be one of the following:
// - "True" means the request is approved.
// - "False" means the request not approved.
RolloutApprovalConditionApproved RolloutApprovalConditionType = "Approved"

// RolloutApprovalConditionApprovalAccepted indicates whether the approval request is accepted by the rollout process.
// Its condition status can be one of the following:
// - "True" means the approval request is accepted.
// - "False" means the approval request is not accepted.
// - "Unknown" means it is not approved yet.
RolloutApprovalConditionApprovalAccepted RolloutApprovalConditionType = "ApprovalAccepted"
)

// RolloutApprovalRequestList contains a list of RolloutApprovalRequest.
// +kubebuilder:resource:scope="Namespaced"
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type RolloutApprovalRequestList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []RolloutApprovalRequest `json:"items"`
}

func init() {
SchemeBuilder.Register(
&StageRollout{}, &StageRolloutList{},
&StageRollout{}, &StageRolloutList{}, &RolloutApprovalRequest{}, &RolloutApprovalRequestList{},
)
}
Loading

0 comments on commit 7fd558b

Please sign in to comment.