diff --git a/api/v1alpha1/cluster_promotion_task_types.go b/api/v1alpha1/cluster_promotion_task_types.go new file mode 100644 index 000000000..6f5383452 --- /dev/null +++ b/api/v1alpha1/cluster_promotion_task_types.go @@ -0,0 +1,27 @@ +package v1alpha1 + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +// +kubebuilder:resource:scope=Cluster,shortName={clusterpromotask,clusterpromotasks} +// +kubebuilder:object:root=true +// +kubebuilder:printcolumn:name=Age,type=date,JSONPath=`.metadata.creationTimestamp` + +type ClusterPromotionTask struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Spec describes the desired transition of a specific Stage into a specific + // Freight. + // + // +kubebuilder:validation:Required + Spec PromotionTaskSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"` +} + +// +kubebuilder:object:root=true + +// ClusterPromotionTaskList contains a list of PromotionTasks. +type ClusterPromotionTaskList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + Items []ClusterPromotionTask `json:"items" protobuf:"bytes,2,rep,name=items"` +} diff --git a/api/v1alpha1/generated.pb.go b/api/v1alpha1/generated.pb.go index 3b9247777..c4989cde3 100644 --- a/api/v1alpha1/generated.pb.go +++ b/api/v1alpha1/generated.pb.go @@ -338,10 +338,66 @@ func (m *ChartSubscription) XXX_DiscardUnknown() { var xxx_messageInfo_ChartSubscription proto.InternalMessageInfo +func (m *ClusterPromotionTask) Reset() { *m = ClusterPromotionTask{} } +func (*ClusterPromotionTask) ProtoMessage() {} +func (*ClusterPromotionTask) Descriptor() ([]byte, []int) { + return fileDescriptor_e26b7f7bbc391025, []int{11} +} +func (m *ClusterPromotionTask) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ClusterPromotionTask) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ClusterPromotionTask) XXX_Merge(src proto.Message) { + xxx_messageInfo_ClusterPromotionTask.Merge(m, src) +} +func (m *ClusterPromotionTask) XXX_Size() int { + return m.Size() +} +func (m *ClusterPromotionTask) XXX_DiscardUnknown() { + xxx_messageInfo_ClusterPromotionTask.DiscardUnknown(m) +} + +var xxx_messageInfo_ClusterPromotionTask proto.InternalMessageInfo + +func (m *ClusterPromotionTaskList) Reset() { *m = ClusterPromotionTaskList{} } +func (*ClusterPromotionTaskList) ProtoMessage() {} +func (*ClusterPromotionTaskList) Descriptor() ([]byte, []int) { + return fileDescriptor_e26b7f7bbc391025, []int{12} +} +func (m *ClusterPromotionTaskList) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ClusterPromotionTaskList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *ClusterPromotionTaskList) XXX_Merge(src proto.Message) { + xxx_messageInfo_ClusterPromotionTaskList.Merge(m, src) +} +func (m *ClusterPromotionTaskList) XXX_Size() int { + return m.Size() +} +func (m *ClusterPromotionTaskList) XXX_DiscardUnknown() { + xxx_messageInfo_ClusterPromotionTaskList.DiscardUnknown(m) +} + +var xxx_messageInfo_ClusterPromotionTaskList proto.InternalMessageInfo + func (m *DiscoveredArtifacts) Reset() { *m = DiscoveredArtifacts{} } func (*DiscoveredArtifacts) ProtoMessage() {} func (*DiscoveredArtifacts) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{11} + return fileDescriptor_e26b7f7bbc391025, []int{13} } func (m *DiscoveredArtifacts) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -369,7 +425,7 @@ var xxx_messageInfo_DiscoveredArtifacts proto.InternalMessageInfo func (m *DiscoveredCommit) Reset() { *m = DiscoveredCommit{} } func (*DiscoveredCommit) ProtoMessage() {} func (*DiscoveredCommit) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{12} + return fileDescriptor_e26b7f7bbc391025, []int{14} } func (m *DiscoveredCommit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -397,7 +453,7 @@ var xxx_messageInfo_DiscoveredCommit proto.InternalMessageInfo func (m *DiscoveredImageReference) Reset() { *m = DiscoveredImageReference{} } func (*DiscoveredImageReference) ProtoMessage() {} func (*DiscoveredImageReference) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{13} + return fileDescriptor_e26b7f7bbc391025, []int{15} } func (m *DiscoveredImageReference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -425,7 +481,7 @@ var xxx_messageInfo_DiscoveredImageReference proto.InternalMessageInfo func (m *Freight) Reset() { *m = Freight{} } func (*Freight) ProtoMessage() {} func (*Freight) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{14} + return fileDescriptor_e26b7f7bbc391025, []int{16} } func (m *Freight) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -453,7 +509,7 @@ var xxx_messageInfo_Freight proto.InternalMessageInfo func (m *FreightCollection) Reset() { *m = FreightCollection{} } func (*FreightCollection) ProtoMessage() {} func (*FreightCollection) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{15} + return fileDescriptor_e26b7f7bbc391025, []int{17} } func (m *FreightCollection) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -481,7 +537,7 @@ var xxx_messageInfo_FreightCollection proto.InternalMessageInfo func (m *FreightList) Reset() { *m = FreightList{} } func (*FreightList) ProtoMessage() {} func (*FreightList) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{16} + return fileDescriptor_e26b7f7bbc391025, []int{18} } func (m *FreightList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -509,7 +565,7 @@ var xxx_messageInfo_FreightList proto.InternalMessageInfo func (m *FreightOrigin) Reset() { *m = FreightOrigin{} } func (*FreightOrigin) ProtoMessage() {} func (*FreightOrigin) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{17} + return fileDescriptor_e26b7f7bbc391025, []int{19} } func (m *FreightOrigin) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -537,7 +593,7 @@ var xxx_messageInfo_FreightOrigin proto.InternalMessageInfo func (m *FreightReference) Reset() { *m = FreightReference{} } func (*FreightReference) ProtoMessage() {} func (*FreightReference) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{18} + return fileDescriptor_e26b7f7bbc391025, []int{20} } func (m *FreightReference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -565,7 +621,7 @@ var xxx_messageInfo_FreightReference proto.InternalMessageInfo func (m *FreightRequest) Reset() { *m = FreightRequest{} } func (*FreightRequest) ProtoMessage() {} func (*FreightRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{19} + return fileDescriptor_e26b7f7bbc391025, []int{21} } func (m *FreightRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -593,7 +649,7 @@ var xxx_messageInfo_FreightRequest proto.InternalMessageInfo func (m *FreightSources) Reset() { *m = FreightSources{} } func (*FreightSources) ProtoMessage() {} func (*FreightSources) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{20} + return fileDescriptor_e26b7f7bbc391025, []int{22} } func (m *FreightSources) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -621,7 +677,7 @@ var xxx_messageInfo_FreightSources proto.InternalMessageInfo func (m *FreightStatus) Reset() { *m = FreightStatus{} } func (*FreightStatus) ProtoMessage() {} func (*FreightStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{21} + return fileDescriptor_e26b7f7bbc391025, []int{23} } func (m *FreightStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -649,7 +705,7 @@ var xxx_messageInfo_FreightStatus proto.InternalMessageInfo func (m *GitCommit) Reset() { *m = GitCommit{} } func (*GitCommit) ProtoMessage() {} func (*GitCommit) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{22} + return fileDescriptor_e26b7f7bbc391025, []int{24} } func (m *GitCommit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -677,7 +733,7 @@ var xxx_messageInfo_GitCommit proto.InternalMessageInfo func (m *GitDiscoveryResult) Reset() { *m = GitDiscoveryResult{} } func (*GitDiscoveryResult) ProtoMessage() {} func (*GitDiscoveryResult) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{23} + return fileDescriptor_e26b7f7bbc391025, []int{25} } func (m *GitDiscoveryResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -705,7 +761,7 @@ var xxx_messageInfo_GitDiscoveryResult proto.InternalMessageInfo func (m *GitSubscription) Reset() { *m = GitSubscription{} } func (*GitSubscription) ProtoMessage() {} func (*GitSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{24} + return fileDescriptor_e26b7f7bbc391025, []int{26} } func (m *GitSubscription) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -733,7 +789,7 @@ var xxx_messageInfo_GitSubscription proto.InternalMessageInfo func (m *Health) Reset() { *m = Health{} } func (*Health) ProtoMessage() {} func (*Health) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{25} + return fileDescriptor_e26b7f7bbc391025, []int{27} } func (m *Health) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -761,7 +817,7 @@ var xxx_messageInfo_Health proto.InternalMessageInfo func (m *HealthCheckStep) Reset() { *m = HealthCheckStep{} } func (*HealthCheckStep) ProtoMessage() {} func (*HealthCheckStep) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{26} + return fileDescriptor_e26b7f7bbc391025, []int{28} } func (m *HealthCheckStep) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -789,7 +845,7 @@ var xxx_messageInfo_HealthCheckStep proto.InternalMessageInfo func (m *Image) Reset() { *m = Image{} } func (*Image) ProtoMessage() {} func (*Image) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{27} + return fileDescriptor_e26b7f7bbc391025, []int{29} } func (m *Image) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -817,7 +873,7 @@ var xxx_messageInfo_Image proto.InternalMessageInfo func (m *ImageDiscoveryResult) Reset() { *m = ImageDiscoveryResult{} } func (*ImageDiscoveryResult) ProtoMessage() {} func (*ImageDiscoveryResult) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{28} + return fileDescriptor_e26b7f7bbc391025, []int{30} } func (m *ImageDiscoveryResult) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -845,7 +901,7 @@ var xxx_messageInfo_ImageDiscoveryResult proto.InternalMessageInfo func (m *ImageSubscription) Reset() { *m = ImageSubscription{} } func (*ImageSubscription) ProtoMessage() {} func (*ImageSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{29} + return fileDescriptor_e26b7f7bbc391025, []int{31} } func (m *ImageSubscription) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -873,7 +929,7 @@ var xxx_messageInfo_ImageSubscription proto.InternalMessageInfo func (m *Project) Reset() { *m = Project{} } func (*Project) ProtoMessage() {} func (*Project) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{30} + return fileDescriptor_e26b7f7bbc391025, []int{32} } func (m *Project) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -901,7 +957,7 @@ var xxx_messageInfo_Project proto.InternalMessageInfo func (m *ProjectList) Reset() { *m = ProjectList{} } func (*ProjectList) ProtoMessage() {} func (*ProjectList) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{31} + return fileDescriptor_e26b7f7bbc391025, []int{33} } func (m *ProjectList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -929,7 +985,7 @@ var xxx_messageInfo_ProjectList proto.InternalMessageInfo func (m *ProjectSpec) Reset() { *m = ProjectSpec{} } func (*ProjectSpec) ProtoMessage() {} func (*ProjectSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{32} + return fileDescriptor_e26b7f7bbc391025, []int{34} } func (m *ProjectSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -957,7 +1013,7 @@ var xxx_messageInfo_ProjectSpec proto.InternalMessageInfo func (m *ProjectStatus) Reset() { *m = ProjectStatus{} } func (*ProjectStatus) ProtoMessage() {} func (*ProjectStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{33} + return fileDescriptor_e26b7f7bbc391025, []int{35} } func (m *ProjectStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -985,7 +1041,7 @@ var xxx_messageInfo_ProjectStatus proto.InternalMessageInfo func (m *Promotion) Reset() { *m = Promotion{} } func (*Promotion) ProtoMessage() {} func (*Promotion) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{34} + return fileDescriptor_e26b7f7bbc391025, []int{36} } func (m *Promotion) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1013,7 +1069,7 @@ var xxx_messageInfo_Promotion proto.InternalMessageInfo func (m *PromotionList) Reset() { *m = PromotionList{} } func (*PromotionList) ProtoMessage() {} func (*PromotionList) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{35} + return fileDescriptor_e26b7f7bbc391025, []int{37} } func (m *PromotionList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1041,7 +1097,7 @@ var xxx_messageInfo_PromotionList proto.InternalMessageInfo func (m *PromotionPolicy) Reset() { *m = PromotionPolicy{} } func (*PromotionPolicy) ProtoMessage() {} func (*PromotionPolicy) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{36} + return fileDescriptor_e26b7f7bbc391025, []int{38} } func (m *PromotionPolicy) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1069,7 +1125,7 @@ var xxx_messageInfo_PromotionPolicy proto.InternalMessageInfo func (m *PromotionReference) Reset() { *m = PromotionReference{} } func (*PromotionReference) ProtoMessage() {} func (*PromotionReference) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{37} + return fileDescriptor_e26b7f7bbc391025, []int{39} } func (m *PromotionReference) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1097,7 +1153,7 @@ var xxx_messageInfo_PromotionReference proto.InternalMessageInfo func (m *PromotionSpec) Reset() { *m = PromotionSpec{} } func (*PromotionSpec) ProtoMessage() {} func (*PromotionSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{38} + return fileDescriptor_e26b7f7bbc391025, []int{40} } func (m *PromotionSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1125,7 +1181,7 @@ var xxx_messageInfo_PromotionSpec proto.InternalMessageInfo func (m *PromotionStatus) Reset() { *m = PromotionStatus{} } func (*PromotionStatus) ProtoMessage() {} func (*PromotionStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{39} + return fileDescriptor_e26b7f7bbc391025, []int{41} } func (m *PromotionStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1153,7 +1209,7 @@ var xxx_messageInfo_PromotionStatus proto.InternalMessageInfo func (m *PromotionStep) Reset() { *m = PromotionStep{} } func (*PromotionStep) ProtoMessage() {} func (*PromotionStep) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{40} + return fileDescriptor_e26b7f7bbc391025, []int{42} } func (m *PromotionStep) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1181,7 +1237,7 @@ var xxx_messageInfo_PromotionStep proto.InternalMessageInfo func (m *PromotionStepRetry) Reset() { *m = PromotionStepRetry{} } func (*PromotionStepRetry) ProtoMessage() {} func (*PromotionStepRetry) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{41} + return fileDescriptor_e26b7f7bbc391025, []int{43} } func (m *PromotionStepRetry) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1206,10 +1262,122 @@ func (m *PromotionStepRetry) XXX_DiscardUnknown() { var xxx_messageInfo_PromotionStepRetry proto.InternalMessageInfo +func (m *PromotionTask) Reset() { *m = PromotionTask{} } +func (*PromotionTask) ProtoMessage() {} +func (*PromotionTask) Descriptor() ([]byte, []int) { + return fileDescriptor_e26b7f7bbc391025, []int{44} +} +func (m *PromotionTask) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PromotionTask) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *PromotionTask) XXX_Merge(src proto.Message) { + xxx_messageInfo_PromotionTask.Merge(m, src) +} +func (m *PromotionTask) XXX_Size() int { + return m.Size() +} +func (m *PromotionTask) XXX_DiscardUnknown() { + xxx_messageInfo_PromotionTask.DiscardUnknown(m) +} + +var xxx_messageInfo_PromotionTask proto.InternalMessageInfo + +func (m *PromotionTaskList) Reset() { *m = PromotionTaskList{} } +func (*PromotionTaskList) ProtoMessage() {} +func (*PromotionTaskList) Descriptor() ([]byte, []int) { + return fileDescriptor_e26b7f7bbc391025, []int{45} +} +func (m *PromotionTaskList) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PromotionTaskList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *PromotionTaskList) XXX_Merge(src proto.Message) { + xxx_messageInfo_PromotionTaskList.Merge(m, src) +} +func (m *PromotionTaskList) XXX_Size() int { + return m.Size() +} +func (m *PromotionTaskList) XXX_DiscardUnknown() { + xxx_messageInfo_PromotionTaskList.DiscardUnknown(m) +} + +var xxx_messageInfo_PromotionTaskList proto.InternalMessageInfo + +func (m *PromotionTaskReference) Reset() { *m = PromotionTaskReference{} } +func (*PromotionTaskReference) ProtoMessage() {} +func (*PromotionTaskReference) Descriptor() ([]byte, []int) { + return fileDescriptor_e26b7f7bbc391025, []int{46} +} +func (m *PromotionTaskReference) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PromotionTaskReference) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *PromotionTaskReference) XXX_Merge(src proto.Message) { + xxx_messageInfo_PromotionTaskReference.Merge(m, src) +} +func (m *PromotionTaskReference) XXX_Size() int { + return m.Size() +} +func (m *PromotionTaskReference) XXX_DiscardUnknown() { + xxx_messageInfo_PromotionTaskReference.DiscardUnknown(m) +} + +var xxx_messageInfo_PromotionTaskReference proto.InternalMessageInfo + +func (m *PromotionTaskSpec) Reset() { *m = PromotionTaskSpec{} } +func (*PromotionTaskSpec) ProtoMessage() {} +func (*PromotionTaskSpec) Descriptor() ([]byte, []int) { + return fileDescriptor_e26b7f7bbc391025, []int{47} +} +func (m *PromotionTaskSpec) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PromotionTaskSpec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *PromotionTaskSpec) XXX_Merge(src proto.Message) { + xxx_messageInfo_PromotionTaskSpec.Merge(m, src) +} +func (m *PromotionTaskSpec) XXX_Size() int { + return m.Size() +} +func (m *PromotionTaskSpec) XXX_DiscardUnknown() { + xxx_messageInfo_PromotionTaskSpec.DiscardUnknown(m) +} + +var xxx_messageInfo_PromotionTaskSpec proto.InternalMessageInfo + func (m *PromotionTemplate) Reset() { *m = PromotionTemplate{} } func (*PromotionTemplate) ProtoMessage() {} func (*PromotionTemplate) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{42} + return fileDescriptor_e26b7f7bbc391025, []int{48} } func (m *PromotionTemplate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1237,7 +1405,7 @@ var xxx_messageInfo_PromotionTemplate proto.InternalMessageInfo func (m *PromotionTemplateSpec) Reset() { *m = PromotionTemplateSpec{} } func (*PromotionTemplateSpec) ProtoMessage() {} func (*PromotionTemplateSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{43} + return fileDescriptor_e26b7f7bbc391025, []int{49} } func (m *PromotionTemplateSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1265,7 +1433,7 @@ var xxx_messageInfo_PromotionTemplateSpec proto.InternalMessageInfo func (m *PromotionVariable) Reset() { *m = PromotionVariable{} } func (*PromotionVariable) ProtoMessage() {} func (*PromotionVariable) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{44} + return fileDescriptor_e26b7f7bbc391025, []int{50} } func (m *PromotionVariable) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1293,7 +1461,7 @@ var xxx_messageInfo_PromotionVariable proto.InternalMessageInfo func (m *RepoSubscription) Reset() { *m = RepoSubscription{} } func (*RepoSubscription) ProtoMessage() {} func (*RepoSubscription) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{45} + return fileDescriptor_e26b7f7bbc391025, []int{51} } func (m *RepoSubscription) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1321,7 +1489,7 @@ var xxx_messageInfo_RepoSubscription proto.InternalMessageInfo func (m *Stage) Reset() { *m = Stage{} } func (*Stage) ProtoMessage() {} func (*Stage) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{46} + return fileDescriptor_e26b7f7bbc391025, []int{52} } func (m *Stage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1349,7 +1517,7 @@ var xxx_messageInfo_Stage proto.InternalMessageInfo func (m *StageList) Reset() { *m = StageList{} } func (*StageList) ProtoMessage() {} func (*StageList) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{47} + return fileDescriptor_e26b7f7bbc391025, []int{53} } func (m *StageList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1377,7 +1545,7 @@ var xxx_messageInfo_StageList proto.InternalMessageInfo func (m *StageSpec) Reset() { *m = StageSpec{} } func (*StageSpec) ProtoMessage() {} func (*StageSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{48} + return fileDescriptor_e26b7f7bbc391025, []int{54} } func (m *StageSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1405,7 +1573,7 @@ var xxx_messageInfo_StageSpec proto.InternalMessageInfo func (m *StageStatus) Reset() { *m = StageStatus{} } func (*StageStatus) ProtoMessage() {} func (*StageStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{49} + return fileDescriptor_e26b7f7bbc391025, []int{55} } func (m *StageStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1433,7 +1601,7 @@ var xxx_messageInfo_StageStatus proto.InternalMessageInfo func (m *StepExecutionMetadata) Reset() { *m = StepExecutionMetadata{} } func (*StepExecutionMetadata) ProtoMessage() {} func (*StepExecutionMetadata) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{50} + return fileDescriptor_e26b7f7bbc391025, []int{56} } func (m *StepExecutionMetadata) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1461,7 +1629,7 @@ var xxx_messageInfo_StepExecutionMetadata proto.InternalMessageInfo func (m *Verification) Reset() { *m = Verification{} } func (*Verification) ProtoMessage() {} func (*Verification) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{51} + return fileDescriptor_e26b7f7bbc391025, []int{57} } func (m *Verification) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1489,7 +1657,7 @@ var xxx_messageInfo_Verification proto.InternalMessageInfo func (m *VerificationInfo) Reset() { *m = VerificationInfo{} } func (*VerificationInfo) ProtoMessage() {} func (*VerificationInfo) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{52} + return fileDescriptor_e26b7f7bbc391025, []int{58} } func (m *VerificationInfo) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1517,7 +1685,7 @@ var xxx_messageInfo_VerificationInfo proto.InternalMessageInfo func (m *VerifiedStage) Reset() { *m = VerifiedStage{} } func (*VerifiedStage) ProtoMessage() {} func (*VerifiedStage) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{53} + return fileDescriptor_e26b7f7bbc391025, []int{59} } func (m *VerifiedStage) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1545,7 +1713,7 @@ var xxx_messageInfo_VerifiedStage proto.InternalMessageInfo func (m *Warehouse) Reset() { *m = Warehouse{} } func (*Warehouse) ProtoMessage() {} func (*Warehouse) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{54} + return fileDescriptor_e26b7f7bbc391025, []int{60} } func (m *Warehouse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1573,7 +1741,7 @@ var xxx_messageInfo_Warehouse proto.InternalMessageInfo func (m *WarehouseList) Reset() { *m = WarehouseList{} } func (*WarehouseList) ProtoMessage() {} func (*WarehouseList) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{55} + return fileDescriptor_e26b7f7bbc391025, []int{61} } func (m *WarehouseList) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1601,7 +1769,7 @@ var xxx_messageInfo_WarehouseList proto.InternalMessageInfo func (m *WarehouseSpec) Reset() { *m = WarehouseSpec{} } func (*WarehouseSpec) ProtoMessage() {} func (*WarehouseSpec) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{56} + return fileDescriptor_e26b7f7bbc391025, []int{62} } func (m *WarehouseSpec) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1629,7 +1797,7 @@ var xxx_messageInfo_WarehouseSpec proto.InternalMessageInfo func (m *WarehouseStatus) Reset() { *m = WarehouseStatus{} } func (*WarehouseStatus) ProtoMessage() {} func (*WarehouseStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_e26b7f7bbc391025, []int{57} + return fileDescriptor_e26b7f7bbc391025, []int{63} } func (m *WarehouseStatus) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -1668,6 +1836,8 @@ func init() { proto.RegisterType((*Chart)(nil), "github.com.akuity.kargo.api.v1alpha1.Chart") proto.RegisterType((*ChartDiscoveryResult)(nil), "github.com.akuity.kargo.api.v1alpha1.ChartDiscoveryResult") proto.RegisterType((*ChartSubscription)(nil), "github.com.akuity.kargo.api.v1alpha1.ChartSubscription") + proto.RegisterType((*ClusterPromotionTask)(nil), "github.com.akuity.kargo.api.v1alpha1.ClusterPromotionTask") + proto.RegisterType((*ClusterPromotionTaskList)(nil), "github.com.akuity.kargo.api.v1alpha1.ClusterPromotionTaskList") proto.RegisterType((*DiscoveredArtifacts)(nil), "github.com.akuity.kargo.api.v1alpha1.DiscoveredArtifacts") proto.RegisterType((*DiscoveredCommit)(nil), "github.com.akuity.kargo.api.v1alpha1.DiscoveredCommit") proto.RegisterType((*DiscoveredImageReference)(nil), "github.com.akuity.kargo.api.v1alpha1.DiscoveredImageReference") @@ -1702,6 +1872,10 @@ func init() { proto.RegisterType((*PromotionStatus)(nil), "github.com.akuity.kargo.api.v1alpha1.PromotionStatus") proto.RegisterType((*PromotionStep)(nil), "github.com.akuity.kargo.api.v1alpha1.PromotionStep") proto.RegisterType((*PromotionStepRetry)(nil), "github.com.akuity.kargo.api.v1alpha1.PromotionStepRetry") + proto.RegisterType((*PromotionTask)(nil), "github.com.akuity.kargo.api.v1alpha1.PromotionTask") + proto.RegisterType((*PromotionTaskList)(nil), "github.com.akuity.kargo.api.v1alpha1.PromotionTaskList") + proto.RegisterType((*PromotionTaskReference)(nil), "github.com.akuity.kargo.api.v1alpha1.PromotionTaskReference") + proto.RegisterType((*PromotionTaskSpec)(nil), "github.com.akuity.kargo.api.v1alpha1.PromotionTaskSpec") proto.RegisterType((*PromotionTemplate)(nil), "github.com.akuity.kargo.api.v1alpha1.PromotionTemplate") proto.RegisterType((*PromotionTemplateSpec)(nil), "github.com.akuity.kargo.api.v1alpha1.PromotionTemplateSpec") proto.RegisterType((*PromotionVariable)(nil), "github.com.akuity.kargo.api.v1alpha1.PromotionVariable") @@ -1725,245 +1899,254 @@ func init() { } var fileDescriptor_e26b7f7bbc391025 = []byte{ - // 3803 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x5c, 0xcd, 0x6f, 0x1c, 0x47, - 0x76, 0x57, 0xcf, 0x90, 0x43, 0xce, 0x1b, 0x52, 0x24, 0x4b, 0x94, 0xcd, 0xe5, 0xc6, 0xa4, 0xd2, - 0x6b, 0x18, 0x76, 0x6c, 0x0f, 0x23, 0xd9, 0xb2, 0x64, 0x39, 0x51, 0xc0, 0x21, 0x25, 0x99, 0x0a, - 0xd7, 0x62, 0x6a, 0x64, 0x79, 0x57, 0x6b, 0xc3, 0x29, 0xce, 0x14, 0x67, 0x3a, 0x9c, 0xe9, 0x9e, - 0xad, 0xaa, 0xe1, 0x9a, 0x49, 0x90, 0x6c, 0xbe, 0x80, 0x45, 0xbe, 0xb0, 0x07, 0x03, 0xde, 0x00, - 0x09, 0x10, 0x24, 0xc7, 0x45, 0xf2, 0x0f, 0xe4, 0xe0, 0x43, 0x2e, 0x46, 0xb0, 0x08, 0x8c, 0x24, - 0x07, 0x1f, 0x16, 0x44, 0xcc, 0x05, 0x72, 0xdc, 0x5b, 0x2e, 0x02, 0x02, 0x04, 0xf5, 0xd1, 0xdd, - 0xd5, 0x3d, 0x3d, 0xe2, 0xf4, 0x88, 0x14, 0x8c, 0xbd, 0x0d, 0xeb, 0xd5, 0xfb, 0xbd, 0xfa, 0x78, - 0xef, 0xd5, 0x7b, 0xaf, 0xaa, 0x09, 0xaf, 0xb7, 0x3c, 0xd1, 0xee, 0xef, 0x56, 0x1b, 0x41, 0x77, - 0x8d, 0xec, 0xf7, 0x3d, 0x71, 0xb8, 0xb6, 0x4f, 0x58, 0x2b, 0x58, 0x23, 0x3d, 0x6f, 0xed, 0xe0, - 0x32, 0xe9, 0xf4, 0xda, 0xe4, 0xf2, 0x5a, 0x8b, 0xfa, 0x94, 0x11, 0x41, 0x9b, 0xd5, 0x1e, 0x0b, - 0x44, 0x80, 0x9e, 0x8f, 0xb9, 0xaa, 0x9a, 0xab, 0xaa, 0xb8, 0xaa, 0xa4, 0xe7, 0x55, 0x43, 0xae, - 0xe5, 0x57, 0x2d, 0xec, 0x56, 0xd0, 0x0a, 0xd6, 0x14, 0xf3, 0x6e, 0x7f, 0x4f, 0xfd, 0xa5, 0xfe, - 0x50, 0xbf, 0x34, 0xe8, 0xf2, 0xdb, 0xfb, 0xd7, 0x79, 0xd5, 0x53, 0x92, 0xe9, 0x47, 0x82, 0xfa, - 0xdc, 0x0b, 0x7c, 0xfe, 0x2a, 0xe9, 0x79, 0x9c, 0xb2, 0x03, 0xca, 0xd6, 0x7a, 0xfb, 0x2d, 0x49, - 0xe3, 0xc9, 0x0e, 0x6b, 0x07, 0x03, 0xc3, 0x5b, 0x7e, 0x3d, 0x46, 0xea, 0x92, 0x46, 0xdb, 0xf3, - 0x29, 0x3b, 0x8c, 0xd9, 0xbb, 0x54, 0x90, 0x2c, 0xae, 0xb5, 0x61, 0x5c, 0xac, 0xef, 0x0b, 0xaf, - 0x4b, 0x07, 0x18, 0xde, 0x38, 0x89, 0x81, 0x37, 0xda, 0xb4, 0x4b, 0xd2, 0x7c, 0xee, 0xfb, 0x70, - 0x61, 0xdd, 0x27, 0x9d, 0x43, 0xee, 0x71, 0xdc, 0xf7, 0xd7, 0x59, 0xab, 0xdf, 0xa5, 0xbe, 0x40, - 0x97, 0x60, 0xc2, 0x27, 0x5d, 0xba, 0xe4, 0x5c, 0x72, 0x5e, 0x2c, 0xd7, 0x66, 0x3e, 0x3b, 0x5a, - 0x3d, 0x77, 0x7c, 0xb4, 0x3a, 0xf1, 0x0e, 0xe9, 0x52, 0xac, 0x28, 0xe8, 0x1b, 0x30, 0x79, 0x40, - 0x3a, 0x7d, 0xba, 0x54, 0x50, 0x5d, 0x66, 0x4d, 0x97, 0xc9, 0x07, 0xb2, 0x11, 0x6b, 0x9a, 0xfb, - 0x27, 0xc5, 0x04, 0xfc, 0x37, 0xa9, 0x20, 0x4d, 0x22, 0x08, 0xea, 0x42, 0xa9, 0x43, 0x76, 0x69, - 0x87, 0x2f, 0x39, 0x97, 0x8a, 0x2f, 0x56, 0xae, 0xdc, 0xaa, 0x8e, 0xb2, 0x89, 0xd5, 0x0c, 0xa8, - 0xea, 0xb6, 0xc2, 0xb9, 0xe5, 0x0b, 0x76, 0x58, 0x3b, 0x6f, 0x06, 0x51, 0xd2, 0x8d, 0xd8, 0x08, - 0x41, 0x7f, 0xe4, 0x40, 0x85, 0xf8, 0x7e, 0x20, 0x88, 0x90, 0xdb, 0xb4, 0x54, 0x50, 0x42, 0xef, - 0x8e, 0x2f, 0x74, 0x3d, 0x06, 0xd3, 0x92, 0x2f, 0x18, 0xc9, 0x15, 0x8b, 0x82, 0x6d, 0x99, 0xcb, - 0x6f, 0x42, 0xc5, 0x1a, 0x2a, 0x9a, 0x87, 0xe2, 0x3e, 0x3d, 0xd4, 0xeb, 0x8b, 0xe5, 0x4f, 0xb4, - 0x98, 0x58, 0x50, 0xb3, 0x82, 0x37, 0x0a, 0xd7, 0x9d, 0xe5, 0x9b, 0x30, 0x9f, 0x16, 0x98, 0x87, - 0xdf, 0xfd, 0x6b, 0x07, 0x16, 0xad, 0x59, 0x60, 0xba, 0x47, 0x19, 0xf5, 0x1b, 0x14, 0xad, 0x41, - 0x59, 0xee, 0x25, 0xef, 0x91, 0x46, 0xb8, 0xd5, 0x0b, 0x66, 0x22, 0xe5, 0x77, 0x42, 0x02, 0x8e, - 0xfb, 0x44, 0x6a, 0x51, 0x78, 0x9c, 0x5a, 0xf4, 0xda, 0x84, 0xd3, 0xa5, 0x62, 0x52, 0x2d, 0x76, - 0x64, 0x23, 0xd6, 0x34, 0xf7, 0xd7, 0xe1, 0x6b, 0xe1, 0x78, 0xee, 0xd3, 0x6e, 0xaf, 0x43, 0x04, - 0x8d, 0x07, 0x75, 0xa2, 0xea, 0xb9, 0xfb, 0x30, 0xbb, 0xde, 0xeb, 0xb1, 0xe0, 0x80, 0x36, 0xeb, - 0x82, 0xb4, 0x28, 0x7a, 0x08, 0x40, 0x4c, 0xc3, 0xba, 0x50, 0x8c, 0x95, 0x2b, 0xbf, 0x52, 0xd5, - 0x16, 0x51, 0xb5, 0x2d, 0xa2, 0xda, 0xdb, 0x6f, 0xc9, 0x06, 0x5e, 0x95, 0x86, 0x57, 0x3d, 0xb8, - 0x5c, 0xbd, 0xef, 0x75, 0x69, 0xed, 0xfc, 0xf1, 0xd1, 0x2a, 0xac, 0x47, 0x08, 0xd8, 0x42, 0x73, - 0xff, 0xd8, 0x81, 0x8b, 0xeb, 0xac, 0x15, 0x6c, 0x6c, 0xae, 0xf7, 0x7a, 0x6f, 0x53, 0xd2, 0x11, - 0xed, 0xba, 0x20, 0xa2, 0xcf, 0xd1, 0x4d, 0x28, 0x71, 0xf5, 0xcb, 0x0c, 0xf5, 0x85, 0x50, 0xfb, - 0x34, 0xfd, 0xd1, 0xd1, 0xea, 0x62, 0x06, 0x23, 0xc5, 0x86, 0x0b, 0xbd, 0x04, 0x53, 0x5d, 0xca, - 0x39, 0x69, 0x85, 0xeb, 0x39, 0x67, 0x00, 0xa6, 0xbe, 0xa9, 0x9b, 0x71, 0x48, 0x77, 0xff, 0xad, - 0x00, 0x73, 0x11, 0x96, 0x11, 0x7f, 0x06, 0x9b, 0xd7, 0x87, 0x99, 0xb6, 0x35, 0x43, 0xb5, 0x87, - 0x95, 0x2b, 0x6f, 0x8d, 0x68, 0x27, 0x59, 0x8b, 0x54, 0x5b, 0x34, 0x62, 0x66, 0xec, 0x56, 0x9c, - 0x10, 0x83, 0xba, 0x00, 0xfc, 0xd0, 0x6f, 0x18, 0xa1, 0x13, 0x4a, 0xe8, 0x9b, 0x39, 0x85, 0xd6, - 0x23, 0x80, 0x1a, 0x32, 0x22, 0x21, 0x6e, 0xc3, 0x96, 0x00, 0xf7, 0x9f, 0x1d, 0xb8, 0x90, 0xc1, - 0x87, 0x7e, 0x2d, 0xb5, 0x9f, 0xcf, 0x0f, 0xec, 0x27, 0x1a, 0x60, 0x8b, 0x77, 0xf3, 0x15, 0x98, - 0x66, 0xf4, 0xc0, 0x93, 0xe7, 0x80, 0x59, 0xe1, 0x79, 0xc3, 0x3f, 0x8d, 0x4d, 0x3b, 0x8e, 0x7a, - 0xa0, 0x97, 0xa1, 0x1c, 0xfe, 0x96, 0xcb, 0x5c, 0x94, 0xa6, 0x22, 0x37, 0x2e, 0xec, 0xca, 0x71, - 0x4c, 0x77, 0xff, 0x10, 0x26, 0x37, 0xda, 0x84, 0x09, 0xa9, 0x31, 0x8c, 0xf6, 0x82, 0x77, 0xf1, - 0xb6, 0x19, 0x62, 0xa4, 0x31, 0x58, 0x37, 0xe3, 0x90, 0x3e, 0xc2, 0x66, 0xbf, 0x04, 0x53, 0x07, - 0x94, 0xa9, 0xf1, 0x16, 0x93, 0x60, 0x0f, 0x74, 0x33, 0x0e, 0xe9, 0xee, 0x7f, 0x3a, 0xb0, 0xa8, - 0x46, 0xb0, 0xe9, 0xf1, 0x46, 0x70, 0x40, 0xd9, 0x21, 0xa6, 0xbc, 0xdf, 0x39, 0xe5, 0x01, 0x6d, - 0xc2, 0x3c, 0xa7, 0xdd, 0x03, 0xca, 0x36, 0x02, 0x9f, 0x0b, 0x46, 0x3c, 0x5f, 0x98, 0x91, 0x2d, - 0x99, 0xde, 0xf3, 0xf5, 0x14, 0x1d, 0x0f, 0x70, 0xa0, 0x17, 0x61, 0xda, 0x0c, 0x5b, 0xaa, 0x92, - 0x5c, 0xd8, 0x19, 0xb9, 0x07, 0x66, 0x4e, 0x1c, 0x47, 0x54, 0xf7, 0x7f, 0x1c, 0x58, 0x50, 0xb3, - 0xaa, 0xf7, 0x77, 0x79, 0x83, 0x79, 0x3d, 0xe9, 0x5e, 0xbf, 0x8a, 0x53, 0xba, 0x09, 0xe7, 0x9b, - 0xe1, 0xc2, 0x6f, 0x7b, 0x5d, 0x4f, 0x28, 0x1b, 0x99, 0xac, 0x3d, 0x63, 0x30, 0xce, 0x6f, 0x26, - 0xa8, 0x38, 0xd5, 0xdb, 0xfd, 0xdb, 0x22, 0x5c, 0x08, 0xbb, 0xd0, 0xe6, 0x3a, 0x13, 0xde, 0x1e, - 0x69, 0x08, 0x8e, 0x9a, 0x30, 0xd3, 0x8c, 0x9b, 0x85, 0xb1, 0xbc, 0x3c, 0x8e, 0x33, 0xb2, 0x6e, - 0x0b, 0x5e, 0xe0, 0x04, 0x2a, 0x7a, 0x0f, 0x8a, 0x2d, 0x4f, 0x98, 0x83, 0xfe, 0xfa, 0x68, 0x66, - 0x7d, 0xc7, 0x4b, 0xab, 0x5a, 0xad, 0x62, 0x44, 0x15, 0xef, 0x78, 0x02, 0x4b, 0x44, 0xb4, 0x0b, - 0x25, 0xaf, 0x4b, 0x5a, 0x34, 0x3c, 0xcf, 0x6f, 0x8c, 0x86, 0xbd, 0x25, 0x79, 0xd2, 0xe8, 0x51, - 0xe4, 0xa0, 0xa8, 0x1c, 0x1b, 0x64, 0x29, 0xa3, 0x21, 0x55, 0x44, 0x1b, 0xe9, 0xc8, 0x32, 0xb2, - 0x8c, 0x25, 0x96, 0xa1, 0xa8, 0x1c, 0x1b, 0x64, 0xf7, 0x8b, 0x02, 0xcc, 0xc7, 0xeb, 0xb7, 0x11, - 0x74, 0xbb, 0x9e, 0x40, 0xcb, 0x50, 0xf0, 0x9a, 0x46, 0x03, 0xc1, 0x30, 0x16, 0xb6, 0x36, 0x71, - 0xc1, 0x6b, 0xa2, 0x17, 0xa0, 0xb4, 0xcb, 0x88, 0xdf, 0x68, 0x1b, 0xcd, 0x8b, 0x80, 0x6b, 0xaa, - 0x15, 0x1b, 0x2a, 0x7a, 0x0e, 0x8a, 0x82, 0xb4, 0x8c, 0xc2, 0x45, 0xeb, 0x77, 0x9f, 0xb4, 0xb0, - 0x6c, 0x97, 0x9a, 0xce, 0xfb, 0xbb, 0xbf, 0x43, 0x1b, 0x7a, 0xe7, 0x2d, 0x4d, 0xaf, 0xeb, 0x66, - 0x1c, 0xd2, 0xa5, 0x44, 0xd2, 0x17, 0xed, 0x80, 0x2d, 0x4d, 0x26, 0x25, 0xae, 0xab, 0x56, 0x6c, - 0xa8, 0xf2, 0x4c, 0x6a, 0xa8, 0xf1, 0x0b, 0xca, 0x96, 0x4a, 0xc9, 0x33, 0x69, 0x23, 0x24, 0xe0, - 0xb8, 0x0f, 0xfa, 0x00, 0x2a, 0x0d, 0x46, 0x89, 0x08, 0xd8, 0x26, 0x11, 0x74, 0x69, 0x2a, 0xb7, - 0x06, 0xce, 0xc9, 0xa0, 0x6b, 0x23, 0x86, 0xc0, 0x36, 0x9e, 0xfb, 0x73, 0x07, 0x96, 0xe2, 0xa5, - 0x55, 0x7b, 0x1b, 0x07, 0x1a, 0x66, 0x79, 0x9c, 0x21, 0xcb, 0xf3, 0x02, 0x94, 0x9a, 0x5e, 0x8b, - 0x72, 0x91, 0x5e, 0xe5, 0x4d, 0xd5, 0x8a, 0x0d, 0x15, 0x5d, 0x01, 0x68, 0x79, 0xc2, 0x38, 0x07, - 0xb3, 0xd8, 0xd1, 0x11, 0x74, 0x27, 0xa2, 0x60, 0xab, 0x17, 0x7a, 0x0f, 0xca, 0x6a, 0x98, 0x63, - 0x9a, 0x9d, 0x3a, 0x2a, 0x36, 0x42, 0x00, 0x1c, 0x63, 0xb9, 0x9f, 0x4f, 0xc0, 0xd4, 0x6d, 0x46, - 0xbd, 0x56, 0x5b, 0xa0, 0xdf, 0x86, 0xe9, 0xae, 0x09, 0x58, 0x4d, 0x4c, 0xf4, 0xab, 0xa3, 0xc9, - 0xb8, 0xa7, 0x36, 0x5d, 0x06, 0xbb, 0xf1, 0x44, 0xe2, 0x36, 0x1c, 0xa1, 0xca, 0x60, 0x8f, 0x74, - 0x3c, 0xc2, 0xd5, 0xbe, 0x59, 0xc1, 0xde, 0xba, 0x6c, 0xc4, 0x9a, 0x86, 0xbe, 0x03, 0xa5, 0x80, - 0x79, 0x2d, 0xcf, 0x5f, 0x2a, 0xab, 0x41, 0xbc, 0x36, 0x9a, 0x09, 0x99, 0x59, 0xdc, 0x53, 0xac, - 0xf1, 0xe2, 0xeb, 0xbf, 0xb1, 0x81, 0x44, 0x0f, 0x61, 0x4a, 0x2b, 0x53, 0x68, 0xa0, 0x6b, 0x23, - 0x3b, 0x18, 0xad, 0x8f, 0xb1, 0xd2, 0xeb, 0xbf, 0x39, 0x0e, 0x01, 0x51, 0x3d, 0xf2, 0x2f, 0x13, - 0x0a, 0xfa, 0xe5, 0x1c, 0xfe, 0x65, 0xa8, 0x43, 0xa9, 0x47, 0x0e, 0x65, 0x32, 0x0f, 0xa8, 0x72, - 0x19, 0xc3, 0x3c, 0x88, 0x5c, 0x62, 0x13, 0xb9, 0x94, 0xc6, 0x58, 0x62, 0x13, 0x36, 0x9d, 0x4f, - 0x86, 0x3b, 0x61, 0x60, 0xe3, 0x7e, 0x5c, 0x84, 0x05, 0xd3, 0x73, 0x23, 0xe8, 0x74, 0x68, 0x43, - 0x1d, 0x93, 0xda, 0x3f, 0x15, 0x33, 0xfd, 0x93, 0x07, 0x93, 0x9e, 0xa0, 0xdd, 0x30, 0xb9, 0xab, - 0xe5, 0x1a, 0x4d, 0x2c, 0xa3, 0xba, 0x25, 0x41, 0x74, 0x7e, 0x15, 0xed, 0x92, 0xe9, 0x85, 0xb5, - 0x04, 0xf4, 0x67, 0x0e, 0x5c, 0x38, 0xa0, 0xcc, 0xdb, 0xf3, 0x1a, 0x2a, 0x3b, 0x7a, 0xdb, 0xe3, - 0x22, 0x60, 0x87, 0xe6, 0x44, 0x78, 0x63, 0x34, 0xc9, 0x0f, 0x2c, 0x80, 0x2d, 0x7f, 0x2f, 0xa8, - 0x7d, 0xdd, 0x48, 0xbb, 0xf0, 0x60, 0x10, 0x1a, 0x67, 0xc9, 0x5b, 0xee, 0x01, 0xc4, 0xa3, 0xcd, - 0x48, 0xce, 0xb6, 0xed, 0xe4, 0x6c, 0xe4, 0x81, 0x85, 0x93, 0x0d, 0x5d, 0x96, 0x9d, 0xd4, 0x7d, - 0xea, 0x40, 0xc5, 0xd0, 0xb7, 0x3d, 0x2e, 0xd0, 0xfb, 0x03, 0xd6, 0x5e, 0x1d, 0xcd, 0xda, 0x25, - 0xb7, 0xb2, 0xf5, 0x28, 0x5e, 0x0d, 0x5b, 0x2c, 0x4b, 0xc7, 0xe1, 0x96, 0xea, 0x85, 0x7d, 0x35, - 0xd7, 0xf8, 0x63, 0xc7, 0xa0, 0xd6, 0xc8, 0xec, 0x9d, 0xcb, 0x60, 0x36, 0x61, 0xe4, 0xe8, 0x2a, - 0x4c, 0xec, 0x7b, 0x7e, 0x78, 0xea, 0xfd, 0x72, 0x18, 0x4f, 0xfd, 0xa6, 0xe7, 0x37, 0x1f, 0x1d, - 0xad, 0x2e, 0x24, 0x3a, 0xcb, 0x46, 0xac, 0xba, 0x9f, 0x1c, 0x86, 0xdd, 0x98, 0xfe, 0xd1, 0xdf, - 0xaf, 0x9e, 0xfb, 0xfe, 0x4f, 0x2f, 0x9d, 0x73, 0x3f, 0x29, 0xc2, 0x7c, 0x7a, 0x55, 0x47, 0x28, - 0x76, 0xc4, 0x3e, 0x6c, 0xfa, 0x4c, 0x7d, 0x58, 0xe1, 0xec, 0x7c, 0x58, 0xf1, 0x2c, 0x7c, 0xd8, - 0xc4, 0xa9, 0xf9, 0x30, 0xf7, 0xdf, 0x1d, 0x38, 0x1f, 0xed, 0xcc, 0x77, 0xfb, 0xf2, 0x64, 0x8d, - 0x57, 0xdd, 0x39, 0xfd, 0x55, 0xff, 0x10, 0xa6, 0x78, 0xd0, 0x67, 0x0d, 0x15, 0x3e, 0x4a, 0xf4, - 0xd7, 0xf3, 0x39, 0x4d, 0xcd, 0x6b, 0xc5, 0x4c, 0xba, 0x01, 0x87, 0xa8, 0xee, 0xfb, 0xd1, 0x7c, - 0x0c, 0x49, 0x47, 0x14, 0x4c, 0xc6, 0x5b, 0x72, 0x3e, 0xd3, 0x76, 0x44, 0x21, 0x5b, 0xb1, 0xa1, - 0x22, 0x57, 0xb9, 0xf3, 0x30, 0xb0, 0x2d, 0xd7, 0xc0, 0x78, 0x65, 0xb5, 0x07, 0x9a, 0xe2, 0xfe, - 0xbc, 0x18, 0x59, 0x8f, 0x49, 0x5f, 0xbf, 0x07, 0xa0, 0x3d, 0x13, 0x6d, 0x6e, 0xf9, 0xc6, 0xf5, - 0x6e, 0x8c, 0x71, 0x10, 0x18, 0x77, 0x28, 0x51, 0xb4, 0xef, 0x8d, 0x62, 0x80, 0x98, 0x80, 0x2d, - 0x51, 0xe8, 0xf7, 0xa0, 0x12, 0xd6, 0x4b, 0x6e, 0x07, 0xcc, 0xe8, 0xf0, 0xe6, 0x38, 0x92, 0xd7, - 0x63, 0x98, 0x74, 0x59, 0x2d, 0xa6, 0x60, 0x5b, 0xda, 0x32, 0x83, 0xb9, 0xd4, 0x78, 0x33, 0xbc, - 0xef, 0x56, 0xd2, 0xfb, 0xbe, 0x96, 0xe7, 0x58, 0x30, 0x35, 0x26, 0xbb, 0x1e, 0xc7, 0x61, 0x3e, - 0x3d, 0xd2, 0x53, 0x13, 0x9a, 0x28, 0x6c, 0xd9, 0xfe, 0xfe, 0xef, 0x0a, 0x50, 0x8e, 0x2c, 0x3e, - 0x4f, 0x96, 0xaa, 0x4f, 0xea, 0xc2, 0x09, 0x99, 0x44, 0x71, 0x94, 0x4c, 0x62, 0x62, 0x78, 0x26, - 0x11, 0x56, 0xb2, 0x4a, 0x8f, 0xaf, 0x64, 0x59, 0x99, 0xc4, 0xd4, 0xe8, 0x99, 0xc4, 0xf4, 0xc9, - 0x99, 0x84, 0xfb, 0x0f, 0x0e, 0xa0, 0xc1, 0xb4, 0x31, 0xcf, 0x42, 0x91, 0xb4, 0x1f, 0x1e, 0xf1, - 0x94, 0x4e, 0xe7, 0x6e, 0xc3, 0xdd, 0xb1, 0xfb, 0xe9, 0x24, 0xcc, 0xdd, 0xf1, 0xc6, 0x2e, 0x38, - 0x08, 0x78, 0x56, 0x23, 0xd5, 0xa9, 0x89, 0x91, 0xea, 0x82, 0x11, 0x41, 0x5b, 0x87, 0x66, 0x7f, - 0x6f, 0x18, 0xd6, 0x67, 0x37, 0xb2, 0xbb, 0x3d, 0x1a, 0x4e, 0xc2, 0xc3, 0xa0, 0x47, 0x56, 0x92, - 0xb7, 0x60, 0x96, 0x0b, 0xe6, 0x35, 0x84, 0x2e, 0x69, 0xf0, 0xa5, 0x8a, 0xf2, 0x72, 0x17, 0x4d, - 0xf7, 0xd9, 0xba, 0x4d, 0xc4, 0xc9, 0xbe, 0x99, 0x95, 0x92, 0x89, 0xdc, 0x95, 0x92, 0x35, 0x28, - 0x93, 0x4e, 0x27, 0xf8, 0xde, 0x7d, 0xd2, 0xe2, 0x26, 0x55, 0x8d, 0xb4, 0x66, 0x3d, 0x24, 0xe0, - 0xb8, 0x0f, 0xaa, 0x02, 0x78, 0x2d, 0x3f, 0x60, 0x54, 0x71, 0x94, 0x94, 0xbb, 0x55, 0xd5, 0xe0, - 0xad, 0xa8, 0x15, 0x5b, 0x3d, 0x50, 0x1d, 0x2e, 0x7a, 0x3e, 0xa7, 0x8d, 0x3e, 0xa3, 0xf5, 0x7d, - 0xaf, 0x77, 0x7f, 0xbb, 0xae, 0xbc, 0xc4, 0xa1, 0xd2, 0xe6, 0xe9, 0xda, 0x73, 0x46, 0xd8, 0xc5, - 0xad, 0xac, 0x4e, 0x38, 0x9b, 0x17, 0xbd, 0x0e, 0x33, 0x9e, 0xdf, 0xe8, 0xf4, 0x9b, 0x74, 0x87, - 0x88, 0x36, 0x5f, 0x9a, 0x56, 0xc3, 0x98, 0x3f, 0x3e, 0x5a, 0x9d, 0xd9, 0xb2, 0xda, 0x71, 0xa2, - 0x97, 0xe4, 0xa2, 0x1f, 0x59, 0x5c, 0xe5, 0x98, 0xeb, 0xd6, 0x47, 0x36, 0x97, 0xdd, 0x2b, 0xa3, - 0x96, 0x04, 0xb9, 0x6a, 0x49, 0x3f, 0x2e, 0x40, 0x49, 0x97, 0x72, 0xd1, 0xd5, 0x54, 0xbd, 0xf4, - 0xb9, 0x81, 0x7a, 0x69, 0x25, 0xab, 0xec, 0xed, 0x42, 0xc9, 0xe3, 0xbc, 0x9f, 0x3c, 0xdd, 0xb6, - 0x54, 0x0b, 0x36, 0x14, 0x55, 0x76, 0x09, 0xfc, 0x3d, 0xaf, 0x65, 0x92, 0xe3, 0x9b, 0x56, 0x28, - 0x1b, 0x5f, 0xb7, 0x7d, 0x18, 0xdd, 0xc7, 0xc5, 0x51, 0x6d, 0xa2, 0x83, 0x0c, 0x6f, 0xef, 0xd6, - 0xef, 0xbd, 0xa3, 0x65, 0x6c, 0x28, 0x44, 0x6c, 0x90, 0xa5, 0x8c, 0xa0, 0x2f, 0x7a, 0x7d, 0xa1, - 0x14, 0xe5, 0x94, 0x64, 0xdc, 0x53, 0x88, 0xd8, 0x20, 0xbb, 0x9f, 0x38, 0x30, 0xa7, 0xd7, 0x60, - 0xa3, 0x4d, 0x1b, 0xfb, 0x75, 0x41, 0x7b, 0x32, 0xda, 0xec, 0x73, 0xca, 0xd3, 0xd1, 0xe6, 0xbb, - 0x9c, 0x72, 0xac, 0x28, 0xd6, 0xec, 0x0b, 0x67, 0x35, 0x7b, 0xf7, 0x9f, 0x1c, 0x98, 0x54, 0x61, - 0x5d, 0x1e, 0xff, 0x93, 0x2c, 0x75, 0x14, 0x46, 0x2a, 0x75, 0x9c, 0x50, 0x84, 0x8a, 0xab, 0x2c, - 0x13, 0x8f, 0xab, 0xb2, 0xb8, 0x3f, 0x73, 0x60, 0x31, 0xab, 0x72, 0x97, 0x67, 0xf8, 0xaf, 0xc0, - 0x74, 0xaf, 0x43, 0xc4, 0x5e, 0xc0, 0xba, 0xe9, 0x12, 0xfd, 0x8e, 0x69, 0xc7, 0x51, 0x0f, 0xc4, - 0x00, 0x58, 0x98, 0x22, 0x84, 0xe1, 0xf3, 0xcd, 0xbc, 0x27, 0x42, 0xb2, 0xe4, 0x14, 0x2f, 0x56, - 0xd4, 0xc4, 0xb1, 0x25, 0xc5, 0xfd, 0x8b, 0x49, 0x58, 0x50, 0x2c, 0xe3, 0x9e, 0x10, 0xe3, 0xec, - 0x50, 0x0f, 0x9e, 0x51, 0x81, 0xfd, 0xe0, 0xa1, 0xa2, 0x37, 0xed, 0xba, 0xe1, 0x7f, 0x66, 0x2b, - 0xb3, 0xd7, 0xa3, 0xa1, 0x14, 0x3c, 0x04, 0x77, 0xf0, 0xa4, 0x80, 0x5f, 0xbc, 0x93, 0xc2, 0x56, - 0xb6, 0xa9, 0x13, 0x95, 0x6d, 0xe8, 0xb9, 0x32, 0xfd, 0x04, 0xe7, 0xca, 0xa0, 0xaf, 0x2f, 0xe7, - 0xf2, 0xf5, 0x7f, 0x53, 0x80, 0xa9, 0x1d, 0x16, 0xa8, 0x0a, 0xf0, 0xd9, 0x17, 0x13, 0xef, 0xc1, - 0x04, 0xef, 0xd1, 0x86, 0xf1, 0x79, 0x97, 0x47, 0xb3, 0x34, 0x33, 0xbc, 0x7a, 0x8f, 0x36, 0x6a, - 0xd3, 0xd2, 0x8d, 0xca, 0x5f, 0x58, 0x01, 0x59, 0x55, 0xb1, 0x62, 0x9e, 0x08, 0x3c, 0x84, 0x7c, - 0x7c, 0x55, 0xec, 0x53, 0x07, 0x2a, 0xa6, 0xe7, 0x57, 0xb6, 0xfc, 0x62, 0xc6, 0x37, 0xa4, 0xfc, - 0xf2, 0x57, 0xf1, 0x0c, 0xe4, 0xa2, 0xa1, 0x3f, 0x80, 0x85, 0x1e, 0x0b, 0xba, 0x81, 0xb4, 0xd4, - 0x9d, 0xa0, 0xe3, 0x35, 0x3c, 0x1a, 0x56, 0xf0, 0xae, 0x8e, 0x2c, 0xcf, 0x62, 0x3f, 0xac, 0x7d, - 0xcd, 0xc8, 0x5d, 0xd8, 0x49, 0xe3, 0xe2, 0x41, 0x51, 0xee, 0x7f, 0x39, 0x30, 0x9b, 0x58, 0x7b, - 0xd4, 0x00, 0x68, 0x04, 0x7e, 0xd3, 0x13, 0xd1, 0x2d, 0x69, 0xe5, 0xca, 0xda, 0x68, 0xab, 0xba, - 0x11, 0xf2, 0xc5, 0x4a, 0x17, 0x35, 0x71, 0x6c, 0xc1, 0xa2, 0xd7, 0xc2, 0x07, 0x0b, 0xc9, 0x20, - 0x46, 0x3f, 0x58, 0x78, 0x74, 0xb4, 0x3a, 0x63, 0xc6, 0x64, 0x3f, 0x60, 0xc8, 0x73, 0x75, 0xff, - 0x8f, 0x05, 0x28, 0x47, 0xf3, 0x7f, 0x0a, 0x66, 0xf4, 0x6e, 0xc2, 0x8c, 0x5e, 0xcb, 0xb9, 0x73, - 0xca, 0x90, 0xa2, 0x98, 0xc4, 0x32, 0xa6, 0x0f, 0x52, 0xc6, 0x94, 0x57, 0x25, 0x4e, 0x30, 0xa7, - 0x7f, 0xd5, 0x9b, 0xaf, 0xfb, 0x3e, 0x05, 0x83, 0xba, 0x9f, 0x34, 0xa8, 0xb5, 0x9c, 0xb3, 0x19, - 0x62, 0x52, 0x3f, 0x70, 0x60, 0x2e, 0x65, 0x04, 0xe8, 0x1b, 0x30, 0xa9, 0x4a, 0x36, 0x46, 0xbf, - 0x22, 0x46, 0x93, 0xe0, 0x2b, 0x1a, 0xda, 0x81, 0x45, 0xd2, 0x17, 0x41, 0xc4, 0x7b, 0xcb, 0x27, - 0xbb, 0x1d, 0xaa, 0xb3, 0xf6, 0xe9, 0xda, 0x2f, 0x19, 0x9e, 0xc5, 0xf5, 0x8c, 0x3e, 0x38, 0x93, - 0xd3, 0xfd, 0x49, 0x01, 0x50, 0xd4, 0x98, 0xa7, 0xd4, 0xf9, 0x01, 0x4c, 0xed, 0xe9, 0xa2, 0xcc, - 0x93, 0xd5, 0xaa, 0x6b, 0x15, 0xbb, 0x5c, 0x1f, 0x62, 0xa2, 0x6f, 0x9f, 0x8e, 0x1e, 0xc1, 0xa0, - 0x0e, 0xa1, 0x87, 0x00, 0x7b, 0x9e, 0xef, 0xf1, 0xf6, 0x98, 0xb7, 0x6a, 0xea, 0x34, 0xbf, 0x1d, - 0x21, 0x60, 0x0b, 0xcd, 0xfd, 0xb8, 0x60, 0xe9, 0xa7, 0x72, 0x97, 0x23, 0xed, 0xeb, 0x4b, 0xc9, - 0xc5, 0x2c, 0x0f, 0xde, 0x63, 0x58, 0x0b, 0x33, 0x71, 0x40, 0x58, 0x58, 0x52, 0xbd, 0x96, 0x73, - 0x59, 0x1e, 0x10, 0xe6, 0xc9, 0x8d, 0x8f, 0xb7, 0xf4, 0x01, 0x61, 0x1c, 0x2b, 0x48, 0xf4, 0x2d, - 0x39, 0x54, 0xda, 0x0b, 0x5d, 0x68, 0x6e, 0x9f, 0x20, 0x68, 0xcf, 0x9e, 0x1f, 0xed, 0x71, 0xac, - 0x01, 0xdd, 0x8f, 0xa7, 0x2c, 0x85, 0x37, 0x5e, 0xfb, 0x2e, 0xa0, 0x0e, 0xe1, 0xe2, 0x6d, 0xe2, - 0x37, 0xa5, 0x7a, 0xd2, 0x3d, 0x46, 0x79, 0xdb, 0x44, 0x68, 0xcb, 0x06, 0x05, 0x6d, 0x0f, 0xf4, - 0xc0, 0x19, 0x5c, 0xe8, 0x6a, 0xd2, 0x39, 0xaf, 0xa6, 0x9d, 0xf3, 0xf9, 0xd8, 0xda, 0xc6, 0x73, - 0xcf, 0xb6, 0xba, 0x4f, 0x9e, 0x81, 0xba, 0xff, 0x3e, 0x2c, 0xec, 0xa5, 0xef, 0xb5, 0xcc, 0x2d, - 0xf7, 0xb5, 0x31, 0xaf, 0xc5, 0x6a, 0x17, 0x8f, 0xe3, 0xcb, 0x90, 0xb8, 0x19, 0x0f, 0x0a, 0x42, - 0x41, 0xf8, 0x9e, 0x4b, 0x65, 0x9f, 0xba, 0xb0, 0x30, 0xb2, 0xc9, 0xa5, 0xf2, 0xd6, 0xf4, 0x4b, - 0x2e, 0x0d, 0x89, 0x13, 0x02, 0x52, 0x26, 0x58, 0x3a, 0x4d, 0x13, 0x44, 0x57, 0xa1, 0xd2, 0xe8, - 0x33, 0x46, 0x7d, 0x21, 0x87, 0xa3, 0x42, 0xd9, 0x62, 0x5c, 0x20, 0xde, 0x88, 0x49, 0xd8, 0xee, - 0x87, 0x7e, 0xe8, 0xc0, 0x45, 0xa9, 0xac, 0xb7, 0x3e, 0xa2, 0x8d, 0xbe, 0x5c, 0x95, 0xf0, 0x11, - 0xe7, 0x52, 0x45, 0xad, 0xc6, 0x88, 0xaf, 0xdb, 0xea, 0x59, 0x10, 0x71, 0x5c, 0x9e, 0x49, 0xc6, - 0xd9, 0x82, 0xd1, 0x87, 0xca, 0x75, 0x08, 0xaa, 0xd2, 0x9e, 0x27, 0x4f, 0xef, 0xcb, 0xc6, 0xed, - 0x08, 0xed, 0x76, 0x04, 0x75, 0xff, 0x32, 0xe1, 0xad, 0x46, 0x2b, 0x3a, 0x2c, 0x43, 0x81, 0xf0, - 0x74, 0x99, 0x78, 0x9d, 0xe3, 0x02, 0xe1, 0xe8, 0xdb, 0x30, 0xc9, 0xa8, 0x60, 0x87, 0xc6, 0xa9, - 0x5e, 0x1f, 0xc3, 0x81, 0x60, 0xc9, 0xaf, 0x87, 0xaa, 0x7e, 0x62, 0x8d, 0x68, 0xd5, 0x3a, 0x8a, - 0x67, 0x56, 0xeb, 0xf8, 0xb1, 0x63, 0x9d, 0x85, 0xd1, 0x60, 0xd0, 0xbb, 0x30, 0x25, 0xbc, 0x2e, - 0x0d, 0xfa, 0x22, 0x5f, 0x80, 0xb1, 0xd9, 0x67, 0xea, 0xee, 0x57, 0x9b, 0xfc, 0x7d, 0x0d, 0x81, - 0x43, 0x2c, 0x99, 0x75, 0x51, 0xc6, 0x02, 0x76, 0xbf, 0x2d, 0x5d, 0x58, 0xd0, 0xd1, 0xa7, 0xf8, - 0x6c, 0x9c, 0x75, 0xdd, 0x4a, 0x50, 0x71, 0xaa, 0xb7, 0xcb, 0x20, 0x8e, 0x97, 0xc3, 0xd7, 0xb1, - 0xe8, 0x03, 0x13, 0xd5, 0x39, 0x79, 0x5e, 0x64, 0x0e, 0xc0, 0x0c, 0x8b, 0xee, 0xdc, 0x9f, 0x38, - 0x70, 0x31, 0xb3, 0x77, 0x74, 0x2c, 0x15, 0xce, 0xf0, 0x58, 0x72, 0x4e, 0xfb, 0x58, 0x7a, 0x68, - 0x2d, 0x61, 0x38, 0x84, 0xd3, 0x7a, 0xd2, 0xfe, 0xa3, 0x02, 0xcc, 0x63, 0xda, 0x0b, 0x12, 0x15, - 0x9a, 0x9d, 0xf0, 0x8d, 0x5b, 0x8e, 0x90, 0x26, 0x75, 0x0f, 0x50, 0x9b, 0x4a, 0x3c, 0x6e, 0xfb, - 0x16, 0x4c, 0xaa, 0xe2, 0x89, 0x09, 0xc2, 0xae, 0xe5, 0xb8, 0xb7, 0x4d, 0xa0, 0x2a, 0x8b, 0xd3, - 0x55, 0x28, 0x0d, 0x28, 0x91, 0xd5, 0x95, 0xab, 0x31, 0xb8, 0x6b, 0x39, 0x2e, 0x6f, 0x07, 0x91, - 0x55, 0x33, 0xd6, 0x80, 0xee, 0x27, 0x05, 0xd0, 0xe1, 0xcf, 0x53, 0x48, 0x73, 0x7e, 0x2b, 0x91, - 0xe6, 0xac, 0x8d, 0xea, 0xc4, 0xe5, 0xf2, 0x0c, 0x4b, 0x71, 0xd2, 0xa1, 0xe9, 0xe5, 0x3c, 0xa0, - 0x8f, 0x4f, 0x6f, 0xfe, 0xc5, 0x81, 0xb2, 0xea, 0xf7, 0x14, 0x52, 0x9b, 0x9d, 0x64, 0x6a, 0xf3, - 0x72, 0x8e, 0x59, 0x0c, 0x49, 0x6b, 0x3e, 0x2e, 0x9a, 0xd1, 0x47, 0x81, 0x6f, 0x9b, 0xb0, 0xa6, - 0x09, 0xe9, 0x62, 0x0b, 0x94, 0x8d, 0x58, 0xd3, 0xd0, 0xef, 0xc2, 0x3c, 0xd3, 0xb7, 0xf8, 0xb4, - 0x79, 0x3b, 0x8a, 0xaf, 0x8a, 0xb9, 0xaf, 0xd9, 0xcd, 0x53, 0x80, 0xb8, 0xb4, 0x87, 0x53, 0xa8, - 0x78, 0x40, 0x8e, 0x8c, 0xb9, 0x7a, 0x69, 0x5f, 0x66, 0x62, 0x91, 0x6b, 0x63, 0x3a, 0x4e, 0x1d, - 0x73, 0x0d, 0x34, 0xe3, 0x41, 0x41, 0xa8, 0x0d, 0x33, 0xf6, 0x03, 0x21, 0xa3, 0x4b, 0x57, 0xf2, - 0xbf, 0x44, 0xd2, 0x57, 0x39, 0x76, 0x0b, 0x4e, 0x20, 0xbb, 0x47, 0x25, 0xa8, 0x58, 0xca, 0x97, - 0x2a, 0x97, 0xcc, 0x9e, 0x4d, 0xb9, 0x24, 0x3b, 0xba, 0xaf, 0x8c, 0x15, 0xdd, 0x5f, 0x4e, 0x46, - 0xf7, 0x5f, 0x4f, 0x47, 0xf7, 0xa0, 0x66, 0x97, 0x88, 0xec, 0x39, 0x9c, 0x37, 0x61, 0x6e, 0xf8, - 0xd2, 0x2b, 0x57, 0xbe, 0x34, 0x18, 0x4c, 0x23, 0x79, 0x22, 0xdf, 0x4e, 0x40, 0xe2, 0x94, 0x08, - 0x79, 0xa2, 0x9b, 0x96, 0x7a, 0xbf, 0xdb, 0x25, 0xec, 0x70, 0x69, 0x46, 0x0d, 0x38, 0x3a, 0xd1, - 0x6f, 0x27, 0xa8, 0x38, 0xd5, 0x1b, 0xed, 0x40, 0x49, 0x47, 0xc9, 0xe6, 0xf5, 0xd0, 0x2b, 0x79, - 0x02, 0x70, 0x1d, 0xd1, 0xe8, 0xdf, 0xd8, 0xe0, 0xd8, 0x09, 0x4e, 0xf9, 0x84, 0x04, 0xe7, 0x2e, - 0xa0, 0x60, 0x57, 0xc5, 0x4e, 0xcd, 0x3b, 0xfa, 0xdb, 0x2f, 0xa9, 0x95, 0x25, 0x15, 0x3d, 0x47, - 0x1b, 0x76, 0x6f, 0xa0, 0x07, 0xce, 0xe0, 0x92, 0x56, 0x6d, 0x42, 0xeb, 0xc8, 0x14, 0x4c, 0x32, - 0x93, 0x37, 0x24, 0x8c, 0xf3, 0xa6, 0x45, 0x69, 0xd5, 0x1b, 0x29, 0x54, 0x3c, 0x20, 0x07, 0x7d, - 0x17, 0x66, 0xa5, 0x0a, 0xc5, 0x82, 0xe1, 0x09, 0x05, 0x2f, 0x1c, 0x1f, 0xad, 0xce, 0x6e, 0xdb, - 0x90, 0x38, 0x29, 0xc1, 0xfd, 0xf3, 0x22, 0x64, 0x07, 0xf6, 0xf1, 0xc3, 0x57, 0xe7, 0x31, 0x0f, - 0x5f, 0xdf, 0x83, 0x32, 0x17, 0x84, 0xe9, 0x47, 0xbe, 0x85, 0xf1, 0x1e, 0xf9, 0xd6, 0x43, 0x00, - 0x1c, 0x63, 0xa5, 0xb2, 0xac, 0xe2, 0xa9, 0x66, 0x59, 0x57, 0x00, 0x54, 0x3c, 0xba, 0x11, 0xf4, - 0xcd, 0xbd, 0xca, 0x6c, 0xec, 0x13, 0x6e, 0x45, 0x14, 0x6c, 0xf5, 0x42, 0xd7, 0xa3, 0x83, 0x53, - 0x5f, 0xa4, 0x5c, 0x1a, 0xb8, 0x08, 0x4e, 0xe7, 0xe9, 0x19, 0x9f, 0x40, 0x9d, 0xf0, 0x70, 0xc4, - 0xfd, 0xbf, 0x02, 0x24, 0x9c, 0x21, 0xfa, 0x81, 0x03, 0x0b, 0x24, 0xf5, 0x15, 0x59, 0x18, 0x4b, - 0xfe, 0x46, 0xbe, 0x4f, 0xfb, 0x06, 0x3e, 0x42, 0x8b, 0x4b, 0xd7, 0xe9, 0x2e, 0x1c, 0x0f, 0x0a, - 0x45, 0x7f, 0xea, 0xc0, 0x05, 0x32, 0xf8, 0x99, 0xa0, 0xd9, 0xf4, 0x37, 0xc7, 0xfe, 0xce, 0xb0, - 0xf6, 0xec, 0xf1, 0xd1, 0x6a, 0xd6, 0x07, 0x94, 0x38, 0x4b, 0x1c, 0xfa, 0x0e, 0x4c, 0x10, 0xd6, - 0x0a, 0xcb, 0x3c, 0xf9, 0xc5, 0x86, 0x5f, 0x7f, 0xc6, 0xd1, 0xd1, 0x3a, 0x6b, 0x71, 0xac, 0x40, - 0xdd, 0x9f, 0x16, 0x61, 0x3e, 0xfd, 0x50, 0xd6, 0xbc, 0x2d, 0x9a, 0xc8, 0x7c, 0x5b, 0x24, 0x6d, - 0xa4, 0x21, 0xa2, 0x87, 0x3e, 0xb1, 0x8d, 0xc8, 0x46, 0xac, 0x69, 0x91, 0x8d, 0x48, 0xbd, 0x34, - 0x05, 0x98, 0xf1, 0x6c, 0x44, 0xfe, 0x89, 0x63, 0x2c, 0x74, 0x3d, 0x79, 0xb6, 0xb8, 0xe9, 0xb3, - 0x65, 0xc1, 0x9e, 0xcb, 0xb8, 0xc5, 0xa3, 0x2e, 0x54, 0xac, 0x7d, 0x30, 0x96, 0x78, 0x23, 0xf7, - 0xba, 0xc7, 0x6a, 0x37, 0xa7, 0x3f, 0x21, 0x8d, 0x29, 0x36, 0x7e, 0x6c, 0xf7, 0x6a, 0xb5, 0x9e, - 0xa8, 0xba, 0xa2, 0x96, 0xcb, 0x42, 0x73, 0xf7, 0x61, 0x36, 0xf1, 0xde, 0x4d, 0x0a, 0x0b, 0xdf, - 0xf8, 0x8d, 0xff, 0x4d, 0xe5, 0x83, 0x08, 0x01, 0x5b, 0x68, 0xea, 0x4e, 0xe4, 0x3d, 0xc2, 0x68, - 0x3b, 0xe8, 0x73, 0xfa, 0x55, 0xbd, 0x13, 0x89, 0x06, 0x78, 0xda, 0x77, 0x22, 0x31, 0xf0, 0xc9, - 0x77, 0x22, 0x51, 0xdf, 0xaf, 0xec, 0x9d, 0x48, 0x34, 0xc2, 0x21, 0xc9, 0xc3, 0xff, 0x16, 0xac, - 0x59, 0x24, 0x13, 0x88, 0xc2, 0x63, 0x12, 0x88, 0xf7, 0x61, 0xda, 0xf3, 0x05, 0x65, 0x07, 0xa4, - 0x63, 0xaa, 0x4e, 0x79, 0xab, 0x33, 0xd1, 0x54, 0xb7, 0x0c, 0x0e, 0x8e, 0x10, 0x51, 0x07, 0x2e, - 0x86, 0xd5, 0x52, 0x46, 0x49, 0x7c, 0x5b, 0x63, 0x5e, 0x3c, 0xbc, 0x11, 0x96, 0xf5, 0x6e, 0x67, - 0x75, 0x7a, 0x34, 0x8c, 0x80, 0xb3, 0x41, 0x11, 0x87, 0x59, 0x6e, 0x65, 0xce, 0xe1, 0x21, 0x35, - 0x62, 0xa5, 0x39, 0x5d, 0x6c, 0xb0, 0x9e, 0x49, 0xd8, 0xa0, 0x38, 0x29, 0xc3, 0xfd, 0x8f, 0x22, - 0xcc, 0xa5, 0x34, 0x2d, 0x95, 0x21, 0x94, 0x9f, 0x66, 0x86, 0x50, 0x1a, 0x2b, 0x43, 0xc8, 0x0e, - 0x5e, 0x27, 0xc6, 0x0a, 0x5e, 0xdf, 0xd2, 0x01, 0xa4, 0xd9, 0xb9, 0xad, 0x4d, 0xf3, 0xaa, 0x34, - 0x5a, 0xcd, 0x6d, 0x9b, 0x88, 0x93, 0x7d, 0xd5, 0x09, 0xdf, 0x1c, 0xfc, 0x84, 0xd2, 0x44, 0xbf, - 0x6f, 0xe6, 0x7d, 0x16, 0x14, 0x01, 0xe8, 0x13, 0x3e, 0x83, 0x80, 0xb3, 0xc4, 0xd5, 0xee, 0x7e, - 0xf6, 0xe5, 0xca, 0xb9, 0xcf, 0xbf, 0x5c, 0x39, 0xf7, 0xc5, 0x97, 0x2b, 0xe7, 0xbe, 0x7f, 0xbc, - 0xe2, 0x7c, 0x76, 0xbc, 0xe2, 0x7c, 0x7e, 0xbc, 0xe2, 0x7c, 0x71, 0xbc, 0xe2, 0xfc, 0xf7, 0xf1, - 0x8a, 0xf3, 0xc3, 0x9f, 0xad, 0x9c, 0x7b, 0xf8, 0xfc, 0x28, 0xff, 0x47, 0xe3, 0xff, 0x03, 0x00, - 0x00, 0xff, 0xff, 0x6a, 0xff, 0x8d, 0xf8, 0x6e, 0x43, 0x00, 0x00, + // 3943 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x5c, 0xdd, 0x6f, 0x5b, 0x47, + 0x76, 0xf7, 0x25, 0x25, 0x4a, 0x3c, 0x94, 0x2c, 0x69, 0x2c, 0x27, 0x5a, 0x6d, 0x23, 0xb9, 0x37, + 0x41, 0x90, 0x34, 0x09, 0x55, 0xdb, 0x71, 0xe2, 0x38, 0x5b, 0x17, 0xa2, 0x64, 0x3b, 0x72, 0xb5, + 0xb1, 0x3a, 0x54, 0x9c, 0x8d, 0xd7, 0x41, 0x3a, 0x22, 0x47, 0xe4, 0xad, 0x48, 0x5e, 0xee, 0xcc, + 0x50, 0x1b, 0xb5, 0x45, 0xbb, 0xfd, 0x02, 0x16, 0x2d, 0x5a, 0xec, 0x43, 0x80, 0x6c, 0x81, 0x16, + 0x28, 0xda, 0xc7, 0x45, 0xfb, 0x0f, 0xf4, 0x21, 0x0f, 0xfb, 0x12, 0xb4, 0x41, 0x11, 0xb4, 0x7d, + 0x48, 0x81, 0x85, 0xd0, 0x68, 0x81, 0x3e, 0xe6, 0xad, 0x2f, 0x06, 0x0a, 0x14, 0xf3, 0x71, 0xef, + 0x9d, 0x7b, 0x79, 0x69, 0xf1, 0xd2, 0x92, 0x90, 0xee, 0x9b, 0x38, 0x67, 0xce, 0xef, 0xcc, 0x9c, + 0x99, 0x73, 0xe6, 0x9c, 0x33, 0x73, 0x05, 0xaf, 0x36, 0x3c, 0xd1, 0xec, 0xed, 0x94, 0x6b, 0x7e, + 0x7b, 0x85, 0xec, 0xf5, 0x3c, 0x71, 0xb0, 0xb2, 0x47, 0x58, 0xc3, 0x5f, 0x21, 0x5d, 0x6f, 0x65, + 0xff, 0x32, 0x69, 0x75, 0x9b, 0xe4, 0xf2, 0x4a, 0x83, 0x76, 0x28, 0x23, 0x82, 0xd6, 0xcb, 0x5d, + 0xe6, 0x0b, 0x1f, 0x3d, 0x17, 0x71, 0x95, 0x35, 0x57, 0x59, 0x71, 0x95, 0x49, 0xd7, 0x2b, 0x07, + 0x5c, 0x8b, 0xaf, 0x58, 0xd8, 0x0d, 0xbf, 0xe1, 0xaf, 0x28, 0xe6, 0x9d, 0xde, 0xae, 0xfa, 0xa5, + 0x7e, 0xa8, 0xbf, 0x34, 0xe8, 0xe2, 0x5b, 0x7b, 0xd7, 0x79, 0xd9, 0x53, 0x92, 0xe9, 0x87, 0x82, + 0x76, 0xb8, 0xe7, 0x77, 0xf8, 0x2b, 0xa4, 0xeb, 0x71, 0xca, 0xf6, 0x29, 0x5b, 0xe9, 0xee, 0x35, + 0x24, 0x8d, 0xc7, 0x3b, 0xac, 0xec, 0xf7, 0x0d, 0x6f, 0xf1, 0xd5, 0x08, 0xa9, 0x4d, 0x6a, 0x4d, + 0xaf, 0x43, 0xd9, 0x41, 0xc4, 0xde, 0xa6, 0x82, 0xa4, 0x71, 0xad, 0x0c, 0xe2, 0x62, 0xbd, 0x8e, + 0xf0, 0xda, 0xb4, 0x8f, 0xe1, 0xb5, 0xe3, 0x18, 0x78, 0xad, 0x49, 0xdb, 0x24, 0xc9, 0xe7, 0x3e, + 0x84, 0x0b, 0xab, 0x1d, 0xd2, 0x3a, 0xe0, 0x1e, 0xc7, 0xbd, 0xce, 0x2a, 0x6b, 0xf4, 0xda, 0xb4, + 0x23, 0xd0, 0x25, 0x18, 0xeb, 0x90, 0x36, 0x5d, 0x70, 0x2e, 0x39, 0x2f, 0x14, 0x2b, 0x53, 0x9f, + 0x1e, 0x2e, 0x9f, 0x3b, 0x3a, 0x5c, 0x1e, 0x7b, 0x9b, 0xb4, 0x29, 0x56, 0x14, 0xf4, 0x2c, 0x8c, + 0xef, 0x93, 0x56, 0x8f, 0x2e, 0xe4, 0x54, 0x97, 0x69, 0xd3, 0x65, 0xfc, 0xbe, 0x6c, 0xc4, 0x9a, + 0xe6, 0xfe, 0x71, 0x3e, 0x06, 0xff, 0x6d, 0x2a, 0x48, 0x9d, 0x08, 0x82, 0xda, 0x50, 0x68, 0x91, + 0x1d, 0xda, 0xe2, 0x0b, 0xce, 0xa5, 0xfc, 0x0b, 0xa5, 0x2b, 0xb7, 0xca, 0xc3, 0x2c, 0x62, 0x39, + 0x05, 0xaa, 0xbc, 0xa9, 0x70, 0x6e, 0x75, 0x04, 0x3b, 0xa8, 0x9c, 0x37, 0x83, 0x28, 0xe8, 0x46, + 0x6c, 0x84, 0xa0, 0x3f, 0x74, 0xa0, 0x44, 0x3a, 0x1d, 0x5f, 0x10, 0x21, 0x97, 0x69, 0x21, 0xa7, + 0x84, 0xde, 0x1d, 0x5d, 0xe8, 0x6a, 0x04, 0xa6, 0x25, 0x5f, 0x30, 0x92, 0x4b, 0x16, 0x05, 0xdb, + 0x32, 0x17, 0xdf, 0x80, 0x92, 0x35, 0x54, 0x34, 0x0b, 0xf9, 0x3d, 0x7a, 0xa0, 0xf5, 0x8b, 0xe5, + 0x9f, 0x68, 0x3e, 0xa6, 0x50, 0xa3, 0xc1, 0x1b, 0xb9, 0xeb, 0xce, 0xe2, 0x4d, 0x98, 0x4d, 0x0a, + 0xcc, 0xc2, 0xef, 0xfe, 0xa5, 0x03, 0xf3, 0xd6, 0x2c, 0x30, 0xdd, 0xa5, 0x8c, 0x76, 0x6a, 0x14, + 0xad, 0x40, 0x51, 0xae, 0x25, 0xef, 0x92, 0x5a, 0xb0, 0xd4, 0x73, 0x66, 0x22, 0xc5, 0xb7, 0x03, + 0x02, 0x8e, 0xfa, 0x84, 0xdb, 0x22, 0xf7, 0xb8, 0x6d, 0xd1, 0x6d, 0x12, 0x4e, 0x17, 0xf2, 0xf1, + 0x6d, 0xb1, 0x25, 0x1b, 0xb1, 0xa6, 0xb9, 0xbf, 0x06, 0xdf, 0x08, 0xc6, 0xb3, 0x4d, 0xdb, 0xdd, + 0x16, 0x11, 0x34, 0x1a, 0xd4, 0xb1, 0x5b, 0xcf, 0xdd, 0x83, 0xe9, 0xd5, 0x6e, 0x97, 0xf9, 0xfb, + 0xb4, 0x5e, 0x15, 0xa4, 0x41, 0xd1, 0x03, 0x00, 0x62, 0x1a, 0x56, 0x85, 0x62, 0x2c, 0x5d, 0xf9, + 0x95, 0xb2, 0xb6, 0x88, 0xb2, 0x6d, 0x11, 0xe5, 0xee, 0x5e, 0x43, 0x36, 0xf0, 0xb2, 0x34, 0xbc, + 0xf2, 0xfe, 0xe5, 0xf2, 0xb6, 0xd7, 0xa6, 0x95, 0xf3, 0x47, 0x87, 0xcb, 0xb0, 0x1a, 0x22, 0x60, + 0x0b, 0xcd, 0xfd, 0x23, 0x07, 0x2e, 0xae, 0xb2, 0x86, 0xbf, 0xb6, 0xbe, 0xda, 0xed, 0xbe, 0x45, + 0x49, 0x4b, 0x34, 0xab, 0x82, 0x88, 0x1e, 0x47, 0x37, 0xa1, 0xc0, 0xd5, 0x5f, 0x66, 0xa8, 0xcf, + 0x07, 0xbb, 0x4f, 0xd3, 0x1f, 0x1d, 0x2e, 0xcf, 0xa7, 0x30, 0x52, 0x6c, 0xb8, 0xd0, 0x8b, 0x30, + 0xd1, 0xa6, 0x9c, 0x93, 0x46, 0xa0, 0xcf, 0x19, 0x03, 0x30, 0xf1, 0x6d, 0xdd, 0x8c, 0x03, 0xba, + 0xfb, 0xcf, 0x39, 0x98, 0x09, 0xb1, 0x8c, 0xf8, 0x53, 0x58, 0xbc, 0x1e, 0x4c, 0x35, 0xad, 0x19, + 0xaa, 0x35, 0x2c, 0x5d, 0x79, 0x73, 0x48, 0x3b, 0x49, 0x53, 0x52, 0x65, 0xde, 0x88, 0x99, 0xb2, + 0x5b, 0x71, 0x4c, 0x0c, 0x6a, 0x03, 0xf0, 0x83, 0x4e, 0xcd, 0x08, 0x1d, 0x53, 0x42, 0xdf, 0xc8, + 0x28, 0xb4, 0x1a, 0x02, 0x54, 0x90, 0x11, 0x09, 0x51, 0x1b, 0xb6, 0x04, 0xb8, 0xff, 0xe8, 0xc0, + 0x85, 0x14, 0x3e, 0xf4, 0xad, 0xc4, 0x7a, 0x3e, 0xd7, 0xb7, 0x9e, 0xa8, 0x8f, 0x2d, 0x5a, 0xcd, + 0x97, 0x61, 0x92, 0xd1, 0x7d, 0x4f, 0x9e, 0x03, 0x46, 0xc3, 0xb3, 0x86, 0x7f, 0x12, 0x9b, 0x76, + 0x1c, 0xf6, 0x40, 0x2f, 0x41, 0x31, 0xf8, 0x5b, 0xaa, 0x39, 0x2f, 0x4d, 0x45, 0x2e, 0x5c, 0xd0, + 0x95, 0xe3, 0x88, 0xee, 0xfe, 0x01, 0x8c, 0xaf, 0x35, 0x09, 0x13, 0x72, 0xc7, 0x30, 0xda, 0xf5, + 0xdf, 0xc1, 0x9b, 0x66, 0x88, 0xe1, 0x8e, 0xc1, 0xba, 0x19, 0x07, 0xf4, 0x21, 0x16, 0xfb, 0x45, + 0x98, 0xd8, 0xa7, 0x4c, 0x8d, 0x37, 0x1f, 0x07, 0xbb, 0xaf, 0x9b, 0x71, 0x40, 0x77, 0xff, 0xdd, + 0x81, 0x79, 0x35, 0x82, 0x75, 0x8f, 0xd7, 0xfc, 0x7d, 0xca, 0x0e, 0x30, 0xe5, 0xbd, 0xd6, 0x09, + 0x0f, 0x68, 0x1d, 0x66, 0x39, 0x6d, 0xef, 0x53, 0xb6, 0xe6, 0x77, 0xb8, 0x60, 0xc4, 0xeb, 0x08, + 0x33, 0xb2, 0x05, 0xd3, 0x7b, 0xb6, 0x9a, 0xa0, 0xe3, 0x3e, 0x0e, 0xf4, 0x02, 0x4c, 0x9a, 0x61, + 0xcb, 0xad, 0x24, 0x15, 0x3b, 0x25, 0xd7, 0xc0, 0xcc, 0x89, 0xe3, 0x90, 0xea, 0xfe, 0xb7, 0x03, + 0x73, 0x6a, 0x56, 0xd5, 0xde, 0x0e, 0xaf, 0x31, 0xaf, 0x2b, 0xdd, 0xeb, 0xd7, 0x71, 0x4a, 0x37, + 0xe1, 0x7c, 0x3d, 0x50, 0xfc, 0xa6, 0xd7, 0xf6, 0x84, 0xb2, 0x91, 0xf1, 0xca, 0x53, 0x06, 0xe3, + 0xfc, 0x7a, 0x8c, 0x8a, 0x13, 0xbd, 0xf5, 0xf2, 0xb5, 0x7a, 0x5c, 0x50, 0xb6, 0xc5, 0xfc, 0xb6, + 0x2f, 0xe7, 0xb9, 0x4d, 0xf8, 0x1e, 0xfa, 0x2d, 0x98, 0x6c, 0x9b, 0x23, 0xcd, 0x78, 0xcd, 0x5f, + 0x1d, 0xce, 0x6b, 0xde, 0xdb, 0xf9, 0x6d, 0x5a, 0x13, 0xf2, 0x38, 0x8c, 0xac, 0x2d, 0x6a, 0xc3, + 0x21, 0x2a, 0x7a, 0x0f, 0xc6, 0x78, 0x97, 0xd6, 0x94, 0x8a, 0x4a, 0x57, 0x5e, 0x1f, 0xce, 0xa8, + 0x63, 0x83, 0xac, 0x76, 0x69, 0x2d, 0xd2, 0xad, 0xfc, 0x85, 0x15, 0xa4, 0xfb, 0x9f, 0x0e, 0x2c, + 0xa4, 0xcd, 0x6a, 0xd3, 0xe3, 0x02, 0x3d, 0xec, 0x9b, 0x59, 0x79, 0xb8, 0x99, 0x49, 0x6e, 0x35, + 0xaf, 0xd0, 0x7a, 0x83, 0x16, 0x6b, 0x56, 0x1f, 0xc0, 0xb8, 0x27, 0x68, 0x3b, 0x08, 0x24, 0x6e, + 0x0c, 0x37, 0xad, 0xb4, 0xc1, 0x46, 0x07, 0xe4, 0x86, 0x04, 0xc4, 0x1a, 0xd7, 0xfd, 0xeb, 0x3c, + 0x5c, 0x08, 0x16, 0x95, 0xd6, 0x57, 0x99, 0xf0, 0x76, 0x49, 0x4d, 0x70, 0x54, 0x87, 0xa9, 0x7a, + 0xd4, 0x2c, 0x8c, 0xaf, 0xcc, 0x72, 0xd4, 0x85, 0xfe, 0xd8, 0x82, 0x17, 0x38, 0x86, 0x8a, 0xde, + 0x85, 0x7c, 0xc3, 0x13, 0x26, 0x34, 0xbb, 0x3e, 0xdc, 0xe4, 0xee, 0x78, 0x49, 0xe7, 0x50, 0x29, + 0x19, 0x51, 0xf9, 0x3b, 0x9e, 0xc0, 0x12, 0x11, 0xed, 0x40, 0xc1, 0x6b, 0x93, 0x06, 0xcd, 0xa8, + 0xb8, 0x0d, 0xc9, 0x93, 0x44, 0x0f, 0x63, 0x3d, 0x45, 0xe5, 0xd8, 0x20, 0x4b, 0x19, 0x35, 0x69, + 0xd4, 0xda, 0xad, 0x0e, 0xbf, 0x38, 0x29, 0xee, 0x2d, 0x92, 0xa1, 0xa8, 0x1c, 0x1b, 0x64, 0xf7, + 0x8b, 0x1c, 0xcc, 0x46, 0xfa, 0x5b, 0xf3, 0xdb, 0x6d, 0x4f, 0xa0, 0x45, 0xc8, 0x79, 0x75, 0xe3, + 0x33, 0xc0, 0x30, 0xe6, 0x36, 0xd6, 0x71, 0xce, 0xab, 0xa3, 0xe7, 0xa1, 0xb0, 0xc3, 0x48, 0xa7, + 0xd6, 0x34, 0xbe, 0x22, 0x04, 0xae, 0xa8, 0x56, 0x6c, 0xa8, 0xe8, 0x19, 0xc8, 0x0b, 0xd2, 0x30, + 0x2e, 0x22, 0xd4, 0xdf, 0x36, 0x69, 0x60, 0xd9, 0x2e, 0x7d, 0x13, 0xef, 0x29, 0x33, 0x53, 0x2b, + 0x6f, 0xf9, 0xa6, 0xaa, 0x6e, 0xc6, 0x01, 0x5d, 0x4a, 0x24, 0x3d, 0xd1, 0xf4, 0xd9, 0xc2, 0x78, + 0x5c, 0xe2, 0xaa, 0x6a, 0xc5, 0x86, 0x2a, 0xa3, 0x88, 0x9a, 0x1a, 0xbf, 0xa0, 0x6c, 0xa1, 0x10, + 0x8f, 0x22, 0xd6, 0x02, 0x02, 0x8e, 0xfa, 0xa0, 0xf7, 0xa1, 0x54, 0x63, 0x94, 0x08, 0x9f, 0xad, + 0x13, 0x41, 0x17, 0x26, 0x32, 0xef, 0xc0, 0x19, 0x19, 0x26, 0xaf, 0x45, 0x10, 0xd8, 0xc6, 0x73, + 0xbf, 0x72, 0x60, 0x21, 0x52, 0xad, 0x5a, 0xdb, 0x28, 0x34, 0x34, 0xea, 0x71, 0x06, 0xa8, 0xe7, + 0x79, 0x28, 0xd4, 0xbd, 0x06, 0xe5, 0x22, 0xa9, 0xe5, 0x75, 0xd5, 0x8a, 0x0d, 0x15, 0x5d, 0x01, + 0x68, 0x78, 0xc2, 0xb8, 0x73, 0xa3, 0xec, 0xd0, 0x8d, 0xdd, 0x09, 0x29, 0xd8, 0xea, 0x85, 0xde, + 0x85, 0xa2, 0x1a, 0xe6, 0x88, 0x66, 0xa7, 0x0e, 0xf7, 0xb5, 0x00, 0x00, 0x47, 0x58, 0xee, 0xe7, + 0x63, 0x30, 0x71, 0x9b, 0x51, 0xaf, 0xd1, 0x14, 0x67, 0xe0, 0x8f, 0x9f, 0x85, 0x71, 0xd2, 0xf2, + 0x08, 0x57, 0xeb, 0x66, 0x85, 0xe7, 0xab, 0xb2, 0x11, 0x6b, 0x1a, 0xfa, 0x2e, 0x14, 0x7c, 0xe6, + 0x35, 0xbc, 0xce, 0x42, 0x51, 0x0d, 0xe2, 0xea, 0x70, 0x26, 0x64, 0x66, 0x71, 0x4f, 0xb1, 0x46, + 0xca, 0xd7, 0xbf, 0xb1, 0x81, 0x44, 0x0f, 0x60, 0x42, 0x6f, 0xa6, 0xc0, 0x40, 0x57, 0x86, 0x76, + 0x30, 0x7a, 0x3f, 0x46, 0x9b, 0x5e, 0xff, 0xe6, 0x38, 0x00, 0x44, 0xd5, 0xd0, 0xbf, 0x8c, 0x29, + 0xe8, 0x97, 0x32, 0xf8, 0x97, 0x81, 0x0e, 0xa5, 0x1a, 0x3a, 0x94, 0xf1, 0x2c, 0xa0, 0xca, 0x65, + 0x0c, 0xf2, 0x20, 0x52, 0xc5, 0x26, 0xd6, 0x2c, 0x8c, 0xa0, 0x62, 0x13, 0xe8, 0x9e, 0x8f, 0x07, + 0xa8, 0x41, 0x28, 0xea, 0x7e, 0x94, 0x87, 0x39, 0xd3, 0x73, 0xcd, 0x6f, 0xb5, 0x68, 0x4d, 0x05, + 0x36, 0xda, 0x3f, 0xe5, 0x53, 0xfd, 0x93, 0x17, 0x1c, 0x68, 0xda, 0xe7, 0x57, 0x32, 0x8d, 0x26, + 0x92, 0x51, 0x56, 0x87, 0x98, 0xce, 0x88, 0xc3, 0x55, 0x32, 0xbd, 0xcc, 0xd1, 0x86, 0xfe, 0xd4, + 0x81, 0x0b, 0xfb, 0x94, 0x79, 0xbb, 0x5e, 0x4d, 0xe5, 0xb3, 0x6f, 0x79, 0x5c, 0xf8, 0xec, 0xc0, + 0x9c, 0x08, 0xaf, 0x0d, 0x27, 0xf9, 0xbe, 0x05, 0xb0, 0xd1, 0xd9, 0xf5, 0x2b, 0xdf, 0x34, 0xd2, + 0x2e, 0xdc, 0xef, 0x87, 0xc6, 0x69, 0xf2, 0x16, 0xbb, 0x00, 0xd1, 0x68, 0x53, 0xd2, 0xe9, 0x4d, + 0x3b, 0x9d, 0x1e, 0x7a, 0x60, 0xc1, 0x64, 0x03, 0x97, 0x65, 0xa7, 0xe1, 0x9f, 0x38, 0x50, 0x32, + 0xf4, 0x33, 0x88, 0x51, 0x70, 0x3c, 0x46, 0x79, 0x25, 0xd3, 0xf8, 0x07, 0x84, 0x25, 0x0c, 0xa6, + 0x63, 0x46, 0x8e, 0xae, 0xc1, 0xd8, 0x9e, 0xd7, 0x09, 0x4e, 0xbd, 0x5f, 0x0e, 0xa2, 0xb4, 0xdf, + 0xf0, 0x3a, 0xf5, 0x47, 0x87, 0xcb, 0x73, 0xb1, 0xce, 0xb2, 0x11, 0xab, 0xee, 0xc7, 0x07, 0xce, + 0x37, 0x26, 0x7f, 0xfc, 0xb7, 0xcb, 0xe7, 0x7e, 0xf0, 0xb3, 0x4b, 0xe7, 0xdc, 0x8f, 0xf3, 0x30, + 0x9b, 0xd4, 0xea, 0x10, 0xe5, 0xa9, 0xc8, 0x87, 0x4d, 0x9e, 0xaa, 0x0f, 0xcb, 0x9d, 0x9e, 0x0f, + 0xcb, 0x9f, 0x86, 0x0f, 0x1b, 0x3b, 0x31, 0x1f, 0xe6, 0xfe, 0xab, 0x03, 0xe7, 0xc3, 0x95, 0xf9, + 0x5e, 0x4f, 0x9e, 0xac, 0x91, 0xd6, 0x9d, 0x93, 0xd7, 0xfa, 0x07, 0x30, 0xc1, 0xfd, 0x1e, 0xab, + 0xa9, 0xf0, 0x51, 0xa2, 0xbf, 0x9a, 0xcd, 0x69, 0x6a, 0x5e, 0x2b, 0x66, 0xd2, 0x0d, 0x38, 0x40, + 0x75, 0x1f, 0x86, 0xf3, 0x31, 0x24, 0x1d, 0x51, 0x30, 0x19, 0x6f, 0xc9, 0xf9, 0x4c, 0xda, 0x11, + 0x85, 0x6c, 0xc5, 0x86, 0x8a, 0x5c, 0xe5, 0xce, 0x83, 0xc0, 0xb6, 0x58, 0x01, 0xe3, 0x95, 0xd5, + 0x1a, 0x68, 0x8a, 0xfb, 0x55, 0x3e, 0xb4, 0x1e, 0x53, 0x70, 0xf8, 0x3e, 0x80, 0xf6, 0x4c, 0xb4, + 0xbe, 0xd1, 0x31, 0xae, 0x77, 0x6d, 0x84, 0x83, 0xc0, 0xb8, 0x43, 0x89, 0xa2, 0x7d, 0x6f, 0x18, + 0x03, 0x44, 0x04, 0x6c, 0x89, 0x42, 0xbf, 0x0b, 0xa5, 0xa0, 0xc2, 0x75, 0xdb, 0x67, 0x66, 0x0f, + 0xaf, 0x8f, 0x22, 0x79, 0x35, 0x82, 0x49, 0x16, 0x42, 0x23, 0x0a, 0xb6, 0xa5, 0x2d, 0x32, 0x98, + 0x49, 0x8c, 0x37, 0xc5, 0xfb, 0x6e, 0xc4, 0xbd, 0xef, 0xd5, 0x2c, 0xc7, 0x82, 0xa9, 0x0a, 0xda, + 0x15, 0x54, 0x0e, 0xb3, 0xc9, 0x91, 0x9e, 0x98, 0xd0, 0x58, 0x29, 0xd2, 0xf6, 0xf7, 0x7f, 0x93, + 0x83, 0x62, 0x68, 0xf1, 0x59, 0xea, 0x0a, 0xfa, 0xa4, 0xce, 0x1d, 0x93, 0x49, 0xe4, 0x87, 0xc9, + 0x24, 0xc6, 0x06, 0x67, 0x12, 0x41, 0xed, 0xb1, 0xf0, 0xf8, 0xda, 0xa3, 0x95, 0x49, 0x4c, 0x0c, + 0x9f, 0x49, 0x4c, 0x1e, 0x9f, 0x49, 0xb8, 0x7f, 0xe7, 0x00, 0xea, 0x4f, 0x1b, 0xb3, 0x28, 0x8a, + 0x24, 0xfd, 0xf0, 0x90, 0xa7, 0x74, 0x32, 0x77, 0x1b, 0xec, 0x8e, 0xdd, 0x4f, 0xc6, 0x61, 0xe6, + 0x8e, 0x37, 0x72, 0x89, 0x48, 0xc0, 0xd3, 0x1a, 0xa9, 0x4a, 0x4d, 0x8c, 0x54, 0x15, 0x8c, 0x08, + 0xda, 0x38, 0x30, 0xeb, 0x7b, 0xc3, 0xb0, 0x3e, 0xbd, 0x96, 0xde, 0xed, 0xd1, 0x60, 0x12, 0x1e, + 0x04, 0x3d, 0xf4, 0x26, 0x79, 0x13, 0xa6, 0xb9, 0x60, 0x5e, 0x4d, 0xe8, 0x22, 0x14, 0x5f, 0x28, + 0x29, 0x2f, 0x77, 0xd1, 0x74, 0x9f, 0xae, 0xda, 0x44, 0x1c, 0xef, 0x9b, 0x5a, 0xdb, 0x1a, 0xcb, + 0x5c, 0xdb, 0x5a, 0x81, 0x22, 0x69, 0xb5, 0xfc, 0xef, 0x6f, 0x93, 0x06, 0x37, 0xa9, 0x6a, 0xb8, + 0x6b, 0x56, 0x03, 0x02, 0x8e, 0xfa, 0xa0, 0x32, 0x80, 0xd7, 0xe8, 0xf8, 0x8c, 0x2a, 0x8e, 0x82, + 0x72, 0xb7, 0xaa, 0x7e, 0xbf, 0x11, 0xb6, 0x62, 0xab, 0x07, 0xaa, 0xc2, 0x45, 0xaf, 0xc3, 0x69, + 0xad, 0xc7, 0x68, 0x75, 0xcf, 0xeb, 0x6e, 0x6f, 0x56, 0x95, 0x97, 0x38, 0x50, 0xbb, 0x79, 0xb2, + 0xf2, 0x8c, 0x11, 0x76, 0x71, 0x23, 0xad, 0x13, 0x4e, 0xe7, 0x45, 0xaf, 0xc2, 0x94, 0xd7, 0xa9, + 0xb5, 0x7a, 0x75, 0xba, 0x45, 0x44, 0x93, 0x2f, 0x4c, 0xaa, 0x61, 0xcc, 0x1e, 0x1d, 0x2e, 0x4f, + 0x6d, 0x58, 0xed, 0x38, 0xd6, 0x4b, 0x72, 0xd1, 0x0f, 0x2d, 0xae, 0x62, 0xc4, 0x75, 0xeb, 0x43, + 0x9b, 0xcb, 0xee, 0x95, 0x52, 0xfd, 0x83, 0x4c, 0xd5, 0xbf, 0x9f, 0xe4, 0xa0, 0xa0, 0x8b, 0xef, + 0xe8, 0x5a, 0xa2, 0xc2, 0xfd, 0x4c, 0x5f, 0x85, 0xbb, 0x94, 0x76, 0x51, 0xe1, 0x42, 0xc1, 0xe3, + 0xbc, 0x17, 0x3f, 0xdd, 0x36, 0x54, 0x0b, 0x36, 0x14, 0x55, 0x76, 0xf1, 0x3b, 0xbb, 0x5e, 0xc3, + 0x24, 0xc7, 0x37, 0xad, 0x50, 0x36, 0xba, 0x20, 0xfd, 0x20, 0xbc, 0x41, 0x8d, 0xa2, 0xda, 0x58, + 0x07, 0x19, 0xde, 0xde, 0xad, 0xde, 0x7b, 0x5b, 0xcb, 0x58, 0x53, 0x88, 0xd8, 0x20, 0x4b, 0x19, + 0x7e, 0x4f, 0x74, 0x7b, 0x42, 0x6d, 0x94, 0x13, 0x92, 0x71, 0x4f, 0x21, 0x62, 0x83, 0xec, 0x7e, + 0xec, 0xc0, 0x8c, 0xd6, 0xc1, 0x5a, 0x93, 0xd6, 0xf6, 0xaa, 0x82, 0x76, 0x65, 0xb4, 0xd9, 0xe3, + 0x94, 0x27, 0xa3, 0xcd, 0x77, 0x38, 0xe5, 0x58, 0x51, 0xac, 0xd9, 0xe7, 0x4e, 0x6b, 0xf6, 0xee, + 0x3f, 0x38, 0x30, 0xae, 0xc2, 0xba, 0x2c, 0xfe, 0x27, 0x5e, 0xea, 0xc8, 0x0d, 0x55, 0xea, 0x38, + 0xa6, 0x08, 0x15, 0x55, 0x59, 0xc6, 0x1e, 0x57, 0x65, 0x71, 0x7f, 0xee, 0xc0, 0x7c, 0x5a, 0xe5, + 0x2e, 0xcb, 0xf0, 0x5f, 0x86, 0xc9, 0x6e, 0x8b, 0x88, 0x5d, 0x9f, 0xb5, 0x93, 0x97, 0x2a, 0x5b, + 0xa6, 0x1d, 0x87, 0x3d, 0x10, 0x03, 0x60, 0x41, 0x8a, 0x10, 0x84, 0xcf, 0x37, 0xb3, 0x9e, 0x08, + 0xf1, 0x92, 0x53, 0xa4, 0xac, 0xb0, 0x89, 0x63, 0x4b, 0x8a, 0xfb, 0xe7, 0xe3, 0x30, 0xa7, 0x58, + 0x46, 0x3d, 0x21, 0x46, 0x59, 0xa1, 0x2e, 0x3c, 0xa5, 0x02, 0xfb, 0xfe, 0x43, 0x45, 0x2f, 0xda, + 0x75, 0xc3, 0xff, 0xd4, 0x46, 0x6a, 0xaf, 0x47, 0x03, 0x29, 0x78, 0x00, 0x6e, 0xff, 0x49, 0x01, + 0xbf, 0x78, 0x27, 0x85, 0xbd, 0xd9, 0x26, 0x8e, 0xdd, 0x6c, 0x03, 0xcf, 0x95, 0xc9, 0x27, 0x38, + 0x57, 0xfa, 0x7d, 0x7d, 0x31, 0x93, 0xaf, 0xff, 0xab, 0x1c, 0x4c, 0x6c, 0x31, 0x5f, 0x55, 0x80, + 0x4f, 0xbf, 0x98, 0x78, 0x2f, 0x76, 0xb9, 0x73, 0x79, 0xe8, 0xcb, 0x1d, 0x09, 0xa5, 0xae, 0x75, + 0x26, 0xe3, 0x57, 0x3a, 0x56, 0x55, 0x2c, 0x9f, 0x25, 0x02, 0x0f, 0x20, 0x1f, 0x5f, 0x15, 0xfb, + 0xc4, 0x81, 0x92, 0xe9, 0xf9, 0xb5, 0x2d, 0xbf, 0x98, 0xf1, 0x0d, 0x28, 0xbf, 0xfc, 0x45, 0x34, + 0x03, 0xa9, 0x34, 0xf4, 0xfb, 0x30, 0xd7, 0x0d, 0x2e, 0x93, 0xb6, 0xfc, 0x96, 0x57, 0xf3, 0x68, + 0x50, 0xc1, 0xbb, 0x96, 0xf1, 0xa6, 0x4d, 0xb1, 0x1f, 0x54, 0xbe, 0x61, 0xe4, 0xce, 0x6d, 0x25, + 0x71, 0x71, 0xbf, 0x28, 0xf7, 0x3f, 0x1c, 0x98, 0x8e, 0xe9, 0x1e, 0xd5, 0x00, 0x6a, 0x7e, 0xa7, + 0xee, 0x89, 0xf0, 0x5e, 0xbb, 0x74, 0x65, 0x65, 0x38, 0xad, 0xae, 0x05, 0x7c, 0xd1, 0xa6, 0x0b, + 0x9b, 0x38, 0xb6, 0x60, 0xd1, 0xd5, 0xe0, 0x89, 0x49, 0x3c, 0x88, 0xd1, 0x4f, 0x4c, 0x1e, 0x1d, + 0x2e, 0x4f, 0x99, 0x31, 0xd9, 0x4f, 0x4e, 0xb2, 0x3c, 0xb6, 0xf8, 0xfb, 0x1c, 0x14, 0xc3, 0xf9, + 0x9f, 0x81, 0x19, 0xbd, 0x13, 0x33, 0xa3, 0xab, 0x19, 0x57, 0x6e, 0xd0, 0xfd, 0x28, 0x7a, 0x3f, + 0x61, 0x4c, 0x59, 0xb7, 0xc4, 0x31, 0xe6, 0xf4, 0x53, 0xbd, 0xf8, 0xba, 0xef, 0x19, 0x18, 0xd4, + 0x76, 0xdc, 0xa0, 0x56, 0x32, 0xce, 0x66, 0x80, 0x49, 0xfd, 0xd0, 0x81, 0x99, 0x84, 0x11, 0xa0, + 0x67, 0x61, 0x5c, 0x95, 0x6c, 0xcc, 0xfe, 0x0a, 0x19, 0x4d, 0x82, 0xaf, 0x68, 0x68, 0x0b, 0xe6, + 0x49, 0x4f, 0xf8, 0x21, 0xef, 0xad, 0x0e, 0xd9, 0x69, 0x51, 0x9d, 0xb5, 0x4f, 0x56, 0x7e, 0xc9, + 0xf0, 0xcc, 0xaf, 0xa6, 0xf4, 0xc1, 0xa9, 0x9c, 0xee, 0x67, 0x39, 0x40, 0x61, 0x63, 0x96, 0x52, + 0xe7, 0xfb, 0x30, 0xb1, 0xab, 0x8b, 0x32, 0x4f, 0x56, 0xab, 0xae, 0x94, 0xec, 0x72, 0x7d, 0x80, + 0x89, 0xde, 0x3b, 0x99, 0x7d, 0x04, 0xfd, 0x7b, 0x08, 0x3d, 0x00, 0xd8, 0xf5, 0x3a, 0x1e, 0x6f, + 0x8e, 0x78, 0xab, 0xa6, 0x4e, 0xf3, 0xdb, 0x21, 0x02, 0xb6, 0xd0, 0xdc, 0x8f, 0x72, 0xd6, 0xfe, + 0x54, 0xee, 0x72, 0xa8, 0x75, 0x7d, 0x31, 0xae, 0xcc, 0x62, 0xff, 0x3d, 0x86, 0xa5, 0x98, 0xb1, + 0x7d, 0xc2, 0x82, 0x92, 0x6a, 0xd6, 0xb7, 0x0d, 0xf7, 0x09, 0xf3, 0xe4, 0xc2, 0x47, 0x4b, 0x7a, + 0x9f, 0x30, 0x8e, 0x15, 0x24, 0xfa, 0x8e, 0x1c, 0x2a, 0xed, 0x06, 0x2e, 0x34, 0xb3, 0x4f, 0x10, + 0xb4, 0x6b, 0xcf, 0x8f, 0x76, 0x39, 0xd6, 0x80, 0xee, 0x47, 0x13, 0xd6, 0x86, 0x37, 0x5e, 0xfb, + 0x2e, 0xa0, 0x16, 0xe1, 0xe2, 0x2d, 0xd2, 0xa9, 0xcb, 0xed, 0x49, 0x77, 0x19, 0xe5, 0x4d, 0x13, + 0xa1, 0x2d, 0x1a, 0x14, 0xb4, 0xd9, 0xd7, 0x03, 0xa7, 0x70, 0xa1, 0x6b, 0x71, 0xe7, 0xbc, 0x9c, + 0x74, 0xce, 0xe7, 0x23, 0x6b, 0x1b, 0xcd, 0x3d, 0xdb, 0xdb, 0x7d, 0xfc, 0x14, 0xb6, 0xfb, 0xef, + 0xc1, 0xdc, 0x6e, 0xf2, 0x5e, 0xcb, 0xdc, 0x72, 0xbf, 0x3e, 0xe2, 0xb5, 0x58, 0xe5, 0xe2, 0x51, + 0x74, 0x19, 0x12, 0x35, 0xe3, 0x7e, 0x41, 0xc8, 0x0f, 0x5e, 0xe0, 0xa9, 0xec, 0x53, 0x17, 0x16, + 0x86, 0x36, 0xb9, 0x44, 0xde, 0x9a, 0x7c, 0x7b, 0xa7, 0x21, 0x71, 0x4c, 0x40, 0xc2, 0x04, 0x0b, + 0x27, 0x69, 0x82, 0xe8, 0x1a, 0x94, 0x6a, 0x3d, 0xc6, 0x68, 0x47, 0xc8, 0xe1, 0xa8, 0x50, 0x36, + 0x1f, 0x15, 0x88, 0xd7, 0x22, 0x12, 0xb6, 0xfb, 0xa1, 0x1f, 0x39, 0x70, 0x51, 0x6e, 0xd6, 0x5b, + 0x1f, 0xd2, 0x5a, 0x4f, 0x6a, 0x25, 0x78, 0x76, 0xbb, 0x50, 0x52, 0xda, 0x18, 0xf2, 0x3d, 0x62, + 0x35, 0x0d, 0x22, 0x8a, 0xcb, 0x53, 0xc9, 0x38, 0x5d, 0x30, 0xfa, 0x40, 0xb9, 0x0e, 0x41, 0x55, + 0xda, 0xf3, 0xe4, 0xe9, 0x7d, 0xd1, 0xb8, 0x1d, 0xa1, 0xdd, 0x8e, 0xa0, 0xee, 0x4f, 0xf3, 0xb6, + 0xb7, 0x1a, 0xae, 0xe8, 0xf0, 0x00, 0xc6, 0x04, 0xe1, 0x7b, 0xc6, 0x0a, 0xbe, 0x35, 0xc2, 0xdb, + 0xaa, 0xc8, 0x16, 0x54, 0x24, 0xae, 0x9a, 0x14, 0x26, 0x5a, 0x84, 0x1c, 0xe1, 0xc9, 0x12, 0xf4, + 0x2a, 0xc7, 0x39, 0xc2, 0xd1, 0x7b, 0x30, 0xce, 0xa8, 0x60, 0x07, 0xc6, 0x61, 0x5f, 0x1f, 0xc1, + 0x39, 0x61, 0xc9, 0xaf, 0xd5, 0xa0, 0xfe, 0xc4, 0x1a, 0x31, 0x74, 0xa9, 0x85, 0x93, 0x77, 0xa9, + 0x51, 0x89, 0x26, 0x7f, 0x6a, 0x25, 0x9a, 0x9f, 0x38, 0xd6, 0x11, 0x1e, 0xce, 0x13, 0xbd, 0x03, + 0x13, 0xc2, 0x6b, 0x53, 0xbf, 0x27, 0xb2, 0xc5, 0x45, 0xeb, 0x3d, 0xa6, 0xae, 0xac, 0xb5, 0xa7, + 0xda, 0xd6, 0x10, 0x38, 0xc0, 0x92, 0xc9, 0x22, 0x65, 0xcc, 0x67, 0xdb, 0x4d, 0xe9, 0x79, 0xfd, + 0x96, 0x0e, 0x3e, 0xa6, 0xa3, 0x64, 0xf1, 0x56, 0x8c, 0x8a, 0x13, 0xbd, 0xdd, 0xcf, 0xec, 0x08, + 0xee, 0xff, 0xff, 0x7b, 0xc0, 0x7f, 0x71, 0x60, 0xee, 0xac, 0x1f, 0x02, 0x7e, 0x27, 0x1e, 0x94, + 0x5e, 0x1d, 0x61, 0x3e, 0x03, 0x02, 0xd3, 0x87, 0xf0, 0x54, 0xba, 0xa9, 0x0e, 0x11, 0x10, 0x5e, + 0x32, 0xb7, 0xf2, 0x89, 0xeb, 0xf5, 0xe8, 0x02, 0xde, 0xfd, 0x34, 0xa9, 0x2b, 0x15, 0x20, 0x05, + 0xd6, 0xe7, 0x9c, 0x62, 0x40, 0x93, 0x3b, 0xe9, 0x80, 0x86, 0xd9, 0x33, 0x31, 0x1f, 0x13, 0xa0, + 0xf7, 0xcd, 0x36, 0x73, 0xb2, 0x3c, 0x60, 0xef, 0x83, 0x19, 0xb8, 0xd5, 0x3e, 0x73, 0xe0, 0x62, + 0x6a, 0xef, 0x50, 0x85, 0xb9, 0x53, 0x54, 0xa1, 0x73, 0xd2, 0x2a, 0x7c, 0x60, 0xa9, 0x30, 0x18, + 0xc2, 0x49, 0x7d, 0x01, 0xf4, 0xe3, 0x1c, 0xcc, 0x62, 0xda, 0xf5, 0x63, 0xe5, 0xd1, 0xad, 0xe0, + 0x81, 0x69, 0x86, 0x7c, 0x22, 0x71, 0x09, 0x57, 0x99, 0x88, 0xbd, 0x2c, 0x95, 0x86, 0xd8, 0x0e, + 0xa2, 0xc7, 0xa1, 0x15, 0xdf, 0x57, 0xb8, 0xd5, 0x47, 0x92, 0x2e, 0x01, 0x6b, 0x40, 0x89, 0xac, + 0xde, 0x3b, 0x98, 0x63, 0xe3, 0xf5, 0x0c, 0x2f, 0x27, 0xfa, 0x91, 0x55, 0x33, 0xd6, 0x80, 0xee, + 0xc7, 0x39, 0xd0, 0xb9, 0xc7, 0x19, 0xf8, 0xdd, 0xdf, 0x8c, 0xf9, 0xdd, 0x95, 0x61, 0x23, 0x28, + 0xa9, 0x9e, 0x41, 0xf5, 0x85, 0x64, 0x5e, 0x78, 0x39, 0x0b, 0xe8, 0xe3, 0x6b, 0x0b, 0xff, 0xe4, + 0x40, 0x51, 0xf5, 0x3b, 0x03, 0x17, 0xbe, 0x15, 0x77, 0xe1, 0x2f, 0x65, 0x98, 0xc5, 0x00, 0xd7, + 0xfd, 0x51, 0xde, 0x8c, 0x3e, 0xcc, 0x3a, 0x9b, 0x84, 0xd5, 0x4d, 0x3e, 0x15, 0x59, 0xa0, 0x6c, + 0xc4, 0x9a, 0x86, 0x7e, 0x07, 0x66, 0x99, 0x7e, 0x42, 0x43, 0xeb, 0xb7, 0xc3, 0xe4, 0x26, 0x9f, + 0xf9, 0x8d, 0x8b, 0x79, 0x87, 0x13, 0xd5, 0xd5, 0x71, 0x02, 0x15, 0xf7, 0xc9, 0x91, 0x09, 0x4f, + 0x37, 0xe9, 0xcb, 0x4c, 0x22, 0xf0, 0xfa, 0x88, 0x8e, 0x53, 0x27, 0x3c, 0x7d, 0xcd, 0xb8, 0x5f, + 0x10, 0x6a, 0xc2, 0x94, 0xfd, 0x3a, 0xcf, 0xec, 0xa5, 0x2b, 0xd9, 0x9f, 0x01, 0xea, 0x7b, 0x54, + 0xbb, 0x05, 0xc7, 0x90, 0xdd, 0xc3, 0x02, 0x94, 0xac, 0xcd, 0x97, 0xa8, 0x55, 0x4e, 0x9f, 0x4e, + 0xad, 0x32, 0x3d, 0xb5, 0x2e, 0x8d, 0x94, 0x5a, 0x5f, 0x8e, 0xa7, 0xd6, 0xdf, 0x4c, 0xa6, 0xd6, + 0xa0, 0x66, 0x17, 0x4b, 0xab, 0x39, 0x9c, 0x37, 0x39, 0x66, 0xf0, 0xcc, 0x32, 0x53, 0xb1, 0xa2, + 0x3f, 0x93, 0x45, 0x32, 0xae, 0xbc, 0x1d, 0x83, 0xc4, 0x09, 0x11, 0x32, 0x2e, 0x35, 0x2d, 0xd5, + 0x5e, 0xbb, 0x4d, 0xd8, 0xc1, 0xc2, 0x94, 0x1a, 0x70, 0x18, 0x97, 0xde, 0x8e, 0x51, 0x71, 0xa2, + 0x37, 0xda, 0x82, 0x82, 0x4e, 0x51, 0xcd, 0xd3, 0xbd, 0x97, 0xb3, 0x64, 0xbf, 0x3a, 0x2e, 0xd7, + 0x7f, 0x63, 0x83, 0x63, 0x57, 0x17, 0x8a, 0xc7, 0x54, 0x17, 0xee, 0x02, 0xf2, 0x77, 0x54, 0x06, + 0x50, 0xbf, 0xa3, 0x3f, 0x95, 0x95, 0xbb, 0xb2, 0xa0, 0x52, 0xd7, 0x70, 0xc1, 0xee, 0xf5, 0xf5, + 0xc0, 0x29, 0x5c, 0xd2, 0xaa, 0x4d, 0x5e, 0x1b, 0x9a, 0x82, 0xa9, 0x24, 0x64, 0xcd, 0x99, 0xa2, + 0x44, 0x6d, 0x5e, 0x5a, 0xf5, 0x5a, 0x02, 0x15, 0xf7, 0xc9, 0x41, 0xdf, 0x83, 0x69, 0xb9, 0x85, + 0x22, 0xc1, 0xf0, 0x84, 0x82, 0xe7, 0x8e, 0x0e, 0x97, 0xa7, 0x37, 0x6d, 0x48, 0x1c, 0x97, 0xe0, + 0xfe, 0x59, 0x1e, 0xd2, 0xb3, 0xea, 0xe8, 0xd5, 0xb9, 0xf3, 0x98, 0x57, 0xe7, 0xef, 0x42, 0x91, + 0x0b, 0xc2, 0xf4, 0x0b, 0xfb, 0xdc, 0x68, 0x2f, 0xec, 0xab, 0x01, 0x00, 0x8e, 0xb0, 0x12, 0x25, + 0x8e, 0xfc, 0x89, 0x96, 0x38, 0xae, 0x00, 0xa8, 0xac, 0x6a, 0xcd, 0xef, 0x99, 0x4b, 0xcd, 0xe9, + 0xc8, 0x27, 0xdc, 0x0a, 0x29, 0xd8, 0xea, 0x85, 0xae, 0x87, 0x07, 0xa7, 0xbe, 0xc5, 0xbc, 0xd4, + 0xf7, 0x0a, 0x23, 0x59, 0x24, 0x4b, 0xf9, 0x62, 0xf4, 0x98, 0x57, 0x5b, 0xee, 0xff, 0xe6, 0x20, + 0xe6, 0x0c, 0xd1, 0x0f, 0x1d, 0x98, 0x23, 0x89, 0x8f, 0x6e, 0x83, 0x58, 0xf2, 0xd7, 0xb3, 0x7d, + 0x09, 0xdd, 0xf7, 0xcd, 0x6e, 0x74, 0x6f, 0x94, 0xec, 0xc2, 0x71, 0xbf, 0x50, 0xf4, 0x27, 0x0e, + 0x5c, 0x20, 0xfd, 0x5f, 0x55, 0x9b, 0x45, 0x7f, 0x63, 0xe4, 0xcf, 0xb2, 0x2b, 0x4f, 0x1f, 0x1d, + 0x2e, 0xa7, 0x7d, 0x6f, 0x8e, 0xd3, 0xc4, 0xa1, 0xef, 0xc2, 0x18, 0x61, 0x8d, 0xa0, 0xc6, 0x9a, + 0x5d, 0x6c, 0xf0, 0xb1, 0x7c, 0x14, 0x1d, 0xad, 0xb2, 0x06, 0xc7, 0x0a, 0xd4, 0xfd, 0x59, 0x1e, + 0x66, 0x93, 0xaf, 0xd4, 0xcd, 0xc3, 0xbe, 0xb1, 0xd4, 0x87, 0x7d, 0xd2, 0x46, 0x6a, 0x22, 0x7c, + 0x65, 0x17, 0xd9, 0x88, 0x6c, 0xc4, 0x9a, 0x16, 0xda, 0x88, 0xdc, 0x97, 0xa6, 0xee, 0x33, 0x9a, + 0x8d, 0xc8, 0x9f, 0x38, 0xc2, 0x42, 0xd7, 0xe3, 0x67, 0x8b, 0x9b, 0x3c, 0x5b, 0xe6, 0xec, 0xb9, + 0x8c, 0x5a, 0xb9, 0x6d, 0x43, 0xc9, 0x5a, 0x07, 0x63, 0x89, 0x37, 0x32, 0xeb, 0x3d, 0xda, 0x76, + 0x33, 0xfa, 0x8b, 0xfb, 0x88, 0x62, 0xe3, 0x47, 0x76, 0xaf, 0xb4, 0xf5, 0x44, 0xa5, 0x4d, 0xa5, + 0x2e, 0x0b, 0xcd, 0xdd, 0x83, 0xe9, 0xd8, 0x63, 0x53, 0x29, 0x2c, 0x78, 0x60, 0x3b, 0xfa, 0x27, + 0xe8, 0xf7, 0x43, 0x04, 0x6c, 0xa1, 0xa9, 0x0b, 0xc9, 0x77, 0x09, 0xa3, 0x4d, 0xbf, 0xc7, 0xe9, + 0xd7, 0xf5, 0x42, 0x32, 0x1c, 0xe0, 0x49, 0x5f, 0x48, 0x46, 0xc0, 0xc7, 0x5f, 0x48, 0x86, 0x7d, + 0xbf, 0xb6, 0x17, 0x92, 0xe1, 0x08, 0x07, 0x24, 0x0f, 0xff, 0x93, 0xb3, 0x66, 0x11, 0x4f, 0x20, + 0x72, 0x8f, 0x49, 0x20, 0x1e, 0xc2, 0xa4, 0xd7, 0x11, 0x94, 0xed, 0x93, 0x96, 0x29, 0xcb, 0x66, + 0xad, 0x31, 0x86, 0x53, 0xdd, 0x30, 0x38, 0x38, 0x44, 0x44, 0x2d, 0xb8, 0x18, 0x5c, 0x55, 0x30, + 0x4a, 0xa2, 0xab, 0x52, 0xf3, 0xdc, 0xe8, 0xb5, 0xa0, 0xa6, 0x7e, 0x3b, 0xad, 0xd3, 0xa3, 0x41, + 0x04, 0x9c, 0x0e, 0x8a, 0x38, 0x4c, 0x73, 0x2b, 0x73, 0x0e, 0x0e, 0xa9, 0x21, 0xaf, 0x79, 0x92, + 0xc5, 0x06, 0xeb, 0x8d, 0x92, 0x0d, 0x8a, 0xe3, 0x32, 0xdc, 0x7f, 0xcb, 0xc3, 0x4c, 0x62, 0xa7, + 0x25, 0x32, 0x84, 0xe2, 0x59, 0x66, 0x08, 0x85, 0x91, 0x32, 0x84, 0xf4, 0xe0, 0x75, 0x6c, 0xa4, + 0xe0, 0xf5, 0x4d, 0x1d, 0x40, 0x9a, 0x95, 0xdb, 0x58, 0x37, 0x4f, 0xba, 0x43, 0x6d, 0x6e, 0xda, + 0x44, 0x1c, 0xef, 0xab, 0x4e, 0xf8, 0x7a, 0xff, 0xf7, 0xcb, 0x26, 0xfa, 0x7d, 0x23, 0xeb, 0x9b, + 0xbc, 0x10, 0x40, 0x9f, 0xf0, 0x29, 0x04, 0x9c, 0x26, 0xae, 0x72, 0xf7, 0xd3, 0x2f, 0x97, 0xce, + 0x7d, 0xfe, 0xe5, 0xd2, 0xb9, 0x2f, 0xbe, 0x5c, 0x3a, 0xf7, 0x83, 0xa3, 0x25, 0xe7, 0xd3, 0xa3, + 0x25, 0xe7, 0xf3, 0xa3, 0x25, 0xe7, 0x8b, 0xa3, 0x25, 0xe7, 0xbf, 0x8e, 0x96, 0x9c, 0x1f, 0xfd, + 0x7c, 0xe9, 0xdc, 0x83, 0xe7, 0x86, 0xf9, 0xb7, 0x43, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0xee, + 0x49, 0x80, 0xf8, 0x9d, 0x48, 0x00, 0x00, } func (m *AnalysisRunArgument) Marshal() (dAtA []byte, err error) { @@ -2425,7 +2608,7 @@ func (m *ChartSubscription) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *DiscoveredArtifacts) Marshal() (dAtA []byte, err error) { +func (m *ClusterPromotionTask) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -2435,18 +2618,18 @@ func (m *DiscoveredArtifacts) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *DiscoveredArtifacts) MarshalTo(dAtA []byte) (int, error) { +func (m *ClusterPromotionTask) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *DiscoveredArtifacts) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ClusterPromotionTask) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l { - size, err := m.DiscoveredAt.MarshalToSizedBuffer(dAtA[:i]) + size, err := m.Spec.MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -2454,53 +2637,21 @@ func (m *DiscoveredArtifacts) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- - dAtA[i] = 0x22 - if len(m.Charts) > 0 { - for iNdEx := len(m.Charts) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Charts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenerated(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - } - if len(m.Images) > 0 { - for iNdEx := len(m.Images) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Images[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenerated(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - } - if len(m.Git) > 0 { - for iNdEx := len(m.Git) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Git[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenerated(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa + dAtA[i] = 0x12 + { + size, err := m.ObjectMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) } + i-- + dAtA[i] = 0xa return len(dAtA) - i, nil } -func (m *DiscoveredCommit) Marshal() (dAtA []byte, err error) { +func (m *ClusterPromotionTaskList) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -2510,24 +2661,146 @@ func (m *DiscoveredCommit) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *DiscoveredCommit) MarshalTo(dAtA []byte) (int, error) { +func (m *ClusterPromotionTaskList) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *DiscoveredCommit) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *ClusterPromotionTaskList) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if m.CreatorDate != nil { - { - size, err := m.CreatorDate.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenerated(dAtA, i, uint64(size)) + if len(m.Items) > 0 { + for iNdEx := len(m.Items) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Items[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + { + size, err := m.ListMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *DiscoveredArtifacts) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DiscoveredArtifacts) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DiscoveredArtifacts) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.DiscoveredAt.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.Charts) > 0 { + for iNdEx := len(m.Charts) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Charts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.Images) > 0 { + for iNdEx := len(m.Images) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Images[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Git) > 0 { + for iNdEx := len(m.Git) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Git[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *DiscoveredCommit) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DiscoveredCommit) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DiscoveredCommit) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CreatorDate != nil { + { + size, err := m.CreatorDate.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- dAtA[i] = 0x3a @@ -4160,6 +4433,32 @@ func (m *PromotionStep) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Vars) > 0 { + for iNdEx := len(m.Vars) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Vars[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + } + if m.Task != nil { + { + size, err := m.Task.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } if m.Retry != nil { { size, err := m.Retry.MarshalToSizedBuffer(dAtA[:i]) @@ -4235,7 +4534,7 @@ func (m *PromotionStepRetry) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *PromotionTemplate) Marshal() (dAtA []byte, err error) { +func (m *PromotionTask) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4245,12 +4544,12 @@ func (m *PromotionTemplate) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *PromotionTemplate) MarshalTo(dAtA []byte) (int, error) { +func (m *PromotionTask) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *PromotionTemplate) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *PromotionTask) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int @@ -4264,11 +4563,21 @@ func (m *PromotionTemplate) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- + dAtA[i] = 0x12 + { + size, err := m.ObjectMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- dAtA[i] = 0xa return len(dAtA) - i, nil } -func (m *PromotionTemplateSpec) Marshal() (dAtA []byte, err error) { +func (m *PromotionTaskList) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4278,20 +4587,20 @@ func (m *PromotionTemplateSpec) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *PromotionTemplateSpec) MarshalTo(dAtA []byte) (int, error) { +func (m *PromotionTaskList) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *PromotionTemplateSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *PromotionTaskList) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if len(m.Vars) > 0 { - for iNdEx := len(m.Vars) - 1; iNdEx >= 0; iNdEx-- { + if len(m.Items) > 0 { + for iNdEx := len(m.Items) - 1; iNdEx >= 0; iNdEx-- { { - size, err := m.Vars[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + size, err := m.Items[iNdEx].MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -4302,24 +4611,20 @@ func (m *PromotionTemplateSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x12 } } - if len(m.Steps) > 0 { - for iNdEx := len(m.Steps) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Steps[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenerated(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa + { + size, err := m.ListMeta.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) } + i-- + dAtA[i] = 0xa return len(dAtA) - i, nil } -func (m *PromotionVariable) Marshal() (dAtA []byte, err error) { +func (m *PromotionTaskReference) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4329,19 +4634,19 @@ func (m *PromotionVariable) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *PromotionVariable) MarshalTo(dAtA []byte) (int, error) { +func (m *PromotionTaskReference) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *PromotionVariable) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *PromotionTaskReference) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - i -= len(m.Value) - copy(dAtA[i:], m.Value) - i = encodeVarintGenerated(dAtA, i, uint64(len(m.Value))) + i -= len(m.Kind) + copy(dAtA[i:], m.Kind) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Kind))) i-- dAtA[i] = 0x12 i -= len(m.Name) @@ -4352,7 +4657,7 @@ func (m *PromotionVariable) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *RepoSubscription) Marshal() (dAtA []byte, err error) { +func (m *PromotionTaskSpec) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -4362,48 +4667,216 @@ func (m *RepoSubscription) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *RepoSubscription) MarshalTo(dAtA []byte) (int, error) { +func (m *PromotionTaskSpec) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *RepoSubscription) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *PromotionTaskSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if m.Chart != nil { - { - size, err := m.Chart.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if len(m.Steps) > 0 { + for iNdEx := len(m.Steps) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Steps[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintGenerated(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x12 } - i-- - dAtA[i] = 0x1a } - if m.Image != nil { - { - size, err := m.Image.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if len(m.Vars) > 0 { + for iNdEx := len(m.Vars) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Vars[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintGenerated(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa } - i-- - dAtA[i] = 0x12 } - if m.Git != nil { - { - size, err := m.Git.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenerated(dAtA, i, uint64(size)) + return len(dAtA) - i, nil +} + +func (m *PromotionTemplate) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PromotionTemplate) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PromotionTemplate) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Spec.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *PromotionTemplateSpec) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PromotionTemplateSpec) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PromotionTemplateSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Vars) > 0 { + for iNdEx := len(m.Vars) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Vars[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Steps) > 0 { + for iNdEx := len(m.Steps) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Steps[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *PromotionVariable) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PromotionVariable) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PromotionVariable) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + i -= len(m.Value) + copy(dAtA[i:], m.Value) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Value))) + i-- + dAtA[i] = 0x12 + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *RepoSubscription) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RepoSubscription) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RepoSubscription) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Chart != nil { + { + size, err := m.Chart.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if m.Image != nil { + { + size, err := m.Image.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Git != nil { + { + size, err := m.Git.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenerated(dAtA, i, uint64(size)) } i-- dAtA[i] = 0xa @@ -5337,6 +5810,36 @@ func (m *ChartSubscription) Size() (n int) { return n } +func (m *ClusterPromotionTask) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Spec.Size() + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *ClusterPromotionTaskList) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ListMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Items) > 0 { + for _, e := range m.Items { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + func (m *DiscoveredArtifacts) Size() (n int) { if m == nil { return 0 @@ -5996,6 +6499,16 @@ func (m *PromotionStep) Size() (n int) { l = m.Retry.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.Task != nil { + l = m.Task.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if len(m.Vars) > 0 { + for _, e := range m.Vars { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } return n } @@ -6013,31 +6526,29 @@ func (m *PromotionStepRetry) Size() (n int) { return n } -func (m *PromotionTemplate) Size() (n int) { +func (m *PromotionTask) Size() (n int) { if m == nil { return 0 } var l int _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) l = m.Spec.Size() n += 1 + l + sovGenerated(uint64(l)) return n } -func (m *PromotionTemplateSpec) Size() (n int) { +func (m *PromotionTaskList) Size() (n int) { if m == nil { return 0 } var l int _ = l - if len(m.Steps) > 0 { - for _, e := range m.Steps { - l = e.Size() - n += 1 + l + sovGenerated(uint64(l)) - } - } - if len(m.Vars) > 0 { - for _, e := range m.Vars { + l = m.ListMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + if len(m.Items) > 0 { + for _, e := range m.Items { l = e.Size() n += 1 + l + sovGenerated(uint64(l)) } @@ -6045,7 +6556,7 @@ func (m *PromotionTemplateSpec) Size() (n int) { return n } -func (m *PromotionVariable) Size() (n int) { +func (m *PromotionTaskReference) Size() (n int) { if m == nil { return 0 } @@ -6053,48 +6564,114 @@ func (m *PromotionVariable) Size() (n int) { _ = l l = len(m.Name) n += 1 + l + sovGenerated(uint64(l)) - l = len(m.Value) + l = len(m.Kind) n += 1 + l + sovGenerated(uint64(l)) return n } -func (m *RepoSubscription) Size() (n int) { +func (m *PromotionTaskSpec) Size() (n int) { if m == nil { return 0 } var l int _ = l - if m.Git != nil { - l = m.Git.Size() - n += 1 + l + sovGenerated(uint64(l)) - } - if m.Image != nil { - l = m.Image.Size() - n += 1 + l + sovGenerated(uint64(l)) + if len(m.Vars) > 0 { + for _, e := range m.Vars { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } } - if m.Chart != nil { - l = m.Chart.Size() - n += 1 + l + sovGenerated(uint64(l)) + if len(m.Steps) > 0 { + for _, e := range m.Steps { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } } return n } -func (m *Stage) Size() (n int) { +func (m *PromotionTemplate) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = m.ObjectMeta.Size() - n += 1 + l + sovGenerated(uint64(l)) l = m.Spec.Size() n += 1 + l + sovGenerated(uint64(l)) - l = m.Status.Size() - n += 1 + l + sovGenerated(uint64(l)) return n } -func (m *StageList) Size() (n int) { +func (m *PromotionTemplateSpec) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Steps) > 0 { + for _, e := range m.Steps { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + if len(m.Vars) > 0 { + for _, e := range m.Vars { + l = e.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + } + return n +} + +func (m *PromotionVariable) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + n += 1 + l + sovGenerated(uint64(l)) + l = len(m.Value) + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *RepoSubscription) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Git != nil { + l = m.Git.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.Image != nil { + l = m.Image.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + if m.Chart != nil { + l = m.Chart.Size() + n += 1 + l + sovGenerated(uint64(l)) + } + return n +} + +func (m *Stage) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.ObjectMeta.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Spec.Size() + n += 1 + l + sovGenerated(uint64(l)) + l = m.Status.Size() + n += 1 + l + sovGenerated(uint64(l)) + return n +} + +func (m *StageList) Size() (n int) { if m == nil { return 0 } @@ -6500,6 +7077,33 @@ func (this *ChartSubscription) String() string { }, "") return s } +func (this *ClusterPromotionTask) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&ClusterPromotionTask{`, + `ObjectMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ObjectMeta), "ObjectMeta", "v1.ObjectMeta", 1), `&`, ``, 1) + `,`, + `Spec:` + strings.Replace(strings.Replace(this.Spec.String(), "PromotionTaskSpec", "PromotionTaskSpec", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *ClusterPromotionTaskList) String() string { + if this == nil { + return "nil" + } + repeatedStringForItems := "[]ClusterPromotionTask{" + for _, f := range this.Items { + repeatedStringForItems += strings.Replace(strings.Replace(f.String(), "ClusterPromotionTask", "ClusterPromotionTask", 1), `&`, ``, 1) + "," + } + repeatedStringForItems += "}" + s := strings.Join([]string{`&ClusterPromotionTaskList{`, + `ListMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ListMeta), "ListMeta", "v1.ListMeta", 1), `&`, ``, 1) + `,`, + `Items:` + repeatedStringForItems + `,`, + `}`, + }, "") + return s +} func (this *DiscoveredArtifacts) String() string { if this == nil { return "nil" @@ -7006,11 +7610,18 @@ func (this *PromotionStep) String() string { if this == nil { return "nil" } + repeatedStringForVars := "[]PromotionVariable{" + for _, f := range this.Vars { + repeatedStringForVars += strings.Replace(strings.Replace(f.String(), "PromotionVariable", "PromotionVariable", 1), `&`, ``, 1) + "," + } + repeatedStringForVars += "}" s := strings.Join([]string{`&PromotionStep{`, `Uses:` + fmt.Sprintf("%v", this.Uses) + `,`, `As:` + fmt.Sprintf("%v", this.As) + `,`, `Config:` + strings.Replace(fmt.Sprintf("%v", this.Config), "JSON", "v11.JSON", 1) + `,`, `Retry:` + strings.Replace(this.Retry.String(), "PromotionStepRetry", "PromotionStepRetry", 1) + `,`, + `Task:` + strings.Replace(this.Task.String(), "PromotionTaskReference", "PromotionTaskReference", 1) + `,`, + `Vars:` + repeatedStringForVars + `,`, `}`, }, "") return s @@ -7026,6 +7637,65 @@ func (this *PromotionStepRetry) String() string { }, "") return s } +func (this *PromotionTask) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PromotionTask{`, + `ObjectMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ObjectMeta), "ObjectMeta", "v1.ObjectMeta", 1), `&`, ``, 1) + `,`, + `Spec:` + strings.Replace(strings.Replace(this.Spec.String(), "PromotionTaskSpec", "PromotionTaskSpec", 1), `&`, ``, 1) + `,`, + `}`, + }, "") + return s +} +func (this *PromotionTaskList) String() string { + if this == nil { + return "nil" + } + repeatedStringForItems := "[]PromotionTask{" + for _, f := range this.Items { + repeatedStringForItems += strings.Replace(strings.Replace(f.String(), "PromotionTask", "PromotionTask", 1), `&`, ``, 1) + "," + } + repeatedStringForItems += "}" + s := strings.Join([]string{`&PromotionTaskList{`, + `ListMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ListMeta), "ListMeta", "v1.ListMeta", 1), `&`, ``, 1) + `,`, + `Items:` + repeatedStringForItems + `,`, + `}`, + }, "") + return s +} +func (this *PromotionTaskReference) String() string { + if this == nil { + return "nil" + } + s := strings.Join([]string{`&PromotionTaskReference{`, + `Name:` + fmt.Sprintf("%v", this.Name) + `,`, + `Kind:` + fmt.Sprintf("%v", this.Kind) + `,`, + `}`, + }, "") + return s +} +func (this *PromotionTaskSpec) String() string { + if this == nil { + return "nil" + } + repeatedStringForVars := "[]PromotionVariable{" + for _, f := range this.Vars { + repeatedStringForVars += strings.Replace(strings.Replace(f.String(), "PromotionVariable", "PromotionVariable", 1), `&`, ``, 1) + "," + } + repeatedStringForVars += "}" + repeatedStringForSteps := "[]PromotionStep{" + for _, f := range this.Steps { + repeatedStringForSteps += strings.Replace(strings.Replace(f.String(), "PromotionStep", "PromotionStep", 1), `&`, ``, 1) + "," + } + repeatedStringForSteps += "}" + s := strings.Join([]string{`&PromotionTaskSpec{`, + `Vars:` + repeatedStringForVars + `,`, + `Steps:` + repeatedStringForSteps + `,`, + `}`, + }, "") + return s +} func (this *PromotionTemplate) String() string { if this == nil { return "nil" @@ -8952,7 +9622,7 @@ func (m *ChartSubscription) Unmarshal(dAtA []byte) error { } return nil } -func (m *DiscoveredArtifacts) Unmarshal(dAtA []byte) error { +func (m *ClusterPromotionTask) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -8975,15 +9645,15 @@ func (m *DiscoveredArtifacts) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DiscoveredArtifacts: wiretype end group for non-group") + return fmt.Errorf("proto: ClusterPromotionTask: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DiscoveredArtifacts: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: ClusterPromotionTask: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Git", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -9010,14 +9680,13 @@ func (m *DiscoveredArtifacts) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Git = append(m.Git, GitDiscoveryResult{}) - if err := m.Git[len(m.Git)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Images", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -9044,14 +9713,63 @@ func (m *DiscoveredArtifacts) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Images = append(m.Images, ImageDiscoveryResult{}) - if err := m.Images[len(m.Images)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 3: + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ClusterPromotionTaskList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ClusterPromotionTaskList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ClusterPromotionTaskList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Charts", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -9078,14 +9796,13 @@ func (m *DiscoveredArtifacts) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Charts = append(m.Charts, ChartDiscoveryResult{}) - if err := m.Charts[len(m.Charts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex - case 4: + case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DiscoveredAt", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -9112,7 +9829,8 @@ func (m *DiscoveredArtifacts) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.DiscoveredAt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Items = append(m.Items, ClusterPromotionTask{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -9137,7 +9855,7 @@ func (m *DiscoveredArtifacts) Unmarshal(dAtA []byte) error { } return nil } -func (m *DiscoveredCommit) Unmarshal(dAtA []byte) error { +func (m *DiscoveredArtifacts) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -9160,17 +9878,17 @@ func (m *DiscoveredCommit) Unmarshal(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: DiscoveredCommit: wiretype end group for non-group") + return fmt.Errorf("proto: DiscoveredArtifacts: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: DiscoveredCommit: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: DiscoveredArtifacts: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Git", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -9180,29 +9898,31 @@ func (m *DiscoveredCommit) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthGenerated } if postIndex > l { return io.ErrUnexpectedEOF } - m.ID = string(dAtA[iNdEx:postIndex]) + m.Git = append(m.Git, GitDiscoveryResult{}) + if err := m.Git[len(m.Git)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Branch", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Images", wireType) } - var stringLen uint64 + var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenerated @@ -9212,27 +9932,210 @@ func (m *DiscoveredCommit) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - stringLen |= uint64(b&0x7F) << shift + msglen |= int(b&0x7F) << shift if b < 0x80 { break } } - intStringLen := int(stringLen) - if intStringLen < 0 { + if msglen < 0 { return ErrInvalidLengthGenerated } - postIndex := iNdEx + intStringLen + postIndex := iNdEx + msglen if postIndex < 0 { return ErrInvalidLengthGenerated } if postIndex > l { return io.ErrUnexpectedEOF } - m.Branch = string(dAtA[iNdEx:postIndex]) + m.Images = append(m.Images, ImageDiscoveryResult{}) + if err := m.Images[len(m.Images)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } iNdEx = postIndex case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Tag", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Charts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Charts = append(m.Charts, ChartDiscoveryResult{}) + if err := m.Charts[len(m.Charts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DiscoveredAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.DiscoveredAt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DiscoveredCommit) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DiscoveredCommit: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DiscoveredCommit: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Branch", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Branch = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tag", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -14600,6 +15503,76 @@ func (m *PromotionStep) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Task", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Task == nil { + m.Task = &PromotionTaskReference{} + } + if err := m.Task.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vars", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Vars = append(m.Vars, PromotionVariable{}) + if err := m.Vars[len(m.Vars)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) @@ -14726,6 +15699,471 @@ func (m *PromotionStepRetry) Unmarshal(dAtA []byte) error { } return nil } +func (m *PromotionTask) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PromotionTask: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PromotionTask: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PromotionTaskList) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PromotionTaskList: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PromotionTaskList: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Items = append(m.Items, PromotionTask{}) + if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PromotionTaskReference) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PromotionTaskReference: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PromotionTaskReference: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Kind", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Kind = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PromotionTaskSpec) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PromotionTaskSpec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PromotionTaskSpec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vars", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Vars = append(m.Vars, PromotionVariable{}) + if err := m.Vars[len(m.Vars)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Steps", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Steps = append(m.Steps, PromotionStep{}) + if err := m.Steps[len(m.Steps)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenerated(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenerated + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *PromotionTemplate) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/api/v1alpha1/generated.proto b/api/v1alpha1/generated.proto index 7e79145a6..46dec8169 100644 --- a/api/v1alpha1/generated.proto +++ b/api/v1alpha1/generated.proto @@ -181,6 +181,23 @@ message ChartSubscription { optional int32 discoveryLimit = 4; } +message ClusterPromotionTask { + optional .k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // Spec describes the desired transition of a specific Stage into a specific + // Freight. + // + // +kubebuilder:validation:Required + optional PromotionTaskSpec spec = 2; +} + +// ClusterPromotionTaskList contains a list of PromotionTasks. +message ClusterPromotionTaskList { + optional .k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; + + repeated ClusterPromotionTask items = 2; +} + // DiscoveredArtifacts holds the artifacts discovered by the Warehouse for its // subscriptions. message DiscoveredArtifacts { @@ -841,14 +858,19 @@ message PromotionSpec { // applies. The Stage referenced by this field MUST be in the same // namespace as the Promotion. // + // +kubebuilder:validation:Required // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ optional string stage = 1; // Freight specifies the piece of Freight to be promoted into the Stage // referenced by the Stage field. // + // +kubebuilder:validation:Required // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ optional string freight = 2; // Vars is a list of variables that can be referenced by expressions in @@ -858,6 +880,10 @@ message PromotionSpec { // Steps specifies the directives to be executed as part of this Promotion. // The order in which the directives are executed is the order in which they // are listed in this field. + // + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:items:XValidation:message="Promotion step must have uses set and must not reference a task",rule="has(self.uses) && !has(self.task)" repeated PromotionStep steps = 3; } @@ -912,15 +938,25 @@ message PromotionStatus { message PromotionStep { // Uses identifies a runner that can execute this step. // + // +kubebuilder:validation:Optional // +kubebuilder:validation:MinLength=1 optional string uses = 1; + // Task is a reference to a PromotionTask that should be inflated into a + // Promotion when it is built from a PromotionTemplate. + optional PromotionTaskReference task = 5; + // As is the alias this step can be referred to as. optional string as = 2; // Retry is the retry policy for this step. optional PromotionStepRetry retry = 4; + // Vars is a list of variables that can be referenced by expressions in + // the step's Config. The values override the values specified in the + // PromotionSpec. + repeated PromotionVariable vars = 6; + // Config is opaque configuration for the PromotionStep that is understood // only by each PromotionStep's implementation. It is legal to utilize // expressions in defining values at any level of this block. @@ -968,6 +1004,57 @@ message PromotionStepRetry { optional uint32 errorThreshold = 2; } +message PromotionTask { + optional .k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + + // Spec describes the composition of a PromotionTask, including the + // variables available to the task and the steps. + // + // +kubebuilder:validation:Required + optional PromotionTaskSpec spec = 2; +} + +// PromotionTaskList contains a list of PromotionTasks. +message PromotionTaskList { + optional .k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; + + repeated PromotionTask items = 2; +} + +// PromotionTaskReference describes a reference to a PromotionTask. +message PromotionTaskReference { + // Name is the name of the (Cluster)PromotionTask. + // + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + optional string name = 1; + + // Kind is the type of the PromotionTask. Can be either PromotionTask or + // ClusterPromotionTask, default is PromotionTask. + // + // +kubebuilder:validation:Optional + // +kubebuilder:validation:Enum=PromotionTask;ClusterPromotionTask + optional string kind = 2; +} + +message PromotionTaskSpec { + // Vars specifies the variables available to the PromotionTask. The + // values of these variables are the default values that can be + // overridden by the step referencing the task. + repeated PromotionVariable vars = 1; + + // Steps specifies the directives to be executed as part of this + // PromotionTask. The steps as defined here are inflated into a + // Promotion when it is built from a PromotionTemplate. + // + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:items:XValidation:message="PromotionTask step must have uses set and must not reference another task",rule="has(self.uses) && !has(self.task)" + repeated PromotionStep steps = 2; +} + // PromotionTemplate defines a template for a Promotion that can be used to // incorporate Freight into a Stage. message PromotionTemplate { @@ -987,6 +1074,7 @@ message PromotionTemplateSpec { // are listed in this field. // // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:items:XValidation:message="PromotionTemplate step must have exactly one of uses or task set",rule="(has(self.uses) ? !has(self.task) : has(self.task))" repeated PromotionStep steps = 1; } diff --git a/api/v1alpha1/groupversion_info.go b/api/v1alpha1/groupversion_info.go index 55b320045..8de4266ca 100644 --- a/api/v1alpha1/groupversion_info.go +++ b/api/v1alpha1/groupversion_info.go @@ -27,6 +27,8 @@ var ( // addKnownTypes adds the set of types defined in this package to the supplied scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(GroupVersion, + &ClusterPromotionTask{}, + &ClusterPromotionTaskList{}, &Freight{}, &FreightList{}, &Stage{}, @@ -35,6 +37,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &ProjectList{}, &Promotion{}, &PromotionList{}, + &PromotionTask{}, + &PromotionTaskList{}, &Warehouse{}, &WarehouseList{}, ) diff --git a/api/v1alpha1/promotion_task_types.go b/api/v1alpha1/promotion_task_types.go new file mode 100644 index 000000000..5c0fe35e3 --- /dev/null +++ b/api/v1alpha1/promotion_task_types.go @@ -0,0 +1,44 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +kubebuilder:resource:shortName={promotask,promotasks} +// +kubebuilder:object:root=true +// +kubebuilder:printcolumn:name=Age,type=date,JSONPath=`.metadata.creationTimestamp` + +type PromotionTask struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // Spec describes the composition of a PromotionTask, including the + // variables available to the task and the steps. + // + // +kubebuilder:validation:Required + Spec PromotionTaskSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"` +} + +type PromotionTaskSpec struct { + // Vars specifies the variables available to the PromotionTask. The + // values of these variables are the default values that can be + // overridden by the step referencing the task. + Vars []PromotionVariable `json:"vars,omitempty" protobuf:"bytes,1,rep,name=vars"` + // Steps specifies the directives to be executed as part of this + // PromotionTask. The steps as defined here are inflated into a + // Promotion when it is built from a PromotionTemplate. + // + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:items:XValidation:message="PromotionTask step must have uses set and must not reference another task",rule="has(self.uses) && !has(self.task)" + Steps []PromotionStep `json:"steps" protobuf:"bytes,2,rep,name=steps"` +} + +// +kubebuilder:object:root=true + +// PromotionTaskList contains a list of PromotionTasks. +type PromotionTaskList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + Items []PromotionTask `json:"items" protobuf:"bytes,2,rep,name=items"` +} diff --git a/api/v1alpha1/promotion_types.go b/api/v1alpha1/promotion_types.go index da18f2dbe..4e5acdc86 100644 --- a/api/v1alpha1/promotion_types.go +++ b/api/v1alpha1/promotion_types.go @@ -1,6 +1,7 @@ package v1alpha1 import ( + "fmt" "time" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -80,13 +81,18 @@ type PromotionSpec struct { // applies. The Stage referenced by this field MUST be in the same // namespace as the Promotion. // + // +kubebuilder:validation:Required // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 // +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ Stage string `json:"stage" protobuf:"bytes,1,opt,name=stage"` // Freight specifies the piece of Freight to be promoted into the Stage // referenced by the Stage field. // + // +kubebuilder:validation:Required // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ Freight string `json:"freight" protobuf:"bytes,2,opt,name=freight"` // Vars is a list of variables that can be referenced by expressions in // promotion steps. @@ -94,7 +100,11 @@ type PromotionSpec struct { // Steps specifies the directives to be executed as part of this Promotion. // The order in which the directives are executed is the order in which they // are listed in this field. - Steps []PromotionStep `json:"steps,omitempty" protobuf:"bytes,3,rep,name=steps"` + // + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:items:XValidation:message="Promotion step must have uses set and must not reference a task",rule="has(self.uses) && !has(self.task)" + Steps []PromotionStep `json:"steps" protobuf:"bytes,3,rep,name=steps"` } // PromotionVariable describes a single variable that may be referenced by @@ -108,7 +118,25 @@ type PromotionVariable struct { // Value is the value of the variable. It is allowed to utilize expressions // in the value. // See https://docs.kargo.io/references/expression-language for details. - Value string `json:"value" protobuf:"bytes,2,opt,name=value"` + Value string `json:"value,omitempty" protobuf:"bytes,2,opt,name=value"` +} + +// PromotionTaskReference describes a reference to a PromotionTask. +type PromotionTaskReference struct { + // Name is the name of the (Cluster)PromotionTask. + // + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + Name string `json:"name" protobuf:"bytes,1,opt,name=name"` + + // Kind is the type of the PromotionTask. Can be either PromotionTask or + // ClusterPromotionTask, default is PromotionTask. + // + // +kubebuilder:validation:Optional + // +kubebuilder:validation:Enum=PromotionTask;ClusterPromotionTask + Kind string `json:"kind,omitempty" protobuf:"bytes,2,opt,name=kind"` } // PromotionStepRetry describes the retry policy for a PromotionStep. @@ -171,12 +199,20 @@ func (r *PromotionStepRetry) GetErrorThreshold(fallback uint32) uint32 { type PromotionStep struct { // Uses identifies a runner that can execute this step. // + // +kubebuilder:validation:Optional // +kubebuilder:validation:MinLength=1 - Uses string `json:"uses" protobuf:"bytes,1,opt,name=uses"` + Uses string `json:"uses,omitempty" protobuf:"bytes,1,opt,name=uses"` + // Task is a reference to a PromotionTask that should be inflated into a + // Promotion when it is built from a PromotionTemplate. + Task *PromotionTaskReference `json:"task,omitempty" protobuf:"bytes,5,opt,name=task"` // As is the alias this step can be referred to as. As string `json:"as,omitempty" protobuf:"bytes,2,opt,name=as"` // Retry is the retry policy for this step. Retry *PromotionStepRetry `json:"retry,omitempty" protobuf:"bytes,4,opt,name=retry"` + // Vars is a list of variables that can be referenced by expressions in + // the step's Config. The values override the values specified in the + // PromotionSpec. + Vars []PromotionVariable `json:"vars,omitempty" protobuf:"bytes,6,rep,name=vars"` // Config is opaque configuration for the PromotionStep that is understood // only by each PromotionStep's implementation. It is legal to utilize // expressions in defining values at any level of this block. @@ -184,6 +220,21 @@ type PromotionStep struct { Config *apiextensionsv1.JSON `json:"config,omitempty" protobuf:"bytes,3,opt,name=config"` } +// GetAlias returns the As field, or a default value in the form of "step-" +// or "task-" if the As field is empty. The index i is provided as an +// argument to this method and should be the index of the PromotionStep in the +// list it belongs to. +func (s *PromotionStep) GetAlias(i int) string { + switch { + case s.As != "": + return s.As + case s.Task != nil: + return fmt.Sprintf("task-%d", i) + default: + return fmt.Sprintf("step-%d", i) + } +} + // PromotionStatus describes the current state of the transition represented by // a Promotion. type PromotionStatus struct { diff --git a/api/v1alpha1/stage_types.go b/api/v1alpha1/stage_types.go index 3d61284d6..e7ae1f88e 100644 --- a/api/v1alpha1/stage_types.go +++ b/api/v1alpha1/stage_types.go @@ -272,6 +272,7 @@ type PromotionTemplateSpec struct { // are listed in this field. // // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:items:XValidation:message="PromotionTemplate step must have exactly one of uses or task set",rule="(has(self.uses) ? !has(self.task) : has(self.task))" Steps []PromotionStep `json:"steps,omitempty" protobuf:"bytes,1,rep,name=steps"` } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 517d1627b..fa365cdc5 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -205,6 +205,64 @@ func (in *ChartSubscription) DeepCopy() *ChartSubscription { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterPromotionTask) DeepCopyInto(out *ClusterPromotionTask) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPromotionTask. +func (in *ClusterPromotionTask) DeepCopy() *ClusterPromotionTask { + if in == nil { + return nil + } + out := new(ClusterPromotionTask) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterPromotionTask) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterPromotionTaskList) DeepCopyInto(out *ClusterPromotionTaskList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterPromotionTask, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterPromotionTaskList. +func (in *ClusterPromotionTaskList) DeepCopy() *ClusterPromotionTaskList { + if in == nil { + return nil + } + out := new(ClusterPromotionTaskList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterPromotionTaskList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiscoveredArtifacts) DeepCopyInto(out *DiscoveredArtifacts) { *out = *in @@ -980,11 +1038,21 @@ func (in *PromotionStatus) DeepCopy() *PromotionStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PromotionStep) DeepCopyInto(out *PromotionStep) { *out = *in + if in.Task != nil { + in, out := &in.Task, &out.Task + *out = new(PromotionTaskReference) + **out = **in + } if in.Retry != nil { in, out := &in.Retry, &out.Retry *out = new(PromotionStepRetry) (*in).DeepCopyInto(*out) } + if in.Vars != nil { + in, out := &in.Vars, &out.Vars + *out = make([]PromotionVariable, len(*in)) + copy(*out, *in) + } if in.Config != nil { in, out := &in.Config, &out.Config *out = new(apiextensionsv1.JSON) @@ -1022,6 +1090,106 @@ func (in *PromotionStepRetry) DeepCopy() *PromotionStepRetry { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PromotionTask) DeepCopyInto(out *PromotionTask) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PromotionTask. +func (in *PromotionTask) DeepCopy() *PromotionTask { + if in == nil { + return nil + } + out := new(PromotionTask) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PromotionTask) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PromotionTaskList) DeepCopyInto(out *PromotionTaskList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]PromotionTask, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PromotionTaskList. +func (in *PromotionTaskList) DeepCopy() *PromotionTaskList { + if in == nil { + return nil + } + out := new(PromotionTaskList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PromotionTaskList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PromotionTaskReference) DeepCopyInto(out *PromotionTaskReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PromotionTaskReference. +func (in *PromotionTaskReference) DeepCopy() *PromotionTaskReference { + if in == nil { + return nil + } + out := new(PromotionTaskReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PromotionTaskSpec) DeepCopyInto(out *PromotionTaskSpec) { + *out = *in + if in.Vars != nil { + in, out := &in.Vars, &out.Vars + *out = make([]PromotionVariable, len(*in)) + copy(*out, *in) + } + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = make([]PromotionStep, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PromotionTaskSpec. +func (in *PromotionTaskSpec) DeepCopy() *PromotionTaskSpec { + if in == nil { + return nil + } + out := new(PromotionTaskSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PromotionTemplate) DeepCopyInto(out *PromotionTemplate) { *out = *in diff --git a/charts/kargo/resources/crds/kargo.akuity.io_clusterpromotiontasks.yaml b/charts/kargo/resources/crds/kargo.akuity.io_clusterpromotiontasks.yaml new file mode 100644 index 000000000..62e603a90 --- /dev/null +++ b/charts/kargo/resources/crds/kargo.akuity.io_clusterpromotiontasks.yaml @@ -0,0 +1,205 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: clusterpromotiontasks.kargo.akuity.io +spec: + group: kargo.akuity.io + names: + kind: ClusterPromotionTask + listKind: ClusterPromotionTaskList + plural: clusterpromotiontasks + shortNames: + - clusterpromotask + - clusterpromotasks + singular: clusterpromotiontask + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + Spec describes the desired transition of a specific Stage into a specific + Freight. + properties: + steps: + description: |- + Steps specifies the directives to be executed as part of this + PromotionTask. The steps as defined here are inflated into a + Promotion when it is built from a PromotionTemplate. + items: + description: PromotionStep describes a directive to be executed + as part of a Promotion. + properties: + as: + description: As is the alias this step can be referred to as. + type: string + config: + description: |- + Config is opaque configuration for the PromotionStep that is understood + only by each PromotionStep's implementation. It is legal to utilize + expressions in defining values at any level of this block. + See https://docs.kargo.io/references/expression-language for details. + x-kubernetes-preserve-unknown-fields: true + retry: + description: Retry is the retry policy for this step. + properties: + errorThreshold: + description: |- + ErrorThreshold is the number of consecutive times the step must fail (for + any reason) before retries are abandoned and the entire Promotion is marked + as failed. + + If this field is set to 0, the effective default will be a step-specific + one. If no step-specific default exists (i.e. is also 0), the effective + default will be the system-wide default of 1. + + A value of 1 will cause the Promotion to be marked as failed after just + a single failure; i.e. no retries will be attempted. + + There is no option to specify an infinite number of retries using a value + such as -1. + + In a future release, Kargo is likely to become capable of distinguishing + between recoverable and non-recoverable step failures. At that time, it is + planned that unrecoverable failures will not be subject to this threshold + and will immediately cause the Promotion to be marked as failed without + further condition. + format: int32 + type: integer + timeout: + description: |- + Timeout is the soft maximum interval in which a step that returns a Running + status (which typically indicates it's waiting for something to happen) + may be retried. + + The maximum is a soft one because the check for whether the interval has + elapsed occurs AFTER the step has run. This effectively means a step may + run ONCE beyond the close of the interval. + + If this field is set to nil, the effective default will be a step-specific + one. If no step-specific default exists (i.e. is also nil), the effective + default will be the system-wide default of 0. + + A value of 0 will cause the step to be retried indefinitely unless the + ErrorThreshold is reached. + type: string + type: object + task: + description: |- + Task is a reference to a PromotionTask that should be inflated into a + Promotion when it is built from a PromotionTemplate. + properties: + kind: + description: |- + Kind is the type of the PromotionTask. Can be either PromotionTask or + ClusterPromotionTask, default is PromotionTask. + enum: + - PromotionTask + - ClusterPromotionTask + type: string + name: + description: Name is the name of the (Cluster)PromotionTask. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + uses: + description: Uses identifies a runner that can execute this + step. + minLength: 1 + type: string + vars: + description: |- + Vars is a list of variables that can be referenced by expressions in + the step's Config. The values override the values specified in the + PromotionSpec. + items: + description: |- + PromotionVariable describes a single variable that may be referenced by + expressions in promotion steps. + properties: + name: + description: Name is the name of the variable. + minLength: 1 + pattern: ^[a-zA-Z_]\w*$ + type: string + value: + description: |- + Value is the value of the variable. It is allowed to utilize expressions + in the value. + See https://docs.kargo.io/references/expression-language for details. + type: string + required: + - name + type: object + type: array + type: object + x-kubernetes-validations: + - message: PromotionTask step must have uses set and must not reference + another task + rule: has(self.uses) && !has(self.task) + minItems: 1 + type: array + vars: + description: |- + Vars specifies the variables available to the PromotionTask. The + values of these variables are the default values that can be + overridden by the step referencing the task. + items: + description: |- + PromotionVariable describes a single variable that may be referenced by + expressions in promotion steps. + properties: + name: + description: Name is the name of the variable. + minLength: 1 + pattern: ^[a-zA-Z_]\w*$ + type: string + value: + description: |- + Value is the value of the variable. It is allowed to utilize expressions + in the value. + See https://docs.kargo.io/references/expression-language for details. + type: string + required: + - name + type: object + type: array + required: + - steps + type: object + required: + - spec + type: object + served: true + storage: true + subresources: {} diff --git a/charts/kargo/resources/crds/kargo.akuity.io_promotions.yaml b/charts/kargo/resources/crds/kargo.akuity.io_promotions.yaml index 8c8c53216..4b7f8198d 100644 --- a/charts/kargo/resources/crds/kargo.akuity.io_promotions.yaml +++ b/charts/kargo/resources/crds/kargo.akuity.io_promotions.yaml @@ -66,13 +66,16 @@ spec: description: |- Freight specifies the piece of Freight to be promoted into the Stage referenced by the Stage field. + maxLength: 253 minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string stage: description: |- Stage specifies the name of the Stage to which this Promotion applies. The Stage referenced by this field MUST be in the same namespace as the Promotion. + maxLength: 253 minLength: 1 pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ type: string @@ -139,14 +142,64 @@ spec: ErrorThreshold is reached. type: string type: object + task: + description: |- + Task is a reference to a PromotionTask that should be inflated into a + Promotion when it is built from a PromotionTemplate. + properties: + kind: + description: |- + Kind is the type of the PromotionTask. Can be either PromotionTask or + ClusterPromotionTask, default is PromotionTask. + enum: + - PromotionTask + - ClusterPromotionTask + type: string + name: + description: Name is the name of the (Cluster)PromotionTask. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object uses: description: Uses identifies a runner that can execute this step. minLength: 1 type: string - required: - - uses + vars: + description: |- + Vars is a list of variables that can be referenced by expressions in + the step's Config. The values override the values specified in the + PromotionSpec. + items: + description: |- + PromotionVariable describes a single variable that may be referenced by + expressions in promotion steps. + properties: + name: + description: Name is the name of the variable. + minLength: 1 + pattern: ^[a-zA-Z_]\w*$ + type: string + value: + description: |- + Value is the value of the variable. It is allowed to utilize expressions + in the value. + See https://docs.kargo.io/references/expression-language for details. + type: string + required: + - name + type: object + type: array type: object + x-kubernetes-validations: + - message: Promotion step must have uses set and must not reference + a task + rule: has(self.uses) && !has(self.task) + minItems: 1 type: array vars: description: |- @@ -170,12 +223,12 @@ spec: type: string required: - name - - value type: object type: array required: - freight - stage + - steps type: object status: description: |- diff --git a/charts/kargo/resources/crds/kargo.akuity.io_promotiontasks.yaml b/charts/kargo/resources/crds/kargo.akuity.io_promotiontasks.yaml new file mode 100644 index 000000000..0deebb508 --- /dev/null +++ b/charts/kargo/resources/crds/kargo.akuity.io_promotiontasks.yaml @@ -0,0 +1,205 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: promotiontasks.kargo.akuity.io +spec: + group: kargo.akuity.io + names: + kind: PromotionTask + listKind: PromotionTaskList + plural: promotiontasks + shortNames: + - promotask + - promotasks + singular: promotiontask + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + Spec describes the composition of a PromotionTask, including the + variables available to the task and the steps. + properties: + steps: + description: |- + Steps specifies the directives to be executed as part of this + PromotionTask. The steps as defined here are inflated into a + Promotion when it is built from a PromotionTemplate. + items: + description: PromotionStep describes a directive to be executed + as part of a Promotion. + properties: + as: + description: As is the alias this step can be referred to as. + type: string + config: + description: |- + Config is opaque configuration for the PromotionStep that is understood + only by each PromotionStep's implementation. It is legal to utilize + expressions in defining values at any level of this block. + See https://docs.kargo.io/references/expression-language for details. + x-kubernetes-preserve-unknown-fields: true + retry: + description: Retry is the retry policy for this step. + properties: + errorThreshold: + description: |- + ErrorThreshold is the number of consecutive times the step must fail (for + any reason) before retries are abandoned and the entire Promotion is marked + as failed. + + If this field is set to 0, the effective default will be a step-specific + one. If no step-specific default exists (i.e. is also 0), the effective + default will be the system-wide default of 1. + + A value of 1 will cause the Promotion to be marked as failed after just + a single failure; i.e. no retries will be attempted. + + There is no option to specify an infinite number of retries using a value + such as -1. + + In a future release, Kargo is likely to become capable of distinguishing + between recoverable and non-recoverable step failures. At that time, it is + planned that unrecoverable failures will not be subject to this threshold + and will immediately cause the Promotion to be marked as failed without + further condition. + format: int32 + type: integer + timeout: + description: |- + Timeout is the soft maximum interval in which a step that returns a Running + status (which typically indicates it's waiting for something to happen) + may be retried. + + The maximum is a soft one because the check for whether the interval has + elapsed occurs AFTER the step has run. This effectively means a step may + run ONCE beyond the close of the interval. + + If this field is set to nil, the effective default will be a step-specific + one. If no step-specific default exists (i.e. is also nil), the effective + default will be the system-wide default of 0. + + A value of 0 will cause the step to be retried indefinitely unless the + ErrorThreshold is reached. + type: string + type: object + task: + description: |- + Task is a reference to a PromotionTask that should be inflated into a + Promotion when it is built from a PromotionTemplate. + properties: + kind: + description: |- + Kind is the type of the PromotionTask. Can be either PromotionTask or + ClusterPromotionTask, default is PromotionTask. + enum: + - PromotionTask + - ClusterPromotionTask + type: string + name: + description: Name is the name of the (Cluster)PromotionTask. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + uses: + description: Uses identifies a runner that can execute this + step. + minLength: 1 + type: string + vars: + description: |- + Vars is a list of variables that can be referenced by expressions in + the step's Config. The values override the values specified in the + PromotionSpec. + items: + description: |- + PromotionVariable describes a single variable that may be referenced by + expressions in promotion steps. + properties: + name: + description: Name is the name of the variable. + minLength: 1 + pattern: ^[a-zA-Z_]\w*$ + type: string + value: + description: |- + Value is the value of the variable. It is allowed to utilize expressions + in the value. + See https://docs.kargo.io/references/expression-language for details. + type: string + required: + - name + type: object + type: array + type: object + x-kubernetes-validations: + - message: PromotionTask step must have uses set and must not reference + another task + rule: has(self.uses) && !has(self.task) + minItems: 1 + type: array + vars: + description: |- + Vars specifies the variables available to the PromotionTask. The + values of these variables are the default values that can be + overridden by the step referencing the task. + items: + description: |- + PromotionVariable describes a single variable that may be referenced by + expressions in promotion steps. + properties: + name: + description: Name is the name of the variable. + minLength: 1 + pattern: ^[a-zA-Z_]\w*$ + type: string + value: + description: |- + Value is the value of the variable. It is allowed to utilize expressions + in the value. + See https://docs.kargo.io/references/expression-language for details. + type: string + required: + - name + type: object + type: array + required: + - steps + type: object + required: + - spec + type: object + served: true + storage: true + subresources: {} diff --git a/charts/kargo/resources/crds/kargo.akuity.io_stages.yaml b/charts/kargo/resources/crds/kargo.akuity.io_stages.yaml index fabd57e02..81f679b48 100644 --- a/charts/kargo/resources/crds/kargo.akuity.io_stages.yaml +++ b/charts/kargo/resources/crds/kargo.akuity.io_stages.yaml @@ -132,14 +132,63 @@ spec: ErrorThreshold is reached. type: string type: object + task: + description: |- + Task is a reference to a PromotionTask that should be inflated into a + Promotion when it is built from a PromotionTemplate. + properties: + kind: + description: |- + Kind is the type of the PromotionTask. Can be either PromotionTask or + ClusterPromotionTask, default is PromotionTask. + enum: + - PromotionTask + - ClusterPromotionTask + type: string + name: + description: Name is the name of the (Cluster)PromotionTask. + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object uses: description: Uses identifies a runner that can execute this step. minLength: 1 type: string - required: - - uses + vars: + description: |- + Vars is a list of variables that can be referenced by expressions in + the step's Config. The values override the values specified in the + PromotionSpec. + items: + description: |- + PromotionVariable describes a single variable that may be referenced by + expressions in promotion steps. + properties: + name: + description: Name is the name of the variable. + minLength: 1 + pattern: ^[a-zA-Z_]\w*$ + type: string + value: + description: |- + Value is the value of the variable. It is allowed to utilize expressions + in the value. + See https://docs.kargo.io/references/expression-language for details. + type: string + required: + - name + type: object + type: array type: object + x-kubernetes-validations: + - message: PromotionTemplate step must have exactly one + of uses or task set + rule: '(has(self.uses) ? !has(self.task) : has(self.task))' minItems: 1 type: array vars: @@ -164,7 +213,6 @@ spec: type: string required: - name - - value type: object type: array type: object diff --git a/charts/kargo/templates/controller/cluster-roles.yaml b/charts/kargo/templates/controller/cluster-roles.yaml index f482a18cf..209e187a3 100644 --- a/charts/kargo/templates/controller/cluster-roles.yaml +++ b/charts/kargo/templates/controller/cluster-roles.yaml @@ -55,6 +55,8 @@ rules: - apiGroups: - kargo.akuity.io resources: + - clusterpromotiontasks + - promotiontasks - warehouses verbs: - get diff --git a/charts/kargo/templates/users/cluster-roles.yaml b/charts/kargo/templates/users/cluster-roles.yaml index 545ab1ad9..1f6b35cbc 100644 --- a/charts/kargo/templates/users/cluster-roles.yaml +++ b/charts/kargo/templates/users/cluster-roles.yaml @@ -105,9 +105,11 @@ rules: - apiGroups: - kargo.akuity.io resources: + - clusterpromotiontasks - freights - projects - promotions + - promotiontasks - stages - warehouses verbs: diff --git a/internal/api/promote_downstream_v1alpha1.go b/internal/api/promote_downstream_v1alpha1.go index 888194f95..ccf616acb 100644 --- a/internal/api/promote_downstream_v1alpha1.go +++ b/internal/api/promote_downstream_v1alpha1.go @@ -137,19 +137,23 @@ func (s *server) PromoteDownstream( promoteErrs := make([]error, 0, len(downstreams)) createdPromos := make([]*kargoapi.Promotion, 0, len(downstreams)) for _, downstream := range downstreams { - newPromo := kargo.NewPromotion(ctx, downstream, freight.Name) if downstream.Spec.PromotionTemplate != nil && len(downstream.Spec.PromotionTemplate.Spec.Steps) == 0 { // Avoid creating a Promotion if the downstream Stage has no promotion // steps and is therefore a "control flow" Stage. continue } - if err := s.createPromotionFn(ctx, &newPromo); err != nil { + newPromo, err := kargo.NewPromotionBuilder(s.client).Build(ctx, downstream, freight.Name) + if err != nil { promoteErrs = append(promoteErrs, err) continue } - s.recordPromotionCreatedEvent(ctx, &newPromo, freight) - createdPromos = append(createdPromos, &newPromo) + if err = s.createPromotionFn(ctx, newPromo); err != nil { + promoteErrs = append(promoteErrs, err) + continue + } + s.recordPromotionCreatedEvent(ctx, newPromo, freight) + createdPromos = append(createdPromos, newPromo) } res := connect.NewResponse(&svcv1alpha1.PromoteDownstreamResponse{ diff --git a/internal/api/promote_downstream_v1alpha1_test.go b/internal/api/promote_downstream_v1alpha1_test.go index 1c30b91fc..af3730869 100644 --- a/internal/api/promote_downstream_v1alpha1_test.go +++ b/internal/api/promote_downstream_v1alpha1_test.go @@ -30,6 +30,7 @@ func TestPromoteDownstream(t *testing.T) { }, }}, } + testCases := []struct { name string req *svcv1alpha1.PromoteDownstreamRequest @@ -74,8 +75,7 @@ func TestPromoteDownstream(t *testing.T) { _ *connect.Response[svcv1alpha1.PromoteDownstreamResponse], err error, ) { - require.Error(t, err) - require.Equal(t, "something went wrong", err.Error()) + require.ErrorContains(t, err, "something went wrong") }, }, { @@ -103,8 +103,7 @@ func TestPromoteDownstream(t *testing.T) { _ *connect.Response[svcv1alpha1.PromoteDownstreamResponse], err error, ) { - require.Error(t, err) - require.Equal(t, "get stage: something went wrong", err.Error()) + require.ErrorContains(t, err, "get stage: something went wrong") }, }, { @@ -174,8 +173,7 @@ func TestPromoteDownstream(t *testing.T) { _ *connect.Response[svcv1alpha1.PromoteDownstreamResponse], err error, ) { - require.Error(t, err) - require.Equal(t, "get freight: something went wrong", err.Error()) + require.ErrorContains(t, err, "get freight: something went wrong") }, }, { @@ -313,8 +311,7 @@ func TestPromoteDownstream(t *testing.T) { _ *connect.Response[svcv1alpha1.PromoteDownstreamResponse], err error, ) { - require.Error(t, err) - require.Equal(t, "find downstream stages: something went wrong", err.Error()) + require.ErrorContains(t, err, "find downstream stages: something went wrong") }, }, { @@ -438,8 +435,87 @@ func TestPromoteDownstream(t *testing.T) { _ *connect.Response[svcv1alpha1.PromoteDownstreamResponse], err error, ) { - require.Error(t, err) - require.Equal(t, "not authorized", err.Error()) + require.ErrorContains(t, err, "not authorized") + }, + }, + { + name: "error building Promotion", + req: &svcv1alpha1.PromoteDownstreamRequest{ + Project: "fake-project", + Stage: "fake-stage", + Freight: "fake-freight", + }, + server: &server{ + validateProjectExistsFn: func(context.Context, string) error { + return nil + }, + getStageFn: func( + context.Context, + client.Client, + types.NamespacedName, + ) (*kargoapi.Stage, error) { + return &kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "fake-project", + Name: "fake-stage", + }, + Spec: testStageSpec, + }, nil + }, + getFreightByNameOrAliasFn: func( + context.Context, + client.Client, + string, string, string, + ) (*kargoapi.Freight, error) { + return &kargoapi.Freight{ + Status: kargoapi.FreightStatus{ + VerifiedIn: map[string]kargoapi.VerifiedStage{ + "fake-stage": {}, + }, + }, + }, nil + }, + findDownstreamStagesFn: func( + context.Context, + *kargoapi.Stage, + kargoapi.FreightOrigin, + ) ([]kargoapi.Stage, error) { + return []kargoapi.Stage{ + { + Spec: kargoapi.StageSpec{ + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{{}}, + }, + }, + }, + }, + }, nil + }, + authorizeFn: func( + context.Context, + string, + schema.GroupVersionResource, + string, + client.ObjectKey, + ) error { + return nil + }, + createPromotionFn: func( + context.Context, + client.Object, + ...client.CreateOption, + ) error { + return nil + }, + }, + assertions: func( + t *testing.T, + _ *fakeevent.EventRecorder, + _ *connect.Response[svcv1alpha1.PromoteDownstreamResponse], + err error, + ) { + require.ErrorContains(t, err, "stage is required") }, }, { @@ -472,6 +548,10 @@ func TestPromoteDownstream(t *testing.T) { string, string, string, ) (*kargoapi.Freight, error) { return &kargoapi.Freight{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "fake-project", + Name: "fake-freight", + }, Status: kargoapi.FreightStatus{ VerifiedIn: map[string]kargoapi.VerifiedStage{ "fake-stage": {}, @@ -486,6 +566,10 @@ func TestPromoteDownstream(t *testing.T) { ) ([]kargoapi.Stage, error) { return []kargoapi.Stage{ { + ObjectMeta: metav1.ObjectMeta{ + Namespace: "fake-project", + Name: "fake-downstream-stage", + }, Spec: kargoapi.StageSpec{ PromotionTemplate: &kargoapi.PromotionTemplate{ Spec: kargoapi.PromotionTemplateSpec{ @@ -556,6 +640,10 @@ func TestPromoteDownstream(t *testing.T) { string, string, string, ) (*kargoapi.Freight, error) { return &kargoapi.Freight{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "fake-project", + Name: "fake-freight", + }, Status: kargoapi.FreightStatus{ VerifiedIn: map[string]kargoapi.VerifiedStage{ "fake-stage": {}, @@ -570,6 +658,10 @@ func TestPromoteDownstream(t *testing.T) { ) ([]kargoapi.Stage, error) { return []kargoapi.Stage{ { + ObjectMeta: metav1.ObjectMeta{ + Namespace: "fake-project", + Name: "fake-downstream-stage", + }, Spec: kargoapi.StageSpec{ PromotionTemplate: &kargoapi.PromotionTemplate{ Spec: kargoapi.PromotionTemplateSpec{ diff --git a/internal/api/promote_to_stage_v1alpha1.go b/internal/api/promote_to_stage_v1alpha1.go index 310d9cd05..d6b7330ab 100644 --- a/internal/api/promote_to_stage_v1alpha1.go +++ b/internal/api/promote_to_stage_v1alpha1.go @@ -98,7 +98,7 @@ func (s *server) PromoteToStage( ) } - if err := s.authorizeFn( + if err = s.authorizeFn( ctx, "promote", schema.GroupVersionResource{ @@ -115,13 +115,16 @@ func (s *server) PromoteToStage( return nil, err } - promotion := kargo.NewPromotion(ctx, *stage, freight.Name) - if err := s.createPromotionFn(ctx, &promotion); err != nil { + promotion, err := kargo.NewPromotionBuilder(s.client).Build(ctx, *stage, freight.Name) + if err != nil { + return nil, fmt.Errorf("build promotion: %w", err) + } + if err := s.createPromotionFn(ctx, promotion); err != nil { return nil, fmt.Errorf("create promotion: %w", err) } - s.recordPromotionCreatedEvent(ctx, &promotion, freight) + s.recordPromotionCreatedEvent(ctx, promotion, freight) return connect.NewResponse(&svcv1alpha1.PromoteToStageResponse{ - Promotion: &promotion, + Promotion: promotion, }), nil } diff --git a/internal/api/promote_to_stage_v1alpha1_test.go b/internal/api/promote_to_stage_v1alpha1_test.go index 99fb960a0..bd1fdcb78 100644 --- a/internal/api/promote_to_stage_v1alpha1_test.go +++ b/internal/api/promote_to_stage_v1alpha1_test.go @@ -8,6 +8,7 @@ import ( "connectrpc.com/connect" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" @@ -28,6 +29,11 @@ func TestPromoteToStage(t *testing.T) { Stages: []string{"fake-upstream-stage"}, }, }}, + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{{}}, + }, + }, } testCases := []struct { name string @@ -74,8 +80,7 @@ func TestPromoteToStage(t *testing.T) { _ *connect.Response[svcv1alpha1.PromoteToStageResponse], err error, ) { - require.Error(t, err) - require.Equal(t, "something went wrong", err.Error()) + require.ErrorContains(t, err, "something went wrong") }, }, { @@ -103,8 +108,7 @@ func TestPromoteToStage(t *testing.T) { _ *connect.Response[svcv1alpha1.PromoteToStageResponse], err error, ) { - require.Error(t, err) - require.Equal(t, "get stage: something went wrong", err.Error()) + require.ErrorContains(t, err, "get stage: something went wrong") }, }, { @@ -174,8 +178,7 @@ func TestPromoteToStage(t *testing.T) { _ *connect.Response[svcv1alpha1.PromoteToStageResponse], err error, ) { - require.Error(t, err) - require.Equal(t, "get freight: something went wrong", err.Error()) + require.ErrorContains(t, err, "get freight: something went wrong") }, }, { @@ -313,12 +316,11 @@ func TestPromoteToStage(t *testing.T) { _ *connect.Response[svcv1alpha1.PromoteToStageResponse], err error, ) { - require.Error(t, err) - require.Equal(t, "not authorized", err.Error()) + require.Error(t, err, "not authorized") }, }, { - name: "error creating Promotion", + name: "error building Promotion", req: &svcv1alpha1.PromoteToStageRequest{ Project: "fake-project", Stage: "fake-stage", @@ -334,6 +336,10 @@ func TestPromoteToStage(t *testing.T) { types.NamespacedName, ) (*kargoapi.Stage, error) { return &kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "fake-project", + Name: "fake-stage", + }, Spec: testStageSpec, }, nil }, @@ -356,6 +362,64 @@ func TestPromoteToStage(t *testing.T) { ) error { return nil }, + }, + assertions: func( + t *testing.T, + _ *fakeevent.EventRecorder, + _ *connect.Response[svcv1alpha1.PromoteToStageResponse], + err error, + ) { + require.ErrorContains(t, err, "build promotion") + }, + }, + { + name: "error creating Promotion", + req: &svcv1alpha1.PromoteToStageRequest{ + Project: "fake-project", + Stage: "fake-stage", + Freight: "fake-freight", + }, + server: &server{ + validateProjectExistsFn: func(context.Context, string) error { + return nil + }, + getStageFn: func( + context.Context, + client.Client, + types.NamespacedName, + ) (*kargoapi.Stage, error) { + return &kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "fake-project", + Name: "fake-stage", + }, + Spec: testStageSpec, + }, nil + }, + getFreightByNameOrAliasFn: func( + context.Context, + client.Client, + string, string, string, + ) (*kargoapi.Freight, error) { + return &kargoapi.Freight{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "fake-project", + Name: "fake-freight", + }, + }, nil + }, + isFreightAvailableFn: func(*kargoapi.Stage, *kargoapi.Freight) bool { + return true + }, + authorizeFn: func( + context.Context, + string, + schema.GroupVersionResource, + string, + client.ObjectKey, + ) error { + return nil + }, createPromotionFn: func( context.Context, client.Object, @@ -370,8 +434,7 @@ func TestPromoteToStage(t *testing.T) { _ *connect.Response[svcv1alpha1.PromoteToStageResponse], err error, ) { - require.Error(t, err) - require.Equal(t, "create promotion: something went wrong", err.Error()) + require.Error(t, err, "create promotion: something went wrong") }, }, { @@ -391,6 +454,10 @@ func TestPromoteToStage(t *testing.T) { types.NamespacedName, ) (*kargoapi.Stage, error) { return &kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "fake-project", + Name: "fake-stage", + }, Spec: testStageSpec, }, nil }, @@ -399,7 +466,12 @@ func TestPromoteToStage(t *testing.T) { client.Client, string, string, string, ) (*kargoapi.Freight, error) { - return &kargoapi.Freight{}, nil + return &kargoapi.Freight{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "fake-project", + Name: "fake-freight", + }, + }, nil }, isFreightAvailableFn: func(*kargoapi.Stage, *kargoapi.Freight) bool { return true diff --git a/internal/controller/promotions/promotions.go b/internal/controller/promotions/promotions.go index 57014318d..022328cf9 100644 --- a/internal/controller/promotions/promotions.go +++ b/internal/controller/promotions/promotions.go @@ -471,6 +471,7 @@ func (r *reconciler) promote( Kind: step.Uses, Alias: step.As, Retry: step.Retry, + Vars: step.Vars, Config: step.Config.Raw, } } diff --git a/internal/controller/stages/regular_stages.go b/internal/controller/stages/regular_stages.go index 1213cae4d..acd81b050 100644 --- a/internal/controller/stages/regular_stages.go +++ b/internal/controller/stages/regular_stages.go @@ -1573,19 +1573,25 @@ func (r *RegularStageReconciler) autoPromoteFreight( } // Auto promote the latest available Freight and record an event. - promotion := kargo.NewPromotion(ctx, *stage, latestFreight.Name) - if err := r.client.Create(ctx, &promotion); err != nil { + promotion, err := kargo.NewPromotionBuilder(r.client).Build(ctx, *stage, latestFreight.Name) + if err != nil { + return newStatus, fmt.Errorf( + "error building Promotion for Freight %q in namespace %q: %w", + latestFreight.Name, stage.Namespace, err, + ) + } + if err = r.client.Create(ctx, promotion); err != nil { return newStatus, fmt.Errorf( "error creating Promotion for Freight %q in namespace %q: %w", latestFreight.Name, stage.Namespace, err, ) } r.eventRecorder.AnnotatedEventf( - &promotion, + promotion, kargoEvent.NewPromotionAnnotations( ctx, kargoapi.FormatEventControllerActor(r.cfg.Name()), - &promotion, + promotion, &latestFreight, ), corev1.EventTypeNormal, diff --git a/internal/controller/stages/regular_stages_test.go b/internal/controller/stages/regular_stages_test.go index 0d87a194b..ab038a6de 100644 --- a/internal/controller/stages/regular_stages_test.go +++ b/internal/controller/stages/regular_stages_test.go @@ -4342,6 +4342,15 @@ func TestRegularStageReconciler_autoPromoteFreight(t *testing.T) { }, }, }, + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + Uses: "fake-step", + }, + }, + }, + }, }, }, objects: []client.Object{ @@ -4555,6 +4564,15 @@ func TestRegularStageReconciler_autoPromoteFreight(t *testing.T) { }, }, }, + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + Uses: "fake-step", + }, + }, + }, + }, }, }, objects: []client.Object{ @@ -4616,6 +4634,15 @@ func TestRegularStageReconciler_autoPromoteFreight(t *testing.T) { }, }, }, + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + Uses: "fake-step", + }, + }, + }, + }, }, }, objects: []client.Object{ @@ -4693,6 +4720,15 @@ func TestRegularStageReconciler_autoPromoteFreight(t *testing.T) { }, }, }, + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + Uses: "fake-step", + }, + }, + }, + }, }, }, objects: []client.Object{ @@ -4777,6 +4813,15 @@ func TestRegularStageReconciler_autoPromoteFreight(t *testing.T) { }, }, }, + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + Uses: "fake-step", + }, + }, + }, + }, }, }, objects: []client.Object{ @@ -4842,6 +4887,15 @@ func TestRegularStageReconciler_autoPromoteFreight(t *testing.T) { }, }, }, + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + Uses: "fake-step", + }, + }, + }, + }, }, }, objects: []client.Object{ @@ -4890,6 +4944,66 @@ func TestRegularStageReconciler_autoPromoteFreight(t *testing.T) { assert.Len(t, promoList.Items, 1) }, }, + { + name: "handles promotion build error", + stage: &kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "fake-project", + Name: "test-stage", + }, + Spec: kargoapi.StageSpec{ + RequestedFreight: []kargoapi.FreightRequest{ + { + Origin: kargoapi.FreightOrigin{ + Kind: kargoapi.FreightOriginKindWarehouse, + Name: "test-warehouse", + }, + Sources: kargoapi.FreightSources{ + Direct: true, + }, + }, + }, + // Missing template to build Promotion + PromotionTemplate: nil, + }, + }, + objects: []client.Object{ + &kargoapi.Project{ + ObjectMeta: metav1.ObjectMeta{ + Name: "fake-project", + }, + Spec: &kargoapi.ProjectSpec{ + PromotionPolicies: []kargoapi.PromotionPolicy{ + { + Stage: "test-stage", + AutoPromotionEnabled: true, + }, + }, + }, + }, + &kargoapi.Freight{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "fake-project", + Name: "test-freight", + CreationTimestamp: metav1.Time{Time: now}, + }, + Origin: kargoapi.FreightOrigin{ + Kind: kargoapi.FreightOriginKindWarehouse, + Name: "test-warehouse", + }, + Status: kargoapi.FreightStatus{}, + }, + }, + assertions: func( + t *testing.T, + _ *fakeevent.EventRecorder, + _ client.Client, + _ kargoapi.StageStatus, + err error, + ) { + require.ErrorContains(t, err, "error building Promotion") + }, + }, { name: "handles promotion creation error", stage: &kargoapi.Stage{ @@ -4909,6 +5023,15 @@ func TestRegularStageReconciler_autoPromoteFreight(t *testing.T) { }, }, }, + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + Uses: "fake-step", + }, + }, + }, + }, }, }, objects: []client.Object{ diff --git a/internal/directives/output_composer.go b/internal/directives/output_composer.go new file mode 100644 index 000000000..3ece6bcdc --- /dev/null +++ b/internal/directives/output_composer.go @@ -0,0 +1,70 @@ +package directives + +import ( + "context" + "fmt" + "maps" + + "github.com/xeipuuv/gojsonschema" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" +) + +func init() { + builtins.RegisterPromotionStepRunner(newOutputComposer(), nil) +} + +// outputComposer is an implementation of the PromotionStepRunner interface +// that allows composing outputs from previous steps into new outputs. +// +// It works based on the PromotionStepContext.Config field allowing to an +// arbitrary number of key-value pairs to be exported as outputs. +// Because the values are allowed to be expressions and can contain +// references to outputs from previous steps, this allows for remapping +// the outputs of previous steps to new keys, or even combining them +// into new structures. +type outputComposer struct { + schemaLoader gojsonschema.JSONLoader +} + +// newOutputComposer returns an implementation of the PromotionStepRunner +// interface that composes output from previous steps into new output. +func newOutputComposer() PromotionStepRunner { + r := &outputComposer{} + r.schemaLoader = getConfigSchemaLoader(r.Name()) + return r +} + +// Name implements the PromotionStepRunner interface. +func (c *outputComposer) Name() string { + return "compose-output" +} + +// RunPromotionStep implements the PromotionStepRunner interface. +func (c *outputComposer) RunPromotionStep( + _ context.Context, + stepCtx *PromotionStepContext, +) (PromotionStepResult, error) { + // Validate the configuration against the JSON Schema. + if err := validate(c.schemaLoader, gojsonschema.NewGoLoader(stepCtx.Config), c.Name()); err != nil { + return PromotionStepResult{Status: kargoapi.PromotionPhaseErrored}, err + } + + // Convert the configuration into a typed object. + cfg, err := ConfigToStruct[ComposeOutput](stepCtx.Config) + if err != nil { + return PromotionStepResult{Status: kargoapi.PromotionPhaseErrored}, + fmt.Errorf("could not convert config into %s config: %w", c.Name(), err) + } + + return c.runPromotionStep(cfg) +} + +func (c *outputComposer) runPromotionStep( + cfg ComposeOutput, +) (PromotionStepResult, error) { + return PromotionStepResult{ + Status: kargoapi.PromotionPhaseSucceeded, + Output: maps.Clone(cfg), + }, nil +} diff --git a/internal/directives/promotions.go b/internal/directives/promotions.go index a4af12e14..dc26adaf0 100644 --- a/internal/directives/promotions.go +++ b/internal/directives/promotions.go @@ -3,6 +3,7 @@ package directives import ( "context" "fmt" + "strings" "time" "github.com/expr-lang/expr" @@ -96,6 +97,9 @@ type PromotionStep struct { Alias string // Retry is the retry configuration for the PromotionStep. Retry *kargoapi.PromotionStepRetry + // Vars is a list of variables definitions that can be used by the + // PromotionStep. + Vars []kargoapi.PromotionVariable // Config is an opaque JSON to be passed to the PromotionStepRunner executing // this step. Config []byte @@ -139,23 +143,35 @@ func (s *PromotionStep) GetConfig( return nil, nil } - vars, err := s.GetVars(promoCtx) + vars, err := s.GetVars(promoCtx, state) if err != nil { return nil, err } + env := map[string]any{ + "ctx": map[string]any{ + "project": promoCtx.Project, + "promotion": promoCtx.Promotion, + "stage": promoCtx.Stage, + }, + "vars": vars, + "secrets": promoCtx.Secrets, + "outputs": state, + } + + // Ensure that if the PromotionStep originated from a task, the task outputs + // are available to the PromotionStep. This allows inflated steps to access + // the outputs of the other steps in the task without needing to know the + // alias (namespace) of the task. + if taskOutput := s.getTaskOutputs(state); taskOutput != nil { + env["task"] = map[string]any{ + "outputs": taskOutput, + } + } + evaledCfgJSON, err := expressions.EvaluateJSONTemplate( s.Config, - map[string]any{ - "ctx": map[string]any{ - "project": promoCtx.Project, - "promotion": promoCtx.Promotion, - "stage": promoCtx.Stage, - }, - "vars": vars, - "secrets": promoCtx.Secrets, - "outputs": state, - }, + env, expr.Function("warehouse", warehouseFunc, new(func(string) kargoapi.FreightOrigin)), expr.Function( "commitFrom", @@ -190,28 +206,63 @@ func (s *PromotionStep) GetConfig( // GetVars returns the variables defined in the PromotionStep. The variables are // evaluated in the context of the provided PromotionContext. -func (s *PromotionStep) GetVars(promoCtx PromotionContext) (map[string]any, error) { - vars := make(map[string]any, len(promoCtx.Vars)) +func (s *PromotionStep) GetVars( + promoCtx PromotionContext, + state State, +) (map[string]any, error) { + var rawVars = make(map[string]string, len(promoCtx.Vars)) for _, v := range promoCtx.Vars { - newVar, err := expressions.EvaluateTemplate( - v.Value, - map[string]any{ - "ctx": map[string]any{ - "project": promoCtx.Project, - "promotion": promoCtx.Promotion, - "stage": promoCtx.Stage, - }, - "vars": vars, + rawVars[v.Name] = v.Value + } + for _, v := range s.Vars { + rawVars[v.Name] = v.Value + } + + taskOutput := s.getTaskOutputs(state) + + vars := make(map[string]any, len(rawVars)) + for k, v := range rawVars { + env := map[string]any{ + "ctx": map[string]any{ + "project": promoCtx.Project, + "promotion": promoCtx.Promotion, + "stage": promoCtx.Stage, }, - ) + "vars": vars, + "outputs": state, + } + + if taskOutput != nil { + env["task"] = map[string]any{ + "outputs": taskOutput, + } + } + + newVar, err := expressions.EvaluateTemplate(v, env) if err != nil { - return nil, fmt.Errorf("error pre-processing promotion variable %q: %w", v.Name, err) + return nil, fmt.Errorf("error pre-processing promotion variable %q: %w", k, err) } - vars[v.Name] = newVar + vars[k] = newVar } return vars, nil } +// getTaskOutputs returns the outputs of a task that are relevant to the current +// step. This is useful when a step is inflated from a task and needs to access +// the outputs of that task. +func (s *PromotionStep) getTaskOutputs(state State) State { + if namespace := getAliasNamespace(s.Alias); namespace != "" { + taskOutputs := make(State) + for k, v := range state.DeepCopy() { + if getAliasNamespace(k) == namespace { + taskOutputs[k[len(namespace)+2:]] = v + } + } + return taskOutputs + } + return nil +} + // PromotionResult is the result of a user-defined promotion process executed by // the Engine. It aggregates the status and output of the individual // PromotionStepResults returned by the PromotionStepRunner executing each @@ -416,3 +467,14 @@ func getChartFunc( ) } } + +// getAliasNamespace returns the namespace part of an alias, if it exists. +// The namespace part is the part before the first "::" separator. Typically, +// this is used for steps inflated from a task. +func getAliasNamespace(alias string) string { + parts := strings.Split(alias, "::") + if len(parts) != 2 { + return "" + } + return parts[0] +} diff --git a/internal/directives/schemas/compose-output-config.json b/internal/directives/schemas/compose-output-config.json new file mode 100644 index 000000000..76421df1d --- /dev/null +++ b/internal/directives/schemas/compose-output-config.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "ComposeOutput", + "type": "object", + "minProperties": 1 +} diff --git a/internal/directives/simple_engine_promote.go b/internal/directives/simple_engine_promote.go index d262e83b8..b3a2c21ae 100644 --- a/internal/directives/simple_engine_promote.go +++ b/internal/directives/simple_engine_promote.go @@ -120,7 +120,21 @@ func (e *SimpleEngine) executeSteps( stepExecMeta.Status = result.Status stepExecMeta.Message = result.Message } - state[step.Alias] = result.Output + + // TODO(hidde): until we have a better way to handle the output of steps + // inflated from tasks, we need to apply a special treatment to the output + // to allow it to become available under the alias of the "task". + aliasNamespace := getAliasNamespace(step.Alias) + if aliasNamespace != "" && reg.Runner.Name() == (&outputComposer{}).Name() { + if state[aliasNamespace] == nil { + state[aliasNamespace] = make(map[string]any) + } + for k, v := range result.Output { + state[aliasNamespace].(map[string]any)[k] = v // nolint: forcetypeassert + } + } else { + state[step.Alias] = result.Output + } if stepExecMeta.Status == kargoapi.PromotionPhaseSucceeded { stepExecMeta.FinishedAt = ptr.To(metav1.Now()) diff --git a/internal/directives/zz_config_types.go b/internal/directives/zz_config_types.go index e09b38c60..c1d89150b 100644 --- a/internal/directives/zz_config_types.go +++ b/internal/directives/zz_config_types.go @@ -4,6 +4,8 @@ package directives type CommonDefs interface{} +type ComposeOutput map[string]interface{} + type ArgoCDUpdateConfig struct { Apps []ArgoCDAppUpdate `json:"apps"` FromOrigin *AppFromOrigin `json:"fromOrigin,omitempty"` diff --git a/internal/indexer/indexer.go b/internal/indexer/indexer.go index 6a134b6bd..6b051f5d9 100644 --- a/internal/indexer/indexer.go +++ b/internal/indexer/indexer.go @@ -168,7 +168,7 @@ func RunningPromotionsByArgoCDApplications( Promotion: promo.Name, Vars: promo.Spec.Vars, } - vars, err := dirStep.GetVars(promoCtx) + vars, err := dirStep.GetVars(promoCtx, promoCtx.State) if err != nil { logger.Error( err, diff --git a/internal/kargo/kargo.go b/internal/kargo/kargo.go index d3c1ad7d2..148bd14c6 100644 --- a/internal/kargo/kargo.go +++ b/internal/kargo/kargo.go @@ -1,71 +1,13 @@ package kargo import ( - "context" - "fmt" - "strings" - - "github.com/oklog/ulid/v2" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" kargoapi "github.com/akuity/kargo/api/v1alpha1" - "github.com/akuity/kargo/internal/api/user" "github.com/akuity/kargo/internal/logging" ) -const ( - // maximum length of the stage name used in the promotion name prefix before it exceeds - // kubernetes resource name limit of 253 - // 253 - 1 (.) - 26 (ulid) - 1 (.) - 7 (sha) = 218 - maxStageNamePrefixLength = 218 -) - -// NewPromotion returns a new Promotion from a given stage and freight with our -// naming convention. -func NewPromotion( - ctx context.Context, - stage kargoapi.Stage, - freight string, -) kargoapi.Promotion { - shortHash := freight - if len(shortHash) > 7 { - shortHash = freight[0:7] - } - shortStageName := stage.Name - if len(stage.Name) > maxStageNamePrefixLength { - shortStageName = shortStageName[0:maxStageNamePrefixLength] - } - - annotations := make(map[string]string, 1) - // Put actor information to track on the controller side - if u, ok := user.InfoFromContext(ctx); ok { - annotations[kargoapi.AnnotationKeyCreateActor] = kargoapi.FormatEventUserActor(u) - } - - // ulid.Make() is pseudo-random, not crypto-random, but we don't care. - // We just want a unique ID that can be sorted lexicographically - promoName := strings.ToLower(fmt.Sprintf("%s.%s.%s", shortStageName, ulid.Make(), shortHash)) - - promotion := kargoapi.Promotion{ - ObjectMeta: metav1.ObjectMeta{ - Name: promoName, - Namespace: stage.Namespace, - Annotations: annotations, - }, - Spec: kargoapi.PromotionSpec{ - Stage: stage.Name, - Freight: freight, - }, - } - if stage.Spec.PromotionTemplate != nil { - promotion.Spec.Vars = stage.Spec.PromotionTemplate.Spec.Vars - promotion.Spec.Steps = stage.Spec.PromotionTemplate.Spec.Steps - } - return promotion -} - func NewPromoWentTerminalPredicate(logger *logging.Logger) PromoWentTerminal[*kargoapi.Promotion] { return PromoWentTerminal[*kargoapi.Promotion]{ logger: logger, diff --git a/internal/kargo/kargo_test.go b/internal/kargo/kargo_test.go index c71d9f929..da5abc9f7 100644 --- a/internal/kargo/kargo_test.go +++ b/internal/kargo/kargo_test.go @@ -37,6 +37,17 @@ func TestNewPromotion(t *testing.T) { Name: "test", Namespace: "kargo-demo", }, + Spec: kargoapi.StageSpec{ + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + Uses: "fake-step", + }, + }, + }, + }, + }, }, freight: testFreight, assertions: func(t *testing.T, _ kargoapi.Stage, promo kargoapi.Promotion) { @@ -53,6 +64,17 @@ func TestNewPromotion(t *testing.T) { Name: veryLongResourceName, Namespace: "kargo-demo", }, + Spec: kargoapi.StageSpec{ + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + Uses: "fake-step", + }, + }, + }, + }, + }, }, freight: testFreight, assertions: func(t *testing.T, _ kargoapi.Stage, promo kargoapi.Promotion) { @@ -65,12 +87,13 @@ func TestNewPromotion(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - promo := NewPromotion(context.TODO(), tc.stage, tc.freight) + promo, err := NewPromotionBuilder(nil).Build(context.TODO(), tc.stage, tc.freight) + require.NoError(t, err) require.Equal(t, tc.freight, promo.Spec.Freight) require.Equal(t, tc.stage.Name, promo.Spec.Stage) require.Equal(t, tc.freight, promo.Spec.Freight) require.LessOrEqual(t, len(promo.Name), 253) - tc.assertions(t, tc.stage, promo) + tc.assertions(t, tc.stage, *promo) }) } } diff --git a/internal/kargo/promotion_builder.go b/internal/kargo/promotion_builder.go new file mode 100644 index 000000000..ff3386fc4 --- /dev/null +++ b/internal/kargo/promotion_builder.go @@ -0,0 +1,264 @@ +package kargo + +import ( + "context" + "errors" + "fmt" + "strings" + + "github.com/oklog/ulid/v2" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/internal/api/user" +) + +const ( + // nameSeparator is the separator used in the Promotion name. + nameSeparator = "." + + // aliasSeparator is the separator used in the Promotion step alias + // to separate the task alias from the step alias. + aliasSeparator = "::" + + // ulidLength is the length of the ULID string. + ulidLength = ulid.EncodedSize + + // shortHashLength is the length of the short hash. + shortHashLength = 7 + + // maxStageNamePrefixLength is the maximum length of the Stage name + // used in the Promotion name prefix before it exceeds the Kubernetes + // resource name limit of 253. + maxStageNamePrefixLength = 253 - len(nameSeparator) - ulidLength - len(nameSeparator) - shortHashLength +) + +type PromotionBuilder struct { + client client.Client +} + +// NewPromotionBuilder creates a new PromotionBuilder with the given client. +func NewPromotionBuilder(c client.Client) *PromotionBuilder { + return &PromotionBuilder{ + client: c, + } +} + +// Build creates a new Promotion for the Freight based on the PromotionTemplate +// of the given Stage. +func (b *PromotionBuilder) Build( + ctx context.Context, + stage kargoapi.Stage, + freight string, +) (*kargoapi.Promotion, error) { + if stage.Name == "" { + return nil, fmt.Errorf("stage is required") + } + + if stage.Spec.PromotionTemplate == nil { + return nil, fmt.Errorf("stage %q has no promotion template", stage.Name) + } + + if freight == "" { + return nil, fmt.Errorf("freight is required") + } + + // Build metadata + annotations := make(map[string]string) + if u, ok := user.InfoFromContext(ctx); ok { + annotations[kargoapi.AnnotationKeyCreateActor] = kargoapi.FormatEventUserActor(u) + } + + // Build steps + steps, err := b.buildSteps(ctx, stage) + if err != nil { + return nil, fmt.Errorf("failed to build promotion steps: %w", err) + } + + promotion := kargoapi.Promotion{ + ObjectMeta: metav1.ObjectMeta{ + Name: generatePromotionName(stage.Name, freight), + Namespace: stage.Namespace, + Annotations: annotations, + }, + Spec: kargoapi.PromotionSpec{ + Stage: stage.Name, + Freight: freight, + Vars: stage.Spec.PromotionTemplate.Spec.Vars, + Steps: steps, + }, + } + return &promotion, nil +} + +// buildSteps processes the Promotion steps from the PromotionTemplate of the +// given Stage. If a PromotionStep references a PromotionTask, the task is +// retrieved and its steps are inflated with the given task inputs. +func (b *PromotionBuilder) buildSteps(ctx context.Context, stage kargoapi.Stage) ([]kargoapi.PromotionStep, error) { + steps := make([]kargoapi.PromotionStep, 0, len(stage.Spec.PromotionTemplate.Spec.Steps)) + for i, step := range stage.Spec.PromotionTemplate.Spec.Steps { + switch { + case step.Task != nil: + alias := step.GetAlias(i) + taskSteps, err := b.inflateTaskSteps( + ctx, + stage.Namespace, + alias, + stage.Spec.PromotionTemplate.Spec.Vars, + step, + ) + if err != nil { + return nil, fmt.Errorf("inflate tasks steps for task %q (%q): %w", step.Task.Name, alias, err) + } + steps = append(steps, taskSteps...) + default: + steps = append(steps, step) + } + } + return steps, nil +} + +// inflateTaskSteps inflates the PromotionSteps for the given PromotionStep +// that references a (Cluster)PromotionTask. The task is retrieved and its +// steps are inflated with the given task inputs. +func (b *PromotionBuilder) inflateTaskSteps( + ctx context.Context, + project, taskAlias string, + promoVars []kargoapi.PromotionVariable, + taskStep kargoapi.PromotionStep, +) ([]kargoapi.PromotionStep, error) { + task, err := b.getTaskSpec(ctx, project, taskStep.Task) + if err != nil { + return nil, err + } + + vars, err := promotionTaskVarsToStepVars(task.Vars, promoVars, taskStep.Vars) + if err != nil { + return nil, err + } + + var steps []kargoapi.PromotionStep + for i := range task.Steps { + // Copy the step as-is. + step := &task.Steps[i] + + // Ensures we have a unique alias for each step within the context of + // the Promotion. + step.As = generatePromotionTaskStepAlias(taskAlias, step.GetAlias(i)) + + // With the variables validated and mapped, they are now available to + // the Config of the step during the Promotion execution. + step.Vars = vars + + // Append the inflated step to the list of steps. + steps = append(steps, *step) + } + return steps, nil +} + +// getTaskSpec retrieves the PromotionTaskSpec for the given PromotionTaskReference. +func (b *PromotionBuilder) getTaskSpec( + ctx context.Context, + project string, + ref *kargoapi.PromotionTaskReference, +) (*kargoapi.PromotionTaskSpec, error) { + var spec kargoapi.PromotionTaskSpec + + if ref == nil { + return nil, errors.New("missing task reference") + } + + switch ref.Kind { + case "PromotionTask", "": + task := &kargoapi.PromotionTask{} + if err := b.client.Get(ctx, client.ObjectKey{Namespace: project, Name: ref.Name}, task); err != nil { + return nil, err + } + spec = task.Spec + case "ClusterPromotionTask": + task := &kargoapi.ClusterPromotionTask{} + if err := b.client.Get(ctx, client.ObjectKey{Name: ref.Name}, task); err != nil { + return nil, err + } + spec = task.Spec + default: + return nil, fmt.Errorf("unknown task reference kind %q", ref.Kind) + } + + return &spec, nil +} + +// generatePromotionName generates a name for the Promotion by combining the +// Stage name, a ULID, and a short hash of the Freight. +// +// The name has the format of: +// +// .. +func generatePromotionName(stageName, freight string) string { + if stageName == "" || freight == "" { + return "" + } + + shortHash := freight + if len(shortHash) > shortHashLength { + shortHash = shortHash[0:shortHashLength] + } + + shortStageName := stageName + if len(stageName) > maxStageNamePrefixLength { + shortStageName = shortStageName[0:maxStageNamePrefixLength] + } + + parts := []string{shortStageName, ulid.Make().String(), shortHash} + return strings.ToLower(strings.Join(parts, nameSeparator)) +} + +// generatePromotionTaskStepAlias generates an alias for a PromotionTask step +// by combining the task alias and the step alias. +func generatePromotionTaskStepAlias(taskAlias, stepAlias string) string { + return fmt.Sprintf("%s%s%s", taskAlias, aliasSeparator, stepAlias) +} + +// promotionTaskVarsToStepVars validates the presence of the PromotionTask +// variables and maps them to variables which can be used by the inflated +// PromotionStep. +func promotionTaskVarsToStepVars( + taskVars, promoVars, stepVars []kargoapi.PromotionVariable, +) ([]kargoapi.PromotionVariable, error) { + if len(taskVars) == 0 { + return nil, nil + } + + promoVarsMap := make(map[string]kargoapi.PromotionVariable, len(promoVars)) + for _, v := range promoVars { + promoVarsMap[v.Name] = v + } + + stepVarsMap := make(map[string]kargoapi.PromotionVariable, len(stepVars)) + for _, v := range stepVars { + stepVarsMap[v.Name] = v + } + + vars := make([]kargoapi.PromotionVariable, 0, len(taskVars)) + for _, v := range taskVars { + if stepVar, ok := stepVarsMap[v.Name]; ok && stepVar.Value != "" { + vars = append(vars, stepVar) + continue + } + + if promoVar, ok := promoVarsMap[v.Name]; ok && promoVar.Value != "" { + // If the variable is defined in the Promotion, the engine will + // automatically use the value from the Promotion, and we do not + // have to explicitly set it here. + continue + } + + if v.Value == "" { + return nil, fmt.Errorf("missing value for variable %q", v.Name) + } + + vars = append(vars, v) + } + return vars, nil +} diff --git a/internal/kargo/promotion_builder_test.go b/internal/kargo/promotion_builder_test.go new file mode 100644 index 000000000..a4b332d7d --- /dev/null +++ b/internal/kargo/promotion_builder_test.go @@ -0,0 +1,1086 @@ +package kargo + +import ( + "context" + "errors" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/client/interceptor" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" + "github.com/akuity/kargo/internal/api/user" +) + +func TestPromotionBuilder_Build(t *testing.T) { + s := runtime.NewScheme() + require.NoError(t, kargoapi.AddToScheme(s)) + + tests := []struct { + name string + stage kargoapi.Stage + freight string + userInfo user.Info + objects []client.Object + assertions func(*testing.T, *kargoapi.Promotion, error) + }{ + { + name: "empty stage name returns error", + stage: kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "test-project", + }, + }, + freight: "abc123", + assertions: func(t *testing.T, promotion *kargoapi.Promotion, err error) { + assert.ErrorContains(t, err, "stage is required") + assert.Nil(t, promotion) + }, + }, + { + name: "empty freight returns error", + stage: kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-stage", + Namespace: "test-project", + }, + Spec: kargoapi.StageSpec{ + PromotionTemplate: &kargoapi.PromotionTemplate{}, + }, + }, + freight: "", + assertions: func(t *testing.T, promotion *kargoapi.Promotion, err error) { + assert.ErrorContains(t, err, "freight is required") + assert.Nil(t, promotion) + }, + }, + { + name: "missing promotion template returns error", + stage: kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-stage", + Namespace: "test-project", + }, + }, + freight: "abc123", + assertions: func(t *testing.T, promotion *kargoapi.Promotion, err error) { + assert.ErrorContains(t, err, "has no promotion template") + assert.Nil(t, promotion) + }, + }, + { + name: "successful build with direct steps", + stage: kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-stage", + Namespace: "test-project", + }, + Spec: kargoapi.StageSpec{ + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Vars: []kargoapi.PromotionVariable{ + {Name: "key1", Value: "value1"}, + }, + Steps: []kargoapi.PromotionStep{ + { + As: "step1", + Uses: "fake-step", + }, + }, + }, + }, + }, + }, + freight: "abc123", + assertions: func(t *testing.T, promotion *kargoapi.Promotion, err error) { + require.NoError(t, err) + require.NotNil(t, promotion) + + // Check basic metadata + assert.Equal(t, "test-project", promotion.Namespace) + assert.Equal(t, "test-stage", promotion.Spec.Stage) + assert.Equal(t, "abc123", promotion.Spec.Freight) + + // Check vars + assert.Equal(t, []kargoapi.PromotionVariable{ + { + Name: "key1", + Value: "value1", + }, + }, promotion.Spec.Vars) + + // Check steps + require.Len(t, promotion.Spec.Steps, 1) + assert.Equal(t, "step1", promotion.Spec.Steps[0].As) + assert.Equal(t, "fake-step", promotion.Spec.Steps[0].Uses) + + // Check name format + assert.Contains(t, promotion.Name, "test-stage") + assert.Contains(t, promotion.Name, "abc123"[:6]) + }, + }, + { + name: "successful build with task steps and user info", + stage: kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-stage", + Namespace: "test-project", + }, + Spec: kargoapi.StageSpec{ + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + As: "task-step", + Task: &kargoapi.PromotionTaskReference{ + Name: "test-task", + }, + Vars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + }, + }, + }, + }, + }, + }, + }, + freight: "abc123", + userInfo: user.Info{ + IsAdmin: true, + }, + objects: []client.Object{ + &kargoapi.PromotionTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-task", + Namespace: "test-project", + }, + Spec: kargoapi.PromotionTaskSpec{ + Vars: []kargoapi.PromotionVariable{ + {Name: "input1"}, + }, + Steps: []kargoapi.PromotionStep{ + { + As: "sub-step", + Uses: "other-fake-step", + }, + }, + }, + }, + }, + assertions: func(t *testing.T, promotion *kargoapi.Promotion, err error) { + require.NoError(t, err) + require.NotNil(t, promotion) + + // Check metadata including user annotation + assert.Equal(t, kargoapi.EventActorAdmin, promotion.Annotations[kargoapi.AnnotationKeyCreateActor]) + + // Check steps + require.Len(t, promotion.Spec.Steps, 1) + assert.Equal(t, "task-step::sub-step", promotion.Spec.Steps[0].As) + assert.Equal(t, "other-fake-step", promotion.Spec.Steps[0].Uses) + assert.ElementsMatch(t, []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + }, promotion.Spec.Steps[0].Vars) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := user.ContextWithInfo(context.Background(), tt.userInfo) + + c := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(tt.objects...). + Build() + + b := NewPromotionBuilder(c) + promotion, err := b.Build(ctx, tt.stage, tt.freight) + tt.assertions(t, promotion, err) + }) + } +} + +func TestPromotionBuilder_buildSteps(t *testing.T) { + s := runtime.NewScheme() + require.NoError(t, kargoapi.AddToScheme(s)) + + tests := []struct { + name string + stage kargoapi.Stage + objects []client.Object + assertions func(*testing.T, []kargoapi.PromotionStep, error) + }{ + { + name: "task not found returns error", + stage: kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-stage", + Namespace: "test-project", + }, + Spec: kargoapi.StageSpec{ + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + Task: &kargoapi.PromotionTaskReference{ + Name: "missing-task", + }, + }, + }, + }, + }, + }, + }, + assertions: func(t *testing.T, steps []kargoapi.PromotionStep, err error) { + assert.ErrorContains(t, err, "not found") + assert.Nil(t, steps) + }, + }, + { + name: "single direct step", + stage: kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-stage", + Namespace: "test-project", + }, + Spec: kargoapi.StageSpec{ + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + As: "direct-step", + Uses: "fake-step", + }, + }, + }, + }, + }, + }, + assertions: func(t *testing.T, steps []kargoapi.PromotionStep, err error) { + require.NoError(t, err) + require.Len(t, steps, 1) + + assert.Equal(t, "direct-step", steps[0].As) + assert.Equal(t, "fake-step", steps[0].Uses) + }, + }, + { + name: "mix of direct and task steps", + stage: kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-stage", + Namespace: "test-project", + }, + Spec: kargoapi.StageSpec{ + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + As: "direct-step", + Uses: "fake-step", + }, + { + As: "task-step", + Task: &kargoapi.PromotionTaskReference{ + Name: "test-task", + }, + Vars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + }, + }, + }, + }, + }, + }, + }, + objects: []client.Object{ + &kargoapi.PromotionTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-task", + Namespace: "test-project", + }, + Spec: kargoapi.PromotionTaskSpec{ + Vars: []kargoapi.PromotionVariable{ + {Name: "input1"}, + }, + Steps: []kargoapi.PromotionStep{ + { + As: "sub-step", + Uses: "other-fake-step", + }, + }, + }, + }, + }, + assertions: func(t *testing.T, steps []kargoapi.PromotionStep, err error) { + require.NoError(t, err) + require.Len(t, steps, 2) + + // Check direct step + assert.Equal(t, "direct-step", steps[0].As) + assert.Equal(t, "fake-step", steps[0].Uses) + + // Check inflated task step + assert.Equal(t, "task-step::sub-step", steps[1].As) + assert.Equal(t, "other-fake-step", steps[1].Uses) + assert.ElementsMatch(t, []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + }, steps[1].Vars) + }, + }, + { + name: "multiple task steps", + stage: kargoapi.Stage{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-stage", + Namespace: "test-project", + }, + Spec: kargoapi.StageSpec{ + PromotionTemplate: &kargoapi.PromotionTemplate{ + Spec: kargoapi.PromotionTemplateSpec{ + Steps: []kargoapi.PromotionStep{ + { + As: "task1", + Task: &kargoapi.PromotionTaskReference{ + Name: "test-task-1", + }, + Vars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + }, + }, + { + As: "task2", + Task: &kargoapi.PromotionTaskReference{ + Kind: "ClusterPromotionTask", + Name: "test-task-2", + }, + Vars: []kargoapi.PromotionVariable{ + {Name: "input2", Value: "value2"}, + }, + }, + }, + }, + }, + }, + }, + objects: []client.Object{ + &kargoapi.PromotionTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-task-1", + Namespace: "test-project", + }, + Spec: kargoapi.PromotionTaskSpec{ + Vars: []kargoapi.PromotionVariable{ + {Name: "input1"}, + }, + Steps: []kargoapi.PromotionStep{ + { + As: "step1", + Uses: "fake-step", + }, + }, + }, + }, + &kargoapi.ClusterPromotionTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-task-2", + }, + Spec: kargoapi.PromotionTaskSpec{ + Vars: []kargoapi.PromotionVariable{ + {Name: "input2"}, + }, + Steps: []kargoapi.PromotionStep{ + { + As: "step2", + Uses: "other-fake-step", + }, + }, + }, + }, + }, + assertions: func(t *testing.T, steps []kargoapi.PromotionStep, err error) { + require.NoError(t, err) + require.Len(t, steps, 2) + + assert.Equal(t, "task1::step1", steps[0].As) + assert.Equal(t, "fake-step", steps[0].Uses) + assert.ElementsMatch(t, []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + }, steps[0].Vars) + + assert.Equal(t, "task2::step2", steps[1].As) + assert.Equal(t, "other-fake-step", steps[1].Uses) + assert.ElementsMatch(t, []kargoapi.PromotionVariable{ + {Name: "input2", Value: "value2"}, + }, steps[1].Vars) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(tt.objects...). + Build() + + b := NewPromotionBuilder(c) + steps, err := b.buildSteps(context.Background(), tt.stage) + tt.assertions(t, steps, err) + }) + } +} + +func TestPromotionBuilder_inflateTaskSteps(t *testing.T) { + s := runtime.NewScheme() + require.NoError(t, kargoapi.AddToScheme(s)) + + tests := []struct { + name string + project string + taskAlias string + promoVars []kargoapi.PromotionVariable + taskStep kargoapi.PromotionStep + objects []client.Object + assertions func(*testing.T, []kargoapi.PromotionStep, error) + }{ + { + name: "task not found", + project: "test-project", + taskAlias: "deploy", + taskStep: kargoapi.PromotionStep{ + Task: &kargoapi.PromotionTaskReference{ + Name: "missing-task", + }, + }, + assertions: func(t *testing.T, steps []kargoapi.PromotionStep, err error) { + assert.True(t, apierrors.IsNotFound(err)) + assert.Nil(t, steps) + }, + }, + { + name: "invalid config for task variables", + project: "test-project", + + taskStep: kargoapi.PromotionStep{ + Task: &kargoapi.PromotionTaskReference{ + Name: "test-task", + }, + // Missing values + Vars: nil, + }, + objects: []client.Object{ + &kargoapi.PromotionTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-task", + Namespace: "test-project", + }, + Spec: kargoapi.PromotionTaskSpec{ + Vars: []kargoapi.PromotionVariable{ + {Name: "input1"}, + }, + }, + }, + }, + assertions: func(t *testing.T, steps []kargoapi.PromotionStep, err error) { + assert.ErrorContains(t, err, "missing value for variable") + assert.Nil(t, steps) + }, + }, + { + name: "successful task step inflation", + project: "test-project", + taskAlias: "task-1", + promoVars: []kargoapi.PromotionVariable{ + {Name: "input3", Value: "value1"}, + }, + taskStep: kargoapi.PromotionStep{ + Task: &kargoapi.PromotionTaskReference{ + Name: "test-task", + }, + Vars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + {Name: "input2", Value: "value2"}, + }, + }, + objects: []client.Object{ + &kargoapi.PromotionTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-task", + Namespace: "test-project", + }, + Spec: kargoapi.PromotionTaskSpec{ + Vars: []kargoapi.PromotionVariable{ + {Name: "input1"}, + {Name: "input2", Value: "default2"}, + {Name: "input3"}, + }, + Steps: []kargoapi.PromotionStep{ + { + As: "step1", + Uses: "fake-step", + }, + { + As: "step2", + Uses: "other-fake-step", + }, + }, + }, + }, + }, + assertions: func(t *testing.T, steps []kargoapi.PromotionStep, err error) { + require.NoError(t, err) + require.Len(t, steps, 2) + + assert.Equal(t, "task-1::step1", steps[0].As) + assert.Equal(t, "fake-step", steps[0].Uses) + assert.ElementsMatch(t, []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + {Name: "input2", Value: "value2"}, + }, steps[0].Vars) + + assert.Equal(t, "task-1::step2", steps[1].As) + assert.Equal(t, "other-fake-step", steps[1].Uses) + assert.ElementsMatch(t, []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + {Name: "input2", Value: "value2"}, + }, steps[1].Vars) + }, + }, + { + name: "task steps with default alias", + project: "test-project", + taskAlias: "custom-alias", + taskStep: kargoapi.PromotionStep{ + Task: &kargoapi.PromotionTaskReference{ + Name: "test-task", + }, + Vars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + }, + }, + objects: []client.Object{ + &kargoapi.PromotionTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-task", + Namespace: "test-project", + }, + Spec: kargoapi.PromotionTaskSpec{ + Vars: []kargoapi.PromotionVariable{ + {Name: "input1"}, + }, + Steps: []kargoapi.PromotionStep{ + { + Uses: "fake-step", + }, + { + Uses: "other-fake-step", + }, + }, + }, + }, + }, + assertions: func(t *testing.T, steps []kargoapi.PromotionStep, err error) { + require.NoError(t, err) + require.Len(t, steps, 2) + + assert.Equal(t, "custom-alias::step-0", steps[0].As) + assert.Equal(t, "custom-alias::step-1", steps[1].As) + }, + }, + { + name: "cluster task with steps", + project: "test-project", + taskAlias: "task-0", + taskStep: kargoapi.PromotionStep{ + Task: &kargoapi.PromotionTaskReference{ + Kind: "ClusterPromotionTask", + Name: "test-cluster-task", + }, + Vars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + }, + }, + objects: []client.Object{ + &kargoapi.ClusterPromotionTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-task", + }, + Spec: kargoapi.PromotionTaskSpec{ + Vars: []kargoapi.PromotionVariable{ + {Name: "input1"}, + }, + Steps: []kargoapi.PromotionStep{ + { + As: "custom-alias", + Uses: "fake-step", + }, + }, + }, + }, + }, + assertions: func(t *testing.T, steps []kargoapi.PromotionStep, err error) { + require.NoError(t, err) + require.Len(t, steps, 1) + assert.Equal(t, "task-0::custom-alias", steps[0].As) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(tt.objects...). + Build() + + b := NewPromotionBuilder(c) + steps, err := b.inflateTaskSteps(context.Background(), tt.project, tt.taskAlias, tt.promoVars, tt.taskStep) + tt.assertions(t, steps, err) + }) + } +} + +func TestPromotionBuilder_getTaskSpec(t *testing.T) { + s := runtime.NewScheme() + require.NoError(t, kargoapi.AddToScheme(s)) + + tests := []struct { + name string + project string + ref *kargoapi.PromotionTaskReference + objects []client.Object + interceptor interceptor.Funcs + assertions func(*testing.T, *kargoapi.PromotionTaskSpec, error) + }{ + { + name: "nil reference returns error", + project: "test-project", + ref: nil, + assertions: func(t *testing.T, result *kargoapi.PromotionTaskSpec, err error) { + assert.ErrorContains(t, err, "missing task reference") + assert.Nil(t, result) + }, + }, + { + name: "unknown task kind returns error", + project: "test-project", + ref: &kargoapi.PromotionTaskReference{ + Kind: "UnknownKind", + Name: "test-task", + }, + assertions: func(t *testing.T, result *kargoapi.PromotionTaskSpec, err error) { + assert.ErrorContains(t, err, "unknown task reference kind") + assert.Nil(t, result) + }, + }, + { + name: "PromotionTask not found returns error", + project: "test-project", + ref: &kargoapi.PromotionTaskReference{ + Kind: "PromotionTask", + Name: "missing-task", + }, + interceptor: interceptor.Funcs{ + Get: func( + context.Context, + client.WithWatch, + client.ObjectKey, + client.Object, + ...client.GetOption, + ) error { + return errors.New("something went wrong") + }, + }, + assertions: func(t *testing.T, result *kargoapi.PromotionTaskSpec, err error) { + assert.ErrorContains(t, err, "something went wrong") + assert.Nil(t, result) + }, + }, + { + name: "ClusterPromotionTask not found returns error", + project: "test-project", + ref: &kargoapi.PromotionTaskReference{ + Kind: "ClusterPromotionTask", + Name: "missing-cluster-task", + }, + interceptor: interceptor.Funcs{ + Get: func( + context.Context, + client.WithWatch, + client.ObjectKey, + client.Object, + ...client.GetOption, + ) error { + return errors.New("something went wrong") + }, + }, + assertions: func(t *testing.T, result *kargoapi.PromotionTaskSpec, err error) { + assert.ErrorContains(t, err, "something went wrong") + assert.Nil(t, result) + }, + }, + { + name: "successfully retrieves PromotionTask", + project: "test-project", + ref: &kargoapi.PromotionTaskReference{ + Kind: "PromotionTask", + Name: "test-task", + }, + objects: []client.Object{ + &kargoapi.PromotionTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-task", + Namespace: "test-project", + }, + Spec: kargoapi.PromotionTaskSpec{ + Vars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + }, + }, + }, + }, + assertions: func(t *testing.T, result *kargoapi.PromotionTaskSpec, err error) { + require.NoError(t, err) + require.NotNil(t, result) + + assert.Len(t, result.Vars, 1) + assert.Equal(t, "input1", result.Vars[0].Name) + assert.Equal(t, "value1", result.Vars[0].Value) + }, + }, + { + name: "successfully retrieves ClusterPromotionTask", + project: "test-project", + ref: &kargoapi.PromotionTaskReference{ + Kind: "ClusterPromotionTask", + Name: "test-cluster-task", + }, + objects: []client.Object{ + &kargoapi.ClusterPromotionTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cluster-task", + }, + Spec: kargoapi.PromotionTaskSpec{ + Vars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + }, + }, + }, + }, + assertions: func(t *testing.T, result *kargoapi.PromotionTaskSpec, err error) { + require.NoError(t, err) + require.NotNil(t, result) + + assert.Len(t, result.Vars, 1) + assert.Equal(t, "input1", result.Vars[0].Name) + assert.Equal(t, "value1", result.Vars[0].Value) + }, + }, + { + name: "empty kind defaults to PromotionTask", + project: "test-project", + ref: &kargoapi.PromotionTaskReference{ + Kind: "", + Name: "test-task", + }, + objects: []client.Object{ + &kargoapi.PromotionTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-task", + Namespace: "test-project", + }, + Spec: kargoapi.PromotionTaskSpec{ + Vars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "value1"}, + }, + }, + }, + }, + assertions: func(t *testing.T, result *kargoapi.PromotionTaskSpec, err error) { + require.NoError(t, err) + require.NotNil(t, result) + + assert.Len(t, result.Vars, 1) + assert.Equal(t, "input1", result.Vars[0].Name) + assert.Equal(t, "value1", result.Vars[0].Value) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := fake.NewClientBuilder(). + WithScheme(s). + WithObjects(tt.objects...). + WithInterceptorFuncs(tt.interceptor). + Build() + + b := NewPromotionBuilder(c) + result, err := b.getTaskSpec(context.Background(), tt.project, tt.ref) + tt.assertions(t, result, err) + }) + } +} + +func Test_generatePromotionName(t *testing.T) { + tests := []struct { + name string + stageName string + freight string + assertions func(t *testing.T, result string) + }{ + { + name: "standard input lengths", + stageName: "dev", + freight: "abc123def456", + assertions: func(t *testing.T, result string) { + components := strings.Split(result, ".") + assert.Len(t, components, 3) + assert.Equal(t, "dev", components[0]) + assert.Len(t, components[1], ulidLength) + assert.Equal(t, "abc123d", components[2]) + }, + }, + { + name: "short freight", + stageName: "prod", + freight: "abc", + assertions: func(t *testing.T, result string) { + components := strings.Split(result, ".") + assert.Len(t, components, 3) + assert.Equal(t, "prod", components[0]) + assert.Len(t, components[1], ulidLength) + assert.Equal(t, "abc", components[2]) + }, + }, + { + name: "long stage name gets truncated", + // nolint:lll + stageName: "this-is-a-very-long-stage-name-that-exceeds-the-maximum-allowed-length-for-kubernetes-resources-and-should-be-truncated-to-fit-within-the-limits-set-by-the-api-server-which-is-253-characters-including-the-generated-suffix", + freight: "abc123def456", + assertions: func(t *testing.T, result string) { + assert.Equal(t, len(result), 253) // Kubernetes resource name limit + assert.Equal(t, maxStageNamePrefixLength, len(result[:strings.Index(result, ".")])) + }, + }, + { + name: "long freight gets truncated", + stageName: "stage", + freight: "this-is-a-very-long-freight-hash-that-should-be-truncated", + assertions: func(t *testing.T, result string) { + shortHash := result[strings.LastIndex(result, ".")+1:] + assert.Equal(t, shortHashLength, len(shortHash)) + }, + }, + { + name: "all lowercase conversion", + stageName: "DEV-STAGE", + freight: "ABC123DEF456", + assertions: func(t *testing.T, result string) { + assert.Equal(t, "dev-stage", result[:len("dev-stage")]) + assert.Equal(t, "abc123d", result[len(result)-7:]) + }, + }, + { + name: "empty inputs", + stageName: "", + freight: "", + assertions: func(t *testing.T, result string) { + assert.Empty(t, result) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := generatePromotionName(tt.stageName, tt.freight) + tt.assertions(t, result) + }) + } +} + +func Test_generatePromotionTaskStepName(t *testing.T) { + tests := []struct { + name string + taskAlias string + stepAlias string + assertions func(t *testing.T, result string) + }{ + { + name: "standard aliases", + taskAlias: "deploy", + stepAlias: "apply", + assertions: func(t *testing.T, result string) { + assert.Equal(t, "deploy::apply", result) + }, + }, + { + name: "empty task alias", + taskAlias: "", + stepAlias: "apply", + assertions: func(t *testing.T, result string) { + assert.Equal(t, "::apply", result) + }, + }, + { + name: "empty step alias", + taskAlias: "deploy", + stepAlias: "", + assertions: func(t *testing.T, result string) { + assert.Equal(t, "deploy::", result) + }, + }, + { + name: "both aliases empty", + taskAlias: "", + stepAlias: "", + assertions: func(t *testing.T, result string) { + assert.Equal(t, "::", result) + }, + }, + { + name: "aliases with special characters", + taskAlias: "deploy-task", + stepAlias: "apply_config", + assertions: func(t *testing.T, result string) { + assert.Equal(t, "deploy-task::apply_config", result) + }, + }, + { + name: "aliases containing separator", + taskAlias: "deploy::task", + stepAlias: "apply::config", + assertions: func(t *testing.T, result string) { + assert.Equal(t, "deploy::task::apply::config", result) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := generatePromotionTaskStepAlias(tt.taskAlias, tt.stepAlias) + tt.assertions(t, result) + }) + } +} + +func Test_promotionTaskVarsToStepVars(t *testing.T) { + tests := []struct { + name string + taskVars []kargoapi.PromotionVariable + promoVars []kargoapi.PromotionVariable + stepVars []kargoapi.PromotionVariable + assertions func(t *testing.T, result []kargoapi.PromotionVariable, err error) + }{ + { + name: "nil inputs returns nil map and no error", + taskVars: nil, + stepVars: nil, + assertions: func(t *testing.T, result []kargoapi.PromotionVariable, err error) { + require.NoError(t, err) + assert.Nil(t, result) + }, + }, + { + name: "empty inputs returns nil map and no error", + taskVars: []kargoapi.PromotionVariable{}, + stepVars: nil, + assertions: func(t *testing.T, result []kargoapi.PromotionVariable, err error) { + require.NoError(t, err) + assert.Nil(t, result) + }, + }, + { + name: "missing required variable returns error", + taskVars: []kargoapi.PromotionVariable{ + {Name: "input1"}, + }, + stepVars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: ""}, + }, + assertions: func(t *testing.T, result []kargoapi.PromotionVariable, err error) { + assert.ErrorContains(t, err, "missing value for variable \"input1\"") + assert.Nil(t, result) + }, + }, + { + name: "default value used when config value not provided", + taskVars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "default1"}, + }, + stepVars: nil, + assertions: func(t *testing.T, result []kargoapi.PromotionVariable, err error) { + require.NoError(t, err) + assert.ElementsMatch(t, []kargoapi.PromotionVariable{ + {Name: "input1", Value: "default1"}, + }, result) + }, + }, + { + name: "step value overrides default value", + taskVars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "default1"}, + }, + stepVars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "override1"}, + }, + assertions: func(t *testing.T, result []kargoapi.PromotionVariable, err error) { + require.NoError(t, err) + assert.ElementsMatch(t, []kargoapi.PromotionVariable{ + {Name: "input1", Value: "override1"}, + }, result) + }, + }, + { + name: "promotion variable overrides default value", + taskVars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "default1"}, + }, + promoVars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "override1"}, + }, + stepVars: nil, + assertions: func(t *testing.T, result []kargoapi.PromotionVariable, err error) { + require.NoError(t, err) + // Variable is set by engine at runtime + assert.Empty(t, result) + }, + }, + { + name: "multiple inputs processed correctly", + taskVars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "default1"}, + {Name: "input2", Value: "default2"}, + {Name: "input3"}, + }, + stepVars: []kargoapi.PromotionVariable{ + {Name: "input1", Value: "override1"}, + {Name: "input3", Value: "value3"}, + }, + assertions: func(t *testing.T, result []kargoapi.PromotionVariable, err error) { + require.NoError(t, err) + assert.ElementsMatch(t, []kargoapi.PromotionVariable{ + {Name: "input1", Value: "override1"}, + {Name: "input2", Value: "default2"}, + {Name: "input3", Value: "value3"}, + }, result) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := promotionTaskVarsToStepVars(tt.taskVars, tt.promoVars, tt.stepVars) + tt.assertions(t, result, err) + }) + } +} diff --git a/ui/src/features/stage/create-stage.tsx b/ui/src/features/stage/create-stage.tsx index 1bebcc210..c01ab74ff 100644 --- a/ui/src/features/stage/create-stage.tsx +++ b/ui/src/features/stage/create-stage.tsx @@ -123,7 +123,8 @@ export const CreateStage = ({ promotionWizardStepsState.state?.map((step) => ({ uses: step?.identifier, as: step?.as, - config: step?.state + config: step?.state, + vars: [] })) ); setValue('value', unmarshalled); @@ -174,7 +175,8 @@ export const CreateStage = ({ promotionWizardStepsState.state?.map((step) => ({ uses: step?.identifier, as: step?.as, - config: step?.state + config: step?.state, + vars: [] })) ) ); diff --git a/ui/src/features/stage/promotion-steps-wizard/use-promotion-wizard-steps-state.ts b/ui/src/features/stage/promotion-steps-wizard/use-promotion-wizard-steps-state.ts index fb0a93d44..b3f1d1c81 100644 --- a/ui/src/features/stage/promotion-steps-wizard/use-promotion-wizard-steps-state.ts +++ b/ui/src/features/stage/promotion-steps-wizard/use-promotion-wizard-steps-state.ts @@ -79,7 +79,8 @@ const stateToYAML = (state: RunnerWithConfiguration[]): string => { promotionSteps.push({ uses: step.identifier, config: step.state, - as: step.as + as: step.as, + vars: [] }); } diff --git a/ui/src/gen/directives/compose-output.json b/ui/src/gen/directives/compose-output.json new file mode 100644 index 000000000..b168b74f6 --- /dev/null +++ b/ui/src/gen/directives/compose-output.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "ComposeOutput", + "type": "object", + "minProperties": 1 +} \ No newline at end of file diff --git a/ui/src/gen/schema/clusterpromotiontasks.kargo.akuity.io_v1alpha1.json b/ui/src/gen/schema/clusterpromotiontasks.kargo.akuity.io_v1alpha1.json new file mode 100644 index 000000000..c774fdb02 --- /dev/null +++ b/ui/src/gen/schema/clusterpromotiontasks.kargo.akuity.io_v1alpha1.json @@ -0,0 +1,146 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to.\nCannot be updated.\nIn CamelCase.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "type": "object" + }, + "spec": { + "description": "Spec describes the desired transition of a specific Stage into a specific\nFreight.", + "properties": { + "steps": { + "description": "Steps specifies the directives to be executed as part of this\nPromotionTask. The steps as defined here are inflated into a\nPromotion when it is built from a PromotionTemplate.", + "items": { + "description": "PromotionStep describes a directive to be executed as part of a Promotion.", + "properties": { + "as": { + "description": "As is the alias this step can be referred to as.", + "type": "string" + }, + "config": { + "description": "Config is opaque configuration for the PromotionStep that is understood\nonly by each PromotionStep's implementation. It is legal to utilize\nexpressions in defining values at any level of this block.\nSee https://docs.kargo.io/references/expression-language for details.", + "x-kubernetes-preserve-unknown-fields": true + }, + "retry": { + "description": "Retry is the retry policy for this step.", + "properties": { + "errorThreshold": { + "description": "ErrorThreshold is the number of consecutive times the step must fail (for\nany reason) before retries are abandoned and the entire Promotion is marked\nas failed.\n\nIf this field is set to 0, the effective default will be a step-specific\none. If no step-specific default exists (i.e. is also 0), the effective\ndefault will be the system-wide default of 1.\n\nA value of 1 will cause the Promotion to be marked as failed after just\na single failure; i.e. no retries will be attempted.\n\nThere is no option to specify an infinite number of retries using a value\nsuch as -1.\n\nIn a future release, Kargo is likely to become capable of distinguishing\nbetween recoverable and non-recoverable step failures. At that time, it is\nplanned that unrecoverable failures will not be subject to this threshold\nand will immediately cause the Promotion to be marked as failed without\nfurther condition.", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "timeout": { + "description": "Timeout is the soft maximum interval in which a step that returns a Running\nstatus (which typically indicates it's waiting for something to happen)\nmay be retried.\n\nThe maximum is a soft one because the check for whether the interval has\nelapsed occurs AFTER the step has run. This effectively means a step may\nrun ONCE beyond the close of the interval.\n\nIf this field is set to nil, the effective default will be a step-specific\none. If no step-specific default exists (i.e. is also nil), the effective\ndefault will be the system-wide default of 0.\n\nA value of 0 will cause the step to be retried indefinitely unless the\nErrorThreshold is reached.", + "type": "string" + } + }, + "type": "object" + }, + "task": { + "description": "Task is a reference to a PromotionTask that should be inflated into a\nPromotion when it is built from a PromotionTemplate.", + "properties": { + "kind": { + "description": "Kind is the type of the PromotionTask. Can be either PromotionTask or\nClusterPromotionTask, default is PromotionTask.", + "enum": [ + "PromotionTask", + "ClusterPromotionTask" + ], + "type": "string" + }, + "name": { + "description": "Name is the name of the (Cluster)PromotionTask.", + "maxLength": 253, + "minLength": 1, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "uses": { + "description": "Uses identifies a runner that can execute this step.", + "minLength": 1, + "type": "string" + }, + "vars": { + "description": "Vars is a list of variables that can be referenced by expressions in\nthe step's Config. The values override the values specified in the\nPromotionSpec.", + "items": { + "description": "PromotionVariable describes a single variable that may be referenced by\nexpressions in promotion steps.", + "properties": { + "name": { + "description": "Name is the name of the variable.", + "minLength": 1, + "pattern": "^[a-zA-Z_]\\w*$", + "type": "string" + }, + "value": { + "description": "Value is the value of the variable. It is allowed to utilize expressions\nin the value.\nSee https://docs.kargo.io/references/expression-language for details.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object", + "x-kubernetes-validations": [ + { + "message": "PromotionTask step must have uses set and must not reference another task", + "rule": "has(self.uses) && !has(self.task)" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "vars": { + "description": "Vars specifies the variables available to the PromotionTask. The\nvalues of these variables are the default values that can be\noverridden by the step referencing the task.", + "items": { + "description": "PromotionVariable describes a single variable that may be referenced by\nexpressions in promotion steps.", + "properties": { + "name": { + "description": "Name is the name of the variable.", + "minLength": 1, + "pattern": "^[a-zA-Z_]\\w*$", + "type": "string" + }, + "value": { + "description": "Value is the value of the variable. It is allowed to utilize expressions\nin the value.\nSee https://docs.kargo.io/references/expression-language for details.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "steps" + ], + "type": "object" + } + }, + "required": [ + "spec" + ], + "type": "object" +} \ No newline at end of file diff --git a/ui/src/gen/schema/promotions.kargo.akuity.io_v1alpha1.json b/ui/src/gen/schema/promotions.kargo.akuity.io_v1alpha1.json index c28cf84a2..db3a72a8d 100644 --- a/ui/src/gen/schema/promotions.kargo.akuity.io_v1alpha1.json +++ b/ui/src/gen/schema/promotions.kargo.akuity.io_v1alpha1.json @@ -18,11 +18,14 @@ "properties": { "freight": { "description": "Freight specifies the piece of Freight to be promoted into the Stage\nreferenced by the Stage field.", + "maxLength": 253, "minLength": 1, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", "type": "string" }, "stage": { "description": "Stage specifies the name of the Stage to which this Promotion\napplies. The Stage referenced by this field MUST be in the same\nnamespace as the Promotion.", + "maxLength": 253, "minLength": 1, "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", "type": "string" @@ -57,17 +60,68 @@ }, "type": "object" }, + "task": { + "description": "Task is a reference to a PromotionTask that should be inflated into a\nPromotion when it is built from a PromotionTemplate.", + "properties": { + "kind": { + "description": "Kind is the type of the PromotionTask. Can be either PromotionTask or\nClusterPromotionTask, default is PromotionTask.", + "enum": [ + "PromotionTask", + "ClusterPromotionTask" + ], + "type": "string" + }, + "name": { + "description": "Name is the name of the (Cluster)PromotionTask.", + "maxLength": 253, + "minLength": 1, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, "uses": { "description": "Uses identifies a runner that can execute this step.", "minLength": 1, "type": "string" + }, + "vars": { + "description": "Vars is a list of variables that can be referenced by expressions in\nthe step's Config. The values override the values specified in the\nPromotionSpec.", + "items": { + "description": "PromotionVariable describes a single variable that may be referenced by\nexpressions in promotion steps.", + "properties": { + "name": { + "description": "Name is the name of the variable.", + "minLength": 1, + "pattern": "^[a-zA-Z_]\\w*$", + "type": "string" + }, + "value": { + "description": "Value is the value of the variable. It is allowed to utilize expressions\nin the value.\nSee https://docs.kargo.io/references/expression-language for details.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" } }, - "required": [ - "uses" - ], - "type": "object" + "type": "object", + "x-kubernetes-validations": [ + { + "message": "Promotion step must have uses set and must not reference a task", + "rule": "has(self.uses) && !has(self.task)" + } + ] }, + "minItems": 1, "type": "array" }, "vars": { @@ -87,8 +141,7 @@ } }, "required": [ - "name", - "value" + "name" ], "type": "object" }, @@ -97,7 +150,8 @@ }, "required": [ "freight", - "stage" + "stage", + "steps" ], "type": "object" }, diff --git a/ui/src/gen/schema/promotiontasks.kargo.akuity.io_v1alpha1.json b/ui/src/gen/schema/promotiontasks.kargo.akuity.io_v1alpha1.json new file mode 100644 index 000000000..1741088e3 --- /dev/null +++ b/ui/src/gen/schema/promotiontasks.kargo.akuity.io_v1alpha1.json @@ -0,0 +1,146 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to.\nCannot be updated.\nIn CamelCase.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "type": "object" + }, + "spec": { + "description": "Spec describes the composition of a PromotionTask, including the\nvariables available to the task and the steps.", + "properties": { + "steps": { + "description": "Steps specifies the directives to be executed as part of this\nPromotionTask. The steps as defined here are inflated into a\nPromotion when it is built from a PromotionTemplate.", + "items": { + "description": "PromotionStep describes a directive to be executed as part of a Promotion.", + "properties": { + "as": { + "description": "As is the alias this step can be referred to as.", + "type": "string" + }, + "config": { + "description": "Config is opaque configuration for the PromotionStep that is understood\nonly by each PromotionStep's implementation. It is legal to utilize\nexpressions in defining values at any level of this block.\nSee https://docs.kargo.io/references/expression-language for details.", + "x-kubernetes-preserve-unknown-fields": true + }, + "retry": { + "description": "Retry is the retry policy for this step.", + "properties": { + "errorThreshold": { + "description": "ErrorThreshold is the number of consecutive times the step must fail (for\nany reason) before retries are abandoned and the entire Promotion is marked\nas failed.\n\nIf this field is set to 0, the effective default will be a step-specific\none. If no step-specific default exists (i.e. is also 0), the effective\ndefault will be the system-wide default of 1.\n\nA value of 1 will cause the Promotion to be marked as failed after just\na single failure; i.e. no retries will be attempted.\n\nThere is no option to specify an infinite number of retries using a value\nsuch as -1.\n\nIn a future release, Kargo is likely to become capable of distinguishing\nbetween recoverable and non-recoverable step failures. At that time, it is\nplanned that unrecoverable failures will not be subject to this threshold\nand will immediately cause the Promotion to be marked as failed without\nfurther condition.", + "format": "int32", + "maximum": 2147483647, + "minimum": -2147483648, + "type": "integer" + }, + "timeout": { + "description": "Timeout is the soft maximum interval in which a step that returns a Running\nstatus (which typically indicates it's waiting for something to happen)\nmay be retried.\n\nThe maximum is a soft one because the check for whether the interval has\nelapsed occurs AFTER the step has run. This effectively means a step may\nrun ONCE beyond the close of the interval.\n\nIf this field is set to nil, the effective default will be a step-specific\none. If no step-specific default exists (i.e. is also nil), the effective\ndefault will be the system-wide default of 0.\n\nA value of 0 will cause the step to be retried indefinitely unless the\nErrorThreshold is reached.", + "type": "string" + } + }, + "type": "object" + }, + "task": { + "description": "Task is a reference to a PromotionTask that should be inflated into a\nPromotion when it is built from a PromotionTemplate.", + "properties": { + "kind": { + "description": "Kind is the type of the PromotionTask. Can be either PromotionTask or\nClusterPromotionTask, default is PromotionTask.", + "enum": [ + "PromotionTask", + "ClusterPromotionTask" + ], + "type": "string" + }, + "name": { + "description": "Name is the name of the (Cluster)PromotionTask.", + "maxLength": 253, + "minLength": 1, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "uses": { + "description": "Uses identifies a runner that can execute this step.", + "minLength": 1, + "type": "string" + }, + "vars": { + "description": "Vars is a list of variables that can be referenced by expressions in\nthe step's Config. The values override the values specified in the\nPromotionSpec.", + "items": { + "description": "PromotionVariable describes a single variable that may be referenced by\nexpressions in promotion steps.", + "properties": { + "name": { + "description": "Name is the name of the variable.", + "minLength": 1, + "pattern": "^[a-zA-Z_]\\w*$", + "type": "string" + }, + "value": { + "description": "Value is the value of the variable. It is allowed to utilize expressions\nin the value.\nSee https://docs.kargo.io/references/expression-language for details.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" + } + }, + "type": "object", + "x-kubernetes-validations": [ + { + "message": "PromotionTask step must have uses set and must not reference another task", + "rule": "has(self.uses) && !has(self.task)" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "vars": { + "description": "Vars specifies the variables available to the PromotionTask. The\nvalues of these variables are the default values that can be\noverridden by the step referencing the task.", + "items": { + "description": "PromotionVariable describes a single variable that may be referenced by\nexpressions in promotion steps.", + "properties": { + "name": { + "description": "Name is the name of the variable.", + "minLength": 1, + "pattern": "^[a-zA-Z_]\\w*$", + "type": "string" + }, + "value": { + "description": "Value is the value of the variable. It is allowed to utilize expressions\nin the value.\nSee https://docs.kargo.io/references/expression-language for details.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "steps" + ], + "type": "object" + } + }, + "required": [ + "spec" + ], + "type": "object" +} \ No newline at end of file diff --git a/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json b/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json index c912502af..0c2b1f77c 100644 --- a/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json +++ b/ui/src/gen/schema/stages.kargo.akuity.io_v1alpha1.json @@ -52,16 +52,66 @@ }, "type": "object" }, + "task": { + "description": "Task is a reference to a PromotionTask that should be inflated into a\nPromotion when it is built from a PromotionTemplate.", + "properties": { + "kind": { + "description": "Kind is the type of the PromotionTask. Can be either PromotionTask or\nClusterPromotionTask, default is PromotionTask.", + "enum": [ + "PromotionTask", + "ClusterPromotionTask" + ], + "type": "string" + }, + "name": { + "description": "Name is the name of the (Cluster)PromotionTask.", + "maxLength": 253, + "minLength": 1, + "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, "uses": { "description": "Uses identifies a runner that can execute this step.", "minLength": 1, "type": "string" + }, + "vars": { + "description": "Vars is a list of variables that can be referenced by expressions in\nthe step's Config. The values override the values specified in the\nPromotionSpec.", + "items": { + "description": "PromotionVariable describes a single variable that may be referenced by\nexpressions in promotion steps.", + "properties": { + "name": { + "description": "Name is the name of the variable.", + "minLength": 1, + "pattern": "^[a-zA-Z_]\\w*$", + "type": "string" + }, + "value": { + "description": "Value is the value of the variable. It is allowed to utilize expressions\nin the value.\nSee https://docs.kargo.io/references/expression-language for details.", + "type": "string" + } + }, + "required": [ + "name" + ], + "type": "object" + }, + "type": "array" } }, - "required": [ - "uses" - ], - "type": "object" + "type": "object", + "x-kubernetes-validations": [ + { + "message": "PromotionTemplate step must have exactly one of uses or task set", + "rule": "(has(self.uses) ? !has(self.task) : has(self.task))" + } + ] }, "minItems": 1, "type": "array" @@ -83,8 +133,7 @@ } }, "required": [ - "name", - "value" + "name" ], "type": "object" }, diff --git a/ui/src/gen/v1alpha1/generated_pb.ts b/ui/src/gen/v1alpha1/generated_pb.ts index 343747c23..3a354e439 100644 --- a/ui/src/gen/v1alpha1/generated_pb.ts +++ b/ui/src/gen/v1alpha1/generated_pb.ts @@ -648,6 +648,99 @@ export class ChartSubscription extends Message { } } +/** + * @generated from message github.com.akuity.kargo.api.v1alpha1.ClusterPromotionTask + */ +export class ClusterPromotionTask extends Message { + /** + * @generated from field: optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + */ + metadata?: ObjectMeta; + + /** + * Spec describes the desired transition of a specific Stage into a specific + * Freight. + * + * +kubebuilder:validation:Required + * + * @generated from field: optional github.com.akuity.kargo.api.v1alpha1.PromotionTaskSpec spec = 2; + */ + spec?: PromotionTaskSpec; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "github.com.akuity.kargo.api.v1alpha1.ClusterPromotionTask"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "metadata", kind: "message", T: ObjectMeta, opt: true }, + { no: 2, name: "spec", kind: "message", T: PromotionTaskSpec, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): ClusterPromotionTask { + return new ClusterPromotionTask().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): ClusterPromotionTask { + return new ClusterPromotionTask().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): ClusterPromotionTask { + return new ClusterPromotionTask().fromJsonString(jsonString, options); + } + + static equals(a: ClusterPromotionTask | PlainMessage | undefined, b: ClusterPromotionTask | PlainMessage | undefined): boolean { + return proto2.util.equals(ClusterPromotionTask, a, b); + } +} + +/** + * ClusterPromotionTaskList contains a list of PromotionTasks. + * + * @generated from message github.com.akuity.kargo.api.v1alpha1.ClusterPromotionTaskList + */ +export class ClusterPromotionTaskList extends Message { + /** + * @generated from field: optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; + */ + metadata?: ListMeta; + + /** + * @generated from field: repeated github.com.akuity.kargo.api.v1alpha1.ClusterPromotionTask items = 2; + */ + items: ClusterPromotionTask[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "github.com.akuity.kargo.api.v1alpha1.ClusterPromotionTaskList"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "metadata", kind: "message", T: ListMeta, opt: true }, + { no: 2, name: "items", kind: "message", T: ClusterPromotionTask, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): ClusterPromotionTaskList { + return new ClusterPromotionTaskList().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): ClusterPromotionTaskList { + return new ClusterPromotionTaskList().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): ClusterPromotionTaskList { + return new ClusterPromotionTaskList().fromJsonString(jsonString, options); + } + + static equals(a: ClusterPromotionTaskList | PlainMessage | undefined, b: ClusterPromotionTaskList | PlainMessage | undefined): boolean { + return proto2.util.equals(ClusterPromotionTaskList, a, b); + } +} + /** * DiscoveredArtifacts holds the artifacts discovered by the Warehouse for its * subscriptions. @@ -2628,7 +2721,9 @@ export class PromotionSpec extends Message { * applies. The Stage referenced by this field MUST be in the same * namespace as the Promotion. * + * +kubebuilder:validation:Required * +kubebuilder:validation:MinLength=1 + * +kubebuilder:validation:MaxLength=253 * +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ * * @generated from field: optional string stage = 1; @@ -2639,7 +2734,10 @@ export class PromotionSpec extends Message { * Freight specifies the piece of Freight to be promoted into the Stage * referenced by the Stage field. * + * +kubebuilder:validation:Required * +kubebuilder:validation:MinLength=1 + * +kubebuilder:validation:MaxLength=253 + * +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ * * @generated from field: optional string freight = 2; */ @@ -2658,6 +2756,10 @@ export class PromotionSpec extends Message { * The order in which the directives are executed is the order in which they * are listed in this field. * + * +kubebuilder:validation:Required + * +kubebuilder:validation:MinItems=1 + * +kubebuilder:validation:items:XValidation:message="Promotion step must have uses set and must not reference a task",rule="has(self.uses) && !has(self.task)" + * * @generated from field: repeated github.com.akuity.kargo.api.v1alpha1.PromotionStep steps = 3; */ steps: PromotionStep[] = []; @@ -2829,12 +2931,21 @@ export class PromotionStep extends Message { /** * Uses identifies a runner that can execute this step. * + * +kubebuilder:validation:Optional * +kubebuilder:validation:MinLength=1 * * @generated from field: optional string uses = 1; */ uses?: string; + /** + * Task is a reference to a PromotionTask that should be inflated into a + * Promotion when it is built from a PromotionTemplate. + * + * @generated from field: optional github.com.akuity.kargo.api.v1alpha1.PromotionTaskReference task = 5; + */ + task?: PromotionTaskReference; + /** * As is the alias this step can be referred to as. * @@ -2849,6 +2960,15 @@ export class PromotionStep extends Message { */ retry?: PromotionStepRetry; + /** + * Vars is a list of variables that can be referenced by expressions in + * the step's Config. The values override the values specified in the + * PromotionSpec. + * + * @generated from field: repeated github.com.akuity.kargo.api.v1alpha1.PromotionVariable vars = 6; + */ + vars: PromotionVariable[] = []; + /** * Config is opaque configuration for the PromotionStep that is understood * only by each PromotionStep's implementation. It is legal to utilize @@ -2868,8 +2988,10 @@ export class PromotionStep extends Message { static readonly typeName = "github.com.akuity.kargo.api.v1alpha1.PromotionStep"; static readonly fields: FieldList = proto2.util.newFieldList(() => [ { no: 1, name: "uses", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 5, name: "task", kind: "message", T: PromotionTaskReference, opt: true }, { no: 2, name: "as", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, { no: 4, name: "retry", kind: "message", T: PromotionStepRetry, opt: true }, + { no: 6, name: "vars", kind: "message", T: PromotionVariable, repeated: true }, { no: 3, name: "config", kind: "message", T: JSON, opt: true }, ]); @@ -2970,6 +3092,212 @@ export class PromotionStepRetry extends Message { } } +/** + * @generated from message github.com.akuity.kargo.api.v1alpha1.PromotionTask + */ +export class PromotionTask extends Message { + /** + * @generated from field: optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; + */ + metadata?: ObjectMeta; + + /** + * Spec describes the composition of a PromotionTask, including the + * variables available to the task and the steps. + * + * +kubebuilder:validation:Required + * + * @generated from field: optional github.com.akuity.kargo.api.v1alpha1.PromotionTaskSpec spec = 2; + */ + spec?: PromotionTaskSpec; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "github.com.akuity.kargo.api.v1alpha1.PromotionTask"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "metadata", kind: "message", T: ObjectMeta, opt: true }, + { no: 2, name: "spec", kind: "message", T: PromotionTaskSpec, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): PromotionTask { + return new PromotionTask().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): PromotionTask { + return new PromotionTask().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): PromotionTask { + return new PromotionTask().fromJsonString(jsonString, options); + } + + static equals(a: PromotionTask | PlainMessage | undefined, b: PromotionTask | PlainMessage | undefined): boolean { + return proto2.util.equals(PromotionTask, a, b); + } +} + +/** + * PromotionTaskList contains a list of PromotionTasks. + * + * @generated from message github.com.akuity.kargo.api.v1alpha1.PromotionTaskList + */ +export class PromotionTaskList extends Message { + /** + * @generated from field: optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; + */ + metadata?: ListMeta; + + /** + * @generated from field: repeated github.com.akuity.kargo.api.v1alpha1.PromotionTask items = 2; + */ + items: PromotionTask[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "github.com.akuity.kargo.api.v1alpha1.PromotionTaskList"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "metadata", kind: "message", T: ListMeta, opt: true }, + { no: 2, name: "items", kind: "message", T: PromotionTask, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): PromotionTaskList { + return new PromotionTaskList().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): PromotionTaskList { + return new PromotionTaskList().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): PromotionTaskList { + return new PromotionTaskList().fromJsonString(jsonString, options); + } + + static equals(a: PromotionTaskList | PlainMessage | undefined, b: PromotionTaskList | PlainMessage | undefined): boolean { + return proto2.util.equals(PromotionTaskList, a, b); + } +} + +/** + * PromotionTaskReference describes a reference to a PromotionTask. + * + * @generated from message github.com.akuity.kargo.api.v1alpha1.PromotionTaskReference + */ +export class PromotionTaskReference extends Message { + /** + * Name is the name of the (Cluster)PromotionTask. + * + * +kubebuilder:validation:Required + * +kubebuilder:validation:MinLength=1 + * +kubebuilder:validation:MaxLength=253 + * +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + * + * @generated from field: optional string name = 1; + */ + name?: string; + + /** + * Kind is the type of the PromotionTask. Can be either PromotionTask or + * ClusterPromotionTask, default is PromotionTask. + * + * +kubebuilder:validation:Optional + * +kubebuilder:validation:Enum=PromotionTask;ClusterPromotionTask + * + * @generated from field: optional string kind = 2; + */ + kind?: string; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "github.com.akuity.kargo.api.v1alpha1.PromotionTaskReference"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + { no: 2, name: "kind", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): PromotionTaskReference { + return new PromotionTaskReference().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): PromotionTaskReference { + return new PromotionTaskReference().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): PromotionTaskReference { + return new PromotionTaskReference().fromJsonString(jsonString, options); + } + + static equals(a: PromotionTaskReference | PlainMessage | undefined, b: PromotionTaskReference | PlainMessage | undefined): boolean { + return proto2.util.equals(PromotionTaskReference, a, b); + } +} + +/** + * @generated from message github.com.akuity.kargo.api.v1alpha1.PromotionTaskSpec + */ +export class PromotionTaskSpec extends Message { + /** + * Vars specifies the variables available to the PromotionTask. The + * values of these variables are the default values that can be + * overridden by the step referencing the task. + * + * @generated from field: repeated github.com.akuity.kargo.api.v1alpha1.PromotionVariable vars = 1; + */ + vars: PromotionVariable[] = []; + + /** + * Steps specifies the directives to be executed as part of this + * PromotionTask. The steps as defined here are inflated into a + * Promotion when it is built from a PromotionTemplate. + * + * +kubebuilder:validation:Required + * +kubebuilder:validation:MinItems=1 + * +kubebuilder:validation:items:XValidation:message="PromotionTask step must have uses set and must not reference another task",rule="has(self.uses) && !has(self.task)" + * + * @generated from field: repeated github.com.akuity.kargo.api.v1alpha1.PromotionStep steps = 2; + */ + steps: PromotionStep[] = []; + + constructor(data?: PartialMessage) { + super(); + proto2.util.initPartial(data, this); + } + + static readonly runtime: typeof proto2 = proto2; + static readonly typeName = "github.com.akuity.kargo.api.v1alpha1.PromotionTaskSpec"; + static readonly fields: FieldList = proto2.util.newFieldList(() => [ + { no: 1, name: "vars", kind: "message", T: PromotionVariable, repeated: true }, + { no: 2, name: "steps", kind: "message", T: PromotionStep, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): PromotionTaskSpec { + return new PromotionTaskSpec().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): PromotionTaskSpec { + return new PromotionTaskSpec().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): PromotionTaskSpec { + return new PromotionTaskSpec().fromJsonString(jsonString, options); + } + + static equals(a: PromotionTaskSpec | PlainMessage | undefined, b: PromotionTaskSpec | PlainMessage | undefined): boolean { + return proto2.util.equals(PromotionTaskSpec, a, b); + } +} + /** * PromotionTemplate defines a template for a Promotion that can be used to * incorporate Freight into a Stage. @@ -3032,6 +3360,7 @@ export class PromotionTemplateSpec extends Message { * are listed in this field. * * +kubebuilder:validation:MinItems=1 + * +kubebuilder:validation:items:XValidation:message="PromotionTemplate step must have exactly one of uses or task set",rule="(has(self.uses) ? !has(self.task) : has(self.task))" * * @generated from field: repeated github.com.akuity.kargo.api.v1alpha1.PromotionStep steps = 1; */