diff --git a/PROJECT b/PROJECT index 1b7d6ba..36a1d4c 100644 --- a/PROJECT +++ b/PROJECT @@ -1,3 +1,7 @@ +# Code generated by tool. DO NOT EDIT. +# This file is used to track the info used to scaffold your project +# and allow the plugins properly work. +# More info: https://book.kubebuilder.io/reference/project-config.html domain: kruise.io layout: - go.kubebuilder.io/v3 @@ -21,4 +25,64 @@ resources: kind: BatchRelease path: github.com/openkruise/rollouts/api/v1alpha1 version: v1alpha1 +- api: + crdVersion: v1 + namespaced: true + domain: kruise.io + group: rollouts + kind: RolloutHistory + path: github.com/openkruise/rollouts/api/v1alpha1 + version: v1alpha1 +- api: + crdVersion: v1 + namespaced: true + domain: kruise.io + group: rollouts + kind: TrafficRouting + path: github.com/openkruise/rollouts/api/v1alpha1 + version: v1alpha1 +- api: + crdVersion: v1 + namespaced: true + domain: kruise.io + group: rollouts + kind: Rollout + path: github.com/openkruise/rollouts/api/v1beta1 + version: v1beta1 + webhooks: + conversion: true + webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + domain: kruise.io + group: rollouts + kind: TrafficRouting + path: github.com/openkruise/rollouts/api/v1beta1 + version: v1beta1 + webhooks: + conversion: true + webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + domain: kruise.io + group: rollouts + kind: BatchRelease + path: github.com/openkruise/rollouts/api/v1beta1 + version: v1beta1 + webhooks: + conversion: true + webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + domain: kruise.io + group: rollouts + kind: RolloutHistory + path: github.com/openkruise/rollouts/api/v1beta1 + version: v1beta1 + webhooks: + conversion: true + webhookVersion: v1 version: "3" diff --git a/api/addtoscheme_v1beta1.go b/api/addtoscheme_v1beta1.go new file mode 100644 index 0000000..302d44c --- /dev/null +++ b/api/addtoscheme_v1beta1.go @@ -0,0 +1,24 @@ +/* +Copyright 2019 The Kruise Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apis + +import "github.com/openkruise/rollouts/api/v1beta1" + +func init() { + // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back + AddToSchemes = append(AddToSchemes, v1beta1.SchemeBuilder.AddToScheme) +} diff --git a/api/v1alpha1/batchrelease_conversion.go b/api/v1alpha1/batchrelease_conversion.go new file mode 100644 index 0000000..eb7638f --- /dev/null +++ b/api/v1alpha1/batchrelease_conversion.go @@ -0,0 +1,132 @@ +package v1alpha1 + +import ( + "fmt" + + "github.com/openkruise/rollouts/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +func (src *BatchRelease) ConvertTo(dstRaw conversion.Hub) error { + switch t := dstRaw.(type) { + case *v1beta1.BatchRelease: + dst := dstRaw.(*v1beta1.BatchRelease) + dst.ObjectMeta = src.ObjectMeta + + // batchrelease spec conversion + dst.Spec.TargetRef.WorkloadRef = &v1beta1.WorkloadRef{ + APIVersion: src.Spec.TargetRef.WorkloadRef.APIVersion, + Kind: src.Spec.TargetRef.WorkloadRef.Kind, + Name: src.Spec.TargetRef.WorkloadRef.Name, + } + batches := make([]v1beta1.ReleaseBatch, len(src.Spec.ReleasePlan.Batches)) + for i, v := range src.Spec.ReleasePlan.Batches { + batches[i].CanaryReplicas = v.CanaryReplicas + } + dst.Spec.ReleasePlan = v1beta1.ReleasePlan{ + Batches: batches, + BatchPartition: src.Spec.ReleasePlan.BatchPartition, + RolloutID: src.Spec.ReleasePlan.RolloutID, + FailureThreshold: src.Spec.ReleasePlan.FailureThreshold, + FinalizingPolicy: v1beta1.FinalizingPolicyType(src.Spec.ReleasePlan.FinalizingPolicy), + PatchPodTemplateMetadata: (*v1beta1.PatchPodTemplateMetadata)(src.Spec.ReleasePlan.PatchPodTemplateMetadata), + } + + // batchrelease status conversion + conditions := make([]v1beta1.RolloutCondition, len(src.Status.Conditions)) + for i, v := range src.Status.Conditions { + conditions[i] = v1beta1.RolloutCondition{ + Type: v1beta1.RolloutConditionType(v.Type), + Status: v.Status, + LastUpdateTime: v.LastUpdateTime, + LastTransitionTime: v.LastTransitionTime, + Reason: v.Reason, + Message: v.Message, + } + } + dst.Status = v1beta1.BatchReleaseStatus{ + Conditions: conditions, + CanaryStatus: v1beta1.BatchReleaseCanaryStatus{ + CurrentBatchState: v1beta1.BatchReleaseBatchStateType(src.Status.CanaryStatus.CurrentBatchState), + CurrentBatch: src.Status.CanaryStatus.CurrentBatch, + BatchReadyTime: src.Status.CanaryStatus.BatchReadyTime, + UpdatedReplicas: src.Status.CanaryStatus.UpdatedReplicas, + UpdatedReadyReplicas: src.Status.CanaryStatus.UpdatedReadyReplicas, + NoNeedUpdateReplicas: src.Status.CanaryStatus.NoNeedUpdateReplicas, + }, + StableRevision: src.Status.StableRevision, + UpdateRevision: src.Status.UpdateRevision, + ObservedGeneration: src.Status.ObservedGeneration, + ObservedRolloutID: src.Status.ObservedRolloutID, + ObservedWorkloadReplicas: src.Status.ObservedWorkloadReplicas, + CollisionCount: src.Status.CollisionCount, + ObservedReleasePlanHash: src.Status.ObservedReleasePlanHash, + Phase: v1beta1.RolloutPhase(src.Status.Phase), + } + default: + return fmt.Errorf("unsupported type %v", t) + } + return nil +} + +func (dst *BatchRelease) ConvertFrom(srcRaw conversion.Hub) error { + switch t := srcRaw.(type) { + case *v1beta1.BatchRelease: + src := srcRaw.(*v1beta1.BatchRelease) + dst.ObjectMeta = src.ObjectMeta + + // batchrelease spec conversion + dst.Spec.TargetRef.WorkloadRef = &WorkloadRef{ + APIVersion: src.Spec.TargetRef.WorkloadRef.APIVersion, + Kind: src.Spec.TargetRef.WorkloadRef.Kind, + Name: src.Spec.TargetRef.WorkloadRef.Name, + } + batches := make([]ReleaseBatch, len(src.Spec.ReleasePlan.Batches)) + for i, v := range src.Spec.ReleasePlan.Batches { + batches[i].CanaryReplicas = v.CanaryReplicas + } + dst.Spec.ReleasePlan = ReleasePlan{ + Batches: batches, + BatchPartition: src.Spec.ReleasePlan.BatchPartition, + RolloutID: src.Spec.ReleasePlan.RolloutID, + FailureThreshold: src.Spec.ReleasePlan.FailureThreshold, + FinalizingPolicy: FinalizingPolicyType(src.Spec.ReleasePlan.FinalizingPolicy), + PatchPodTemplateMetadata: (*PatchPodTemplateMetadata)(src.Spec.ReleasePlan.PatchPodTemplateMetadata), + } + + // batchrelease status conversion + conditions := make([]RolloutCondition, len(src.Status.Conditions)) + for i, v := range src.Status.Conditions { + conditions[i] = RolloutCondition{ + Type: RolloutConditionType(v.Type), + Status: v.Status, + LastUpdateTime: v.LastUpdateTime, + LastTransitionTime: v.LastTransitionTime, + Reason: v.Reason, + Message: v.Message, + } + } + dst.Status = BatchReleaseStatus{ + Conditions: conditions, + CanaryStatus: BatchReleaseCanaryStatus{ + CurrentBatchState: BatchReleaseBatchStateType(src.Status.CanaryStatus.CurrentBatchState), + CurrentBatch: src.Status.CanaryStatus.CurrentBatch, + BatchReadyTime: src.Status.CanaryStatus.BatchReadyTime, + UpdatedReplicas: src.Status.CanaryStatus.UpdatedReplicas, + UpdatedReadyReplicas: src.Status.CanaryStatus.UpdatedReadyReplicas, + NoNeedUpdateReplicas: src.Status.CanaryStatus.NoNeedUpdateReplicas, + }, + StableRevision: src.Status.StableRevision, + UpdateRevision: src.Status.UpdateRevision, + ObservedGeneration: src.Status.ObservedGeneration, + ObservedRolloutID: src.Status.ObservedRolloutID, + ObservedWorkloadReplicas: src.Status.ObservedWorkloadReplicas, + CollisionCount: src.Status.CollisionCount, + ObservedReleasePlanHash: src.Status.ObservedReleasePlanHash, + Phase: RolloutPhase(src.Status.Phase), + } + default: + return fmt.Errorf("unsupported type %v", t) + } + return nil +} diff --git a/api/v1alpha1/rollout_conversion.go b/api/v1alpha1/rollout_conversion.go new file mode 100644 index 0000000..09ab6ce --- /dev/null +++ b/api/v1alpha1/rollout_conversion.go @@ -0,0 +1,201 @@ +package v1alpha1 + +import ( + "fmt" + + "github.com/openkruise/rollouts/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +func (src *Rollout) ConvertTo(dstRaw conversion.Hub) error { + switch t := dstRaw.(type) { + case *v1beta1.Rollout: + dst := dstRaw.(*v1beta1.Rollout) + dst.ObjectMeta = src.ObjectMeta + + // rollout spec conversion + dst.Spec.DeprecatedRolloutID = src.Spec.DeprecatedRolloutID + dst.Spec.Disabled = src.Spec.Disabled + dst.Spec.ObjectRef = v1beta1.ObjectRef{ + WorkloadRef: &v1beta1.WorkloadRef{ + APIVersion: src.Spec.ObjectRef.WorkloadRef.APIVersion, + Kind: src.Spec.ObjectRef.WorkloadRef.Kind, + Name: src.Spec.ObjectRef.WorkloadRef.Name, + }, + } + dst.Spec.Strategy.Paused = src.Spec.Strategy.Paused + if src.Spec.Strategy.Canary != nil { + dst.Spec.Strategy.Canary = &v1beta1.CanaryStrategy{} + dst.Spec.Strategy.Canary.FailureThreshold = src.Spec.Strategy.Canary.FailureThreshold + dst.Spec.Strategy.Canary.PatchPodTemplateMetadata = (*v1beta1.PatchPodTemplateMetadata)(src.Spec.Strategy.Canary.PatchPodTemplateMetadata) + trafficRoutings := make([]v1beta1.TrafficRoutingRef, len(src.Spec.Strategy.Canary.TrafficRoutings)) + for i, v := range src.Spec.Strategy.Canary.TrafficRoutings { + trafficRoutings[i] = v1beta1.TrafficRoutingRef{ + GracePeriodSeconds: v.GracePeriodSeconds, + Service: v.Service, + } + if v.Gateway != nil { + trafficRoutings[i].Gateway.HTTPRouteName = v.Gateway.HTTPRouteName + } + if v.Ingress != nil { + trafficRoutings[i].Ingress = (*v1beta1.IngressTrafficRouting)(v.Ingress) + } + } + dst.Spec.Strategy.Canary.TrafficRoutings = trafficRoutings + steps := make([]v1beta1.CanaryStep, len(src.Spec.Strategy.Canary.Steps)) + for i, v := range src.Spec.Strategy.Canary.Steps { + step := v1beta1.CanaryStep{ + Pause: v1beta1.RolloutPause(v.Pause), + Replicas: v.Replicas, + TrafficRoutingStrategy: v1beta1.TrafficRoutingStrategy{ + Weight: v.Weight, + RequestHeaderModifier: v.RequestHeaderModifier, + Matches: make([]v1beta1.HttpRouteMatch, len(v.Matches)), + }, + } + for j, u := range v.Matches { + step.Matches[j] = v1beta1.HttpRouteMatch{ + Headers: u.Headers, + } + } + steps[i] = step + } + dst.Spec.Strategy.Canary.Steps = steps + } + + // rollout status conversion + conditions := make([]v1beta1.RolloutCondition, len(src.Status.Conditions)) + for i, v := range src.Status.Conditions { + conditions[i] = v1beta1.RolloutCondition{ + Type: v1beta1.RolloutConditionType(v.Type), + Status: v.Status, + LastUpdateTime: v.LastUpdateTime, + LastTransitionTime: v.LastTransitionTime, + Reason: v.Reason, + Message: v.Message, + } + } + dst.Status = v1beta1.RolloutStatus{ + ObservedGeneration: src.Status.ObservedGeneration, + Phase: v1beta1.RolloutPhase(src.Status.Phase), + Message: src.Status.Message, + Conditions: conditions, + } + if src.Status.CanaryStatus != nil { + dst.Status.CanaryStatus = &v1beta1.CanaryStatus{ + ObservedWorkloadGeneration: src.Status.CanaryStatus.ObservedWorkloadGeneration, + ObservedRolloutID: src.Status.CanaryStatus.ObservedRolloutID, + RolloutHash: src.Status.CanaryStatus.RolloutHash, + StableRevision: src.Status.CanaryStatus.StableRevision, + CanaryRevision: src.Status.CanaryStatus.CanaryRevision, + PodTemplateHash: src.Status.CanaryStatus.PodTemplateHash, + CanaryReplicas: src.Status.CanaryStatus.CanaryReadyReplicas, + CanaryReadyReplicas: src.Status.CanaryStatus.CanaryReadyReplicas, + CurrentStepIndex: src.Status.CanaryStatus.CurrentStepIndex, + CurrentStepState: v1beta1.CanaryStepState(src.Status.CanaryStatus.CurrentStepState), + Message: src.Status.CanaryStatus.Message, + LastUpdateTime: src.Status.CanaryStatus.LastUpdateTime, + } + } + default: + return fmt.Errorf("unsupported type %v", t) + } + return nil +} + +func (dst *Rollout) ConvertFrom(srcRaw conversion.Hub) error { + switch t := srcRaw.(type) { + case *v1beta1.Rollout: + src := srcRaw.(*v1beta1.Rollout) + dst.ObjectMeta = src.ObjectMeta + + // rollout spec conversion + dst.Spec.DeprecatedRolloutID = src.Spec.DeprecatedRolloutID + dst.Spec.Disabled = src.Spec.Disabled + dst.Spec.ObjectRef = ObjectRef{ + WorkloadRef: &WorkloadRef{ + APIVersion: src.Spec.ObjectRef.WorkloadRef.APIVersion, + Kind: src.Spec.ObjectRef.WorkloadRef.Kind, + Name: src.Spec.ObjectRef.WorkloadRef.Name, + }, + } + dst.Spec.Strategy.Paused = src.Spec.Strategy.Paused + if src.Spec.Strategy.Canary != nil { + dst.Spec.Strategy.Canary = &CanaryStrategy{} + dst.Spec.Strategy.Canary.FailureThreshold = src.Spec.Strategy.Canary.FailureThreshold + dst.Spec.Strategy.Canary.PatchPodTemplateMetadata = (*PatchPodTemplateMetadata)(src.Spec.Strategy.Canary.PatchPodTemplateMetadata) + trafficRoutings := make([]TrafficRoutingRef, len(src.Spec.Strategy.Canary.TrafficRoutings)) + for i, v := range src.Spec.Strategy.Canary.TrafficRoutings { + trafficRoutings[i] = TrafficRoutingRef{ + GracePeriodSeconds: v.GracePeriodSeconds, + Service: v.Service, + } + if v.Gateway != nil { + trafficRoutings[i].Gateway.HTTPRouteName = v.Gateway.HTTPRouteName + } + if v.Ingress != nil { + trafficRoutings[i].Ingress = (*IngressTrafficRouting)(v.Ingress) + } + } + dst.Spec.Strategy.Canary.TrafficRoutings = trafficRoutings + steps := make([]CanaryStep, len(src.Spec.Strategy.Canary.Steps)) + for i, v := range src.Spec.Strategy.Canary.Steps { + step := CanaryStep{ + Pause: RolloutPause(v.Pause), + Replicas: v.Replicas, + TrafficRoutingStrategy: TrafficRoutingStrategy{ + Weight: v.Weight, + RequestHeaderModifier: v.RequestHeaderModifier, + Matches: make([]HttpRouteMatch, len(v.Matches)), + }, + } + for j, u := range v.Matches { + step.Matches[j] = HttpRouteMatch{ + Headers: u.Headers, + } + } + steps[i] = step + } + dst.Spec.Strategy.Canary.Steps = steps + } + + // rollout spec conversion + conditions := make([]RolloutCondition, len(src.Status.Conditions)) + for i, v := range src.Status.Conditions { + conditions[i] = RolloutCondition{ + Type: RolloutConditionType(v.Type), + Status: v.Status, + LastUpdateTime: v.LastUpdateTime, + LastTransitionTime: v.LastTransitionTime, + Reason: v.Reason, + Message: v.Message, + } + } + dst.Status = RolloutStatus{ + ObservedGeneration: src.Status.ObservedGeneration, + Phase: RolloutPhase(src.Status.Phase), + Message: src.Status.Message, + Conditions: conditions, + } + if src.Status.CanaryStatus != nil { + dst.Status.CanaryStatus = &CanaryStatus{ + ObservedWorkloadGeneration: src.Status.CanaryStatus.ObservedWorkloadGeneration, + ObservedRolloutID: src.Status.CanaryStatus.ObservedRolloutID, + RolloutHash: src.Status.CanaryStatus.RolloutHash, + StableRevision: src.Status.CanaryStatus.StableRevision, + CanaryRevision: src.Status.CanaryStatus.CanaryRevision, + PodTemplateHash: src.Status.CanaryStatus.PodTemplateHash, + CanaryReplicas: src.Status.CanaryStatus.CanaryReadyReplicas, + CanaryReadyReplicas: src.Status.CanaryStatus.CanaryReadyReplicas, + CurrentStepIndex: src.Status.CanaryStatus.CurrentStepIndex, + CurrentStepState: CanaryStepState(src.Status.CanaryStatus.CurrentStepState), + Message: src.Status.CanaryStatus.Message, + LastUpdateTime: src.Status.CanaryStatus.LastUpdateTime, + } + } + default: + return fmt.Errorf("unsupported type %v", t) + } + + return nil +} diff --git a/api/v1alpha1/rollout_types.go b/api/v1alpha1/rollout_types.go index 1a8bea1..43e8a74 100644 --- a/api/v1alpha1/rollout_types.go +++ b/api/v1alpha1/rollout_types.go @@ -279,8 +279,8 @@ const ( ) // +genclient -//+kubebuilder:object:root=true -//+kubebuilder:subresource:status +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="STATUS",type="string",JSONPath=".status.phase",description="The rollout status phase" // +kubebuilder:printcolumn:name="CANARY_STEP",type="integer",JSONPath=".status.canaryStatus.currentStepIndex",description="The rollout canary status step" // +kubebuilder:printcolumn:name="CANARY_STATE",type="string",JSONPath=".status.canaryStatus.currentStepState",description="The rollout canary status step state" diff --git a/api/v1alpha1/rollouthistory_conversion.go b/api/v1alpha1/rollouthistory_conversion.go new file mode 100644 index 0000000..1d08132 --- /dev/null +++ b/api/v1alpha1/rollouthistory_conversion.go @@ -0,0 +1,84 @@ +package v1alpha1 + +import ( + "fmt" + + "github.com/openkruise/rollouts/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +func (src *RolloutHistory) ConvertTo(dstRaw conversion.Hub) error { + switch t := dstRaw.(type) { + case *v1beta1.RolloutHistory: + dst := dstRaw.(*v1beta1.RolloutHistory) + dst.ObjectMeta = src.ObjectMeta + + // rollouthistory spec conversion + dst.Spec.Rollout.RolloutID = src.Spec.Rollout.RolloutID + dst.Spec.Rollout.NameAndSpecData = v1beta1.NameAndSpecData(src.Spec.Rollout.NameAndSpecData) + dst.Spec.Workload.TypeMeta = src.Spec.Workload.TypeMeta + dst.Spec.Workload.NameAndSpecData = v1beta1.NameAndSpecData(src.Spec.Workload.NameAndSpecData) + dst.Spec.Service.NameAndSpecData = v1beta1.NameAndSpecData(src.Spec.Service.NameAndSpecData) + if src.Spec.TrafficRouting.HTTPRoute != nil { + dst.Spec.TrafficRouting.HTTPRoute.NameAndSpecData = v1beta1.NameAndSpecData(src.Spec.TrafficRouting.HTTPRoute.NameAndSpecData) + } + if src.Spec.TrafficRouting.Ingress != nil { + dst.Spec.TrafficRouting.Ingress.NameAndSpecData = v1beta1.NameAndSpecData(src.Spec.TrafficRouting.Ingress.NameAndSpecData) + } + + // rollouthistory status conversion + steps := make([]v1beta1.CanaryStepInfo, len(src.Status.CanarySteps)) + for i, v := range src.Status.CanarySteps { + pods := make([]v1beta1.Pod, len(v.Pods)) + for j, u := range v.Pods { + pods[j].Name = u.Name + pods[j].IP = u.IP + pods[j].NodeName = u.NodeName + } + steps[i].CanaryStepIndex = v.CanaryStepIndex + steps[i].Pods = pods + } + dst.Status.Phase = src.Status.Phase + default: + return fmt.Errorf("unsupported type %v", t) + } + return nil +} + +func (dst *RolloutHistory) ConvertFrom(srcRaw conversion.Hub) error { + switch t := srcRaw.(type) { + case *v1beta1.RolloutHistory: + src := srcRaw.(*v1beta1.RolloutHistory) + dst.ObjectMeta = src.ObjectMeta + + // rollouthistory spec conversion + dst.Spec.Rollout.RolloutID = src.Spec.Rollout.RolloutID + dst.Spec.Rollout.NameAndSpecData = NameAndSpecData(src.Spec.Rollout.NameAndSpecData) + dst.Spec.Workload.TypeMeta = src.Spec.Workload.TypeMeta + dst.Spec.Workload.NameAndSpecData = NameAndSpecData(src.Spec.Workload.NameAndSpecData) + dst.Spec.Service.NameAndSpecData = NameAndSpecData(src.Spec.Service.NameAndSpecData) + if src.Spec.TrafficRouting.HTTPRoute != nil { + dst.Spec.TrafficRouting.HTTPRoute.NameAndSpecData = NameAndSpecData(src.Spec.TrafficRouting.HTTPRoute.NameAndSpecData) + } + if src.Spec.TrafficRouting.Ingress != nil { + dst.Spec.TrafficRouting.Ingress.NameAndSpecData = NameAndSpecData(src.Spec.TrafficRouting.Ingress.NameAndSpecData) + } + + // rollouthistory status conversion + steps := make([]CanaryStepInfo, len(src.Status.CanarySteps)) + for i, v := range src.Status.CanarySteps { + pods := make([]Pod, len(v.Pods)) + for j, u := range v.Pods { + pods[j].Name = u.Name + pods[j].IP = u.IP + pods[j].NodeName = u.NodeName + } + steps[i].CanaryStepIndex = v.CanaryStepIndex + steps[i].Pods = pods + } + dst.Status.Phase = src.Status.Phase + default: + return fmt.Errorf("unsupported type %v", t) + } + return nil +} diff --git a/api/v1alpha1/rollouthistory_types.go b/api/v1alpha1/rollouthistory_types.go index 0a80be3..1edf275 100644 --- a/api/v1alpha1/rollouthistory_types.go +++ b/api/v1alpha1/rollouthistory_types.go @@ -125,8 +125,8 @@ const ( ) // +genclient -//+kubebuilder:object:root=true -//+kubebuilder:subresource:status +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status // RolloutHistory is the Schema for the rollouthistories API type RolloutHistory struct { diff --git a/api/v1alpha1/trafficrouting_conversion.go b/api/v1alpha1/trafficrouting_conversion.go new file mode 100644 index 0000000..d1acb57 --- /dev/null +++ b/api/v1alpha1/trafficrouting_conversion.go @@ -0,0 +1,100 @@ +package v1alpha1 + +import ( + "fmt" + + "github.com/openkruise/rollouts/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +func (src *TrafficRouting) ConvertTo(dstRaw conversion.Hub) error { + switch t := dstRaw.(type) { + case *v1beta1.TrafficRouting: + dst := dstRaw.(*v1beta1.TrafficRouting) + dst.ObjectMeta = src.ObjectMeta + + // trafficRouting spec conversion + objectRef := make([]v1beta1.TrafficRoutingRef, len(src.Spec.ObjectRef)) + for i, v := range src.Spec.ObjectRef { + objectRef[i] = v1beta1.TrafficRoutingRef{ + GracePeriodSeconds: v.GracePeriodSeconds, + Service: v.Service, + } + if v.Ingress != nil { + objectRef[i].Ingress = &v1beta1.IngressTrafficRouting{ + Name: v.Ingress.Name, + ClassType: v.Ingress.ClassType, + } + } + if v.Gateway != nil { + objectRef[i].Gateway = &v1beta1.GatewayTrafficRouting{ + HTTPRouteName: v.Gateway.HTTPRouteName, + } + } + } + dst.Spec.ObjectRef = objectRef + matches := make([]v1beta1.HttpRouteMatch, len(src.Spec.Strategy.Matches)) + for i, v := range src.Spec.Strategy.Matches { + matches[i].Headers = v.Headers + } + dst.Spec.Strategy = v1beta1.TrafficRoutingStrategy{ + Weight: src.Spec.Strategy.Weight, + RequestHeaderModifier: src.Spec.Strategy.RequestHeaderModifier, + Matches: matches, + } + + // trafficRouting status conversion + dst.Status.ObservedGeneration = src.Status.ObservedGeneration + dst.Status.Phase = v1beta1.TrafficRoutingPhase(src.Status.Phase) + dst.Status.Message = src.Status.Message + default: + return fmt.Errorf("unsupported type %v", t) + } + return nil +} + +func (dst *TrafficRouting) ConvertFrom(srcRaw conversion.Hub) error { + switch t := srcRaw.(type) { + case *v1beta1.TrafficRouting: + src := srcRaw.(*v1beta1.TrafficRouting) + dst.ObjectMeta = src.ObjectMeta + + // trafficRouting spec conversion + objectRef := make([]TrafficRoutingRef, len(src.Spec.ObjectRef)) + for i, v := range src.Spec.ObjectRef { + objectRef[i] = TrafficRoutingRef{ + GracePeriodSeconds: v.GracePeriodSeconds, + Service: v.Service, + } + if v.Ingress != nil { + objectRef[i].Ingress = &IngressTrafficRouting{ + Name: v.Ingress.Name, + ClassType: v.Ingress.ClassType, + } + } + if v.Gateway != nil { + objectRef[i].Gateway = &GatewayTrafficRouting{ + HTTPRouteName: v.Gateway.HTTPRouteName, + } + } + } + dst.Spec.ObjectRef = objectRef + matches := make([]HttpRouteMatch, len(src.Spec.Strategy.Matches)) + for i, v := range src.Spec.Strategy.Matches { + matches[i].Headers = v.Headers + } + dst.Spec.Strategy = TrafficRoutingStrategy{ + Weight: src.Spec.Strategy.Weight, + RequestHeaderModifier: src.Spec.Strategy.RequestHeaderModifier, + Matches: matches, + } + + // trafficRouting status conversion + dst.Status.ObservedGeneration = src.Status.ObservedGeneration + dst.Status.Phase = TrafficRoutingPhase(src.Status.Phase) + dst.Status.Message = src.Status.Message + default: + return fmt.Errorf("unsupported type %v", t) + } + return nil +} diff --git a/api/v1alpha1/trafficrouting_types.go b/api/v1alpha1/trafficrouting_types.go index 0386a87..a79042f 100644 --- a/api/v1alpha1/trafficrouting_types.go +++ b/api/v1alpha1/trafficrouting_types.go @@ -125,8 +125,8 @@ const ( ) // +genclient -//+kubebuilder:object:root=true -//+kubebuilder:subresource:status +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="STATUS",type="string",JSONPath=".status.phase",description="The TrafficRouting status phase" // +kubebuilder:printcolumn:name="MESSAGE",type="string",JSONPath=".status.message",description="The TrafficRouting canary status message" // +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=".metadata.creationTimestamp" diff --git a/api/v1beta1/batchrelease_conversion.go b/api/v1beta1/batchrelease_conversion.go new file mode 100644 index 0000000..29e6397 --- /dev/null +++ b/api/v1beta1/batchrelease_conversion.go @@ -0,0 +1,3 @@ +package v1beta1 + +func (*BatchRelease) Hub() {} diff --git a/api/v1beta1/batchrelease_types.go b/api/v1beta1/batchrelease_types.go new file mode 100644 index 0000000..ca46b15 --- /dev/null +++ b/api/v1beta1/batchrelease_types.go @@ -0,0 +1,186 @@ +/* +Copyright 2022 The Kruise Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +// batchrelease plan +// ReleasePlan fines the details of the release plan +type ReleasePlan struct { + // Batches is the details on each batch of the ReleasePlan. + //Users can specify their batch plan in this field, such as: + // batches: + // - canaryReplicas: 1 # batches 0 + // - canaryReplicas: 2 # batches 1 + // - canaryReplicas: 5 # batches 2 + // Not that these canaryReplicas should be a non-decreasing sequence. + // +optional + Batches []ReleaseBatch `json:"batches"` + // All pods in the batches up to the batchPartition (included) will have + // the target resource specification while the rest still is the stable revision. + // This is designed for the operators to manually rollout. + // Default is nil, which means no partition and will release all batches. + // BatchPartition start from 0. + // +optional + BatchPartition *int32 `json:"batchPartition,omitempty"` + // RolloutID indicates an id for each rollout progress + RolloutID string `json:"rolloutID,omitempty"` + // FailureThreshold indicates how many failed pods can be tolerated in all upgraded pods. + // Only when FailureThreshold are satisfied, Rollout can enter ready state. + // If FailureThreshold is nil, Rollout will use the MaxUnavailable of workload as its + // FailureThreshold. + // Defaults to nil. + FailureThreshold *intstr.IntOrString `json:"failureThreshold,omitempty"` + // FinalizingPolicy define the behavior of controller when phase enter Finalizing + // Defaults to "Immediate" + FinalizingPolicy FinalizingPolicyType `json:"finalizingPolicy,omitempty"` + // PatchPodTemplateMetadata indicates patch configuration(e.g. labels, annotations) to the canary deployment podTemplateSpec.metadata + // only support for canary deployment + // +optional + PatchPodTemplateMetadata *PatchPodTemplateMetadata `json:"patchPodTemplateMetadata,omitempty"` +} + +type FinalizingPolicyType string + +const ( + // WaitResumeFinalizingPolicyType will wait workload to be resumed, which means + // controller will be hold at Finalizing phase util all pods of workload is upgraded. + // WaitResumeFinalizingPolicyType only works in canary-style BatchRelease controller. + WaitResumeFinalizingPolicyType FinalizingPolicyType = "WaitResume" + // ImmediateFinalizingPolicyType will not to wait workload to be resumed. + ImmediateFinalizingPolicyType FinalizingPolicyType = "Immediate" +) + +// ReleaseBatch is used to describe how each batch release should be +type ReleaseBatch struct { + // CanaryReplicas is the number of upgraded pods that should have in this batch. + // it can be an absolute number (ex: 5) or a percentage of workload replicas. + // batches[i].canaryReplicas should less than or equal to batches[j].canaryReplicas if i < j. + CanaryReplicas intstr.IntOrString `json:"canaryReplicas"` +} + +// BatchReleaseStatus defines the observed state of a release plan +type BatchReleaseStatus struct { + // Conditions represents the observed process state of each phase during executing the release plan. + Conditions []RolloutCondition `json:"conditions,omitempty"` + // CanaryStatus describes the state of the canary rollout. + CanaryStatus BatchReleaseCanaryStatus `json:"canaryStatus,omitempty"` + // StableRevision is the pod-template-hash of stable revision pod template. + StableRevision string `json:"stableRevision,omitempty"` + // UpdateRevision is the pod-template-hash of update revision pod template. + UpdateRevision string `json:"updateRevision,omitempty"` + // ObservedGeneration is the most recent generation observed for this BatchRelease. + // It corresponds to this BatchRelease's generation, which is updated on mutation + // by the API Server, and only if BatchRelease Spec was changed, its generation will increase 1. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // ObservedRolloutID is the most recent rollout-id observed for this BatchRelease. + // If RolloutID was changed, we will restart to roll out from batch 0, + // to ensure the batch-id and rollout-id labels of Pods are correct. + ObservedRolloutID string `json:"observedRolloutID,omitempty"` + // ObservedWorkloadReplicas is observed replicas of target referenced workload. + // This field is designed to deal with scaling event during rollout, if this field changed, + // it means that the workload is scaling during rollout. + ObservedWorkloadReplicas int32 `json:"observedWorkloadReplicas,omitempty"` + // Count of hash collisions for creating canary Deployment. The controller uses this + // field as a collision avoidance mechanism when it needs to create the name for the + // newest canary Deployment. + // +optional + CollisionCount *int32 `json:"collisionCount,omitempty"` + // ObservedReleasePlanHash is a hash code of observed itself spec.releasePlan. + ObservedReleasePlanHash string `json:"observedReleasePlanHash,omitempty"` + // Phase is the release plan phase, which indicates the current state of release + // plan state machine in BatchRelease controller. + Phase RolloutPhase `json:"phase,omitempty"` +} + +type BatchReleaseCanaryStatus struct { + // CurrentBatchState indicates the release state of the current batch. + CurrentBatchState BatchReleaseBatchStateType `json:"batchState,omitempty"` + // The current batch the rollout is working on/blocked, it starts from 0 + CurrentBatch int32 `json:"currentBatch"` + // BatchReadyTime is the ready timestamp of the current batch or the last batch. + // This field is updated once a batch ready, and the batches[x].pausedSeconds + // relies on this field to calculate the real-time duration. + BatchReadyTime *metav1.Time `json:"batchReadyTime,omitempty"` + // UpdatedReplicas is the number of upgraded Pods. + UpdatedReplicas int32 `json:"updatedReplicas,omitempty"` + // UpdatedReadyReplicas is the number upgraded Pods that have a Ready Condition. + UpdatedReadyReplicas int32 `json:"updatedReadyReplicas,omitempty"` + // the number of pods that no need to rollback in rollback scene. + NoNeedUpdateReplicas *int32 `json:"noNeedUpdateReplicas,omitempty"` +} + +type BatchReleaseBatchStateType string + +const ( + // UpgradingBatchState indicates that current batch is at upgrading pod state + UpgradingBatchState BatchReleaseBatchStateType = "Upgrading" + // VerifyingBatchState indicates that current batch is at verifying whether it's ready state + VerifyingBatchState BatchReleaseBatchStateType = "Verifying" + // ReadyBatchState indicates that current batch is at batch ready state + ReadyBatchState BatchReleaseBatchStateType = "Ready" +) + +const ( + // RolloutPhasePreparing indicates a rollout is preparing for next progress. + RolloutPhasePreparing RolloutPhase = "Preparing" + // RolloutPhaseFinalizing indicates a rollout is finalizing + RolloutPhaseFinalizing RolloutPhase = "Finalizing" + // RolloutPhaseCompleted indicates a rollout is completed/cancelled/terminated + RolloutPhaseCompleted RolloutPhase = "Completed" +) + +// +genclient +// +k8s:openapi-gen=true +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="KIND",type=string,JSONPath=`.spec.targetReference.workloadRef.kind` +// +kubebuilder:printcolumn:name="PHASE",type=string,JSONPath=`.status.phase` +// +kubebuilder:printcolumn:name="BATCH",type=integer,JSONPath=`.status.canaryStatus.currentBatch` +// +kubebuilder:printcolumn:name="BATCH-STATE",type=string,JSONPath=`.status.canaryStatus.batchState` +// +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=".metadata.creationTimestamp" +// +kubebuilder:storageversion +type BatchRelease struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec BatchReleaseSpec `json:"spec,omitempty"` + Status BatchReleaseStatus `json:"status,omitempty"` +} + +// BatchReleaseSpec defines how to describe an update between different compRevision +type BatchReleaseSpec struct { + // TargetRef contains the GVK and name of the workload that we need to upgrade to. + TargetRef ObjectRef `json:"targetReference"` + // ReleasePlan is the details on how to rollout the resources + ReleasePlan ReleasePlan `json:"releasePlan"` +} + +// BatchReleaseList contains a list of BatchRelease +// +kubebuilder:object:root=true +type BatchReleaseList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []BatchRelease `json:"items"` +} + +func init() { + SchemeBuilder.Register(&BatchRelease{}, &BatchReleaseList{}) +} diff --git a/api/v1beta1/groupversion_info.go b/api/v1beta1/groupversion_info.go new file mode 100644 index 0000000..8571953 --- /dev/null +++ b/api/v1beta1/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2022 The Kruise Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1beta1 contains API Schema definitions for the rollouts v1beta1 API group +// +kubebuilder:object:generate=true +// +groupName=rollouts.kruise.io +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "rollouts.kruise.io", Version: "v1beta1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/v1beta1/rollout_conversion.go b/api/v1beta1/rollout_conversion.go new file mode 100644 index 0000000..bba384a --- /dev/null +++ b/api/v1beta1/rollout_conversion.go @@ -0,0 +1,3 @@ +package v1beta1 + +func (*Rollout) Hub() {} diff --git a/api/v1beta1/rollout_types.go b/api/v1beta1/rollout_types.go new file mode 100644 index 0000000..342dca9 --- /dev/null +++ b/api/v1beta1/rollout_types.go @@ -0,0 +1,310 @@ +/* +Copyright 2022 The Kruise Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +const ( + // RolloutIDLabel is set to workload labels. + // RolloutIDLabel is designed to distinguish each workload revision publications. + // The value of RolloutIDLabel corresponds Rollout.Spec.RolloutID. + RolloutIDLabel = "rollouts.kruise.io/rollout-id" + + // RolloutBatchIDLabel is patched in pod labels. + // RolloutBatchIDLabel is the label key of batch id that will be patched to pods during rollout. + // Only when RolloutIDLabel is set, RolloutBatchIDLabel will be patched. + // Users can use RolloutIDLabel and RolloutBatchIDLabel to select the pods that are upgraded in some certain batch and release. + RolloutBatchIDLabel = "rollouts.kruise.io/rollout-batch-id" + + // RollbackInBatchAnnotation is set to rollout annotations. + // RollbackInBatchAnnotation allow use disable quick rollback, and will roll back in batch style. + RollbackInBatchAnnotation = "rollouts.kruise.io/rollback-in-batch" + + // RolloutStyleAnnotation define the rolling behavior for Deployment. + // must be "partition" or "canary": + // * "partition" means rolling in batches just like CloneSet, and will NOT create any extra Workload; + // * "canary" means rolling in canary way, and will create a canary Workload. + // Currently, only Deployment support both "partition" and "canary" rolling styles. + // For other workload types, they only support "partition" styles. + // Defaults to "canary" to Deployment. + // Defaults to "partition" to the others. + RolloutStyleAnnotation = "rollouts.kruise.io/rolling-style" + + // TrafficRoutingAnnotation is the TrafficRouting Name, and it is the Rollout's TrafficRouting. + // The Rollout release will trigger the TrafficRouting release. For example: + // A microservice consists of three applications, and the invocation relationship is as follows: a -> b -> c, + // and application(a, b, c)'s gateway is trafficRouting. Any application(a, b or b) release will trigger TrafficRouting release. + TrafficRoutingAnnotation = "rollouts.kruise.io/trafficrouting" +) + +// RolloutSpec defines the desired state of Rollout +type RolloutSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + // ObjectRef indicates workload + ObjectRef ObjectRef `json:"objectRef"` + // rollout strategy + Strategy RolloutStrategy `json:"strategy"` + // DeprecatedRolloutID is the deprecated field. + // It is recommended that configure RolloutId in workload.annotations[rollouts.kruise.io/rollout-id]. + // RolloutID should be changed before each workload revision publication. + // It is to distinguish consecutive multiple workload publications and rollout progress. + DeprecatedRolloutID string `json:"rolloutID,omitempty"` + // if a rollout disabled, then the rollout would not watch changes of workload + //+kubebuilder:validation:Optional + //+kubebuilder:default=false + Disabled bool `json:"disabled"` +} + +type ObjectRef struct { + // WorkloadRef contains enough information to let you identify a workload for Rollout + // Batch release of the bypass + WorkloadRef *WorkloadRef `json:"workloadRef,omitempty"` +} + +// WorkloadRef holds a references to the Kubernetes object +type WorkloadRef struct { + // API Version of the referent + APIVersion string `json:"apiVersion"` + // Kind of the referent + Kind string `json:"kind"` + // Name of the referent + Name string `json:"name"` +} + +// RolloutStrategy defines strategy to apply during next rollout +type RolloutStrategy struct { + // Paused indicates that the Rollout is paused. + // Default value is false + Paused bool `json:"paused,omitempty"` + // +optional + Canary *CanaryStrategy `json:"canary,omitempty"` +} + +// CanaryStrategy defines parameters for a Replica Based Canary +type CanaryStrategy struct { + // Steps define the order of phases to execute release in batches(20%, 40%, 60%, 80%, 100%) + // +optional + Steps []CanaryStep `json:"steps,omitempty"` + // TrafficRoutings hosts all the supported service meshes supported to enable more fine-grained traffic routing + // and current only support one TrafficRouting + TrafficRoutings []TrafficRoutingRef `json:"trafficRoutings,omitempty"` + // FailureThreshold indicates how many failed pods can be tolerated in all upgraded pods. + // Only when FailureThreshold are satisfied, Rollout can enter ready state. + // If FailureThreshold is nil, Rollout will use the MaxUnavailable of workload as its + // FailureThreshold. + // Defaults to nil. + FailureThreshold *intstr.IntOrString `json:"failureThreshold,omitempty"` + // PatchPodTemplateMetadata indicates patch configuration(e.g. labels, annotations) to the canary deployment podTemplateSpec.metadata + // only support for canary deployment + // +optional + PatchPodTemplateMetadata *PatchPodTemplateMetadata `json:"patchPodTemplateMetadata,omitempty"` +} + +type PatchPodTemplateMetadata struct { + // annotations + Annotations map[string]string `json:"annotations,omitempty"` + // labels + Labels map[string]string `json:"labels,omitempty"` +} + +// CanaryStep defines a step of a canary workload. +type CanaryStep struct { + TrafficRoutingStrategy `json:",inline"` + // Replicas is the number of expected canary pods in this batch + // it can be an absolute number (ex: 5) or a percentage of total pods. + Replicas *intstr.IntOrString `json:"replicas,omitempty"` + // Pause defines a pause stage for a rollout, manual or auto + // +optional + Pause RolloutPause `json:"pause,omitempty"` +} + +type HttpRouteMatch struct { + // Headers specifies HTTP request header matchers. Multiple match values are + // ANDed together, meaning, a request must match all the specified headers + // to select the route. + // +kubebuilder:validation:MaxItems=16 + Headers []gatewayv1alpha2.HTTPHeaderMatch `json:"headers,omitempty"` +} + +// RolloutPause defines a pause stage for a rollout +type RolloutPause struct { + // Duration the amount of time to wait before moving to the next step. + // +optional + Duration *int32 `json:"duration,omitempty"` +} + +// RolloutStatus defines the observed state of Rollout +type RolloutStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // observedGeneration is the most recent generation observed for this Rollout. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // Canary describes the state of the canary rollout + // +optional + CanaryStatus *CanaryStatus `json:"canaryStatus,omitempty"` + // Conditions a list of conditions a rollout can have. + // +optional + Conditions []RolloutCondition `json:"conditions,omitempty"` + // +optional + //BlueGreenStatus *BlueGreenStatus `json:"blueGreenStatus,omitempty"` + // Phase is the rollout phase. + Phase RolloutPhase `json:"phase,omitempty"` + // Message provides details on why the rollout is in its current phase + Message string `json:"message,omitempty"` +} + +// RolloutCondition describes the state of a rollout at a certain point. +type RolloutCondition struct { + // Type of rollout condition. + Type RolloutConditionType `json:"type"` + // Phase of the condition, one of True, False, Unknown. + Status corev1.ConditionStatus `json:"status"` + // The last time this condition was updated. + LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"` + // Last time the condition transitioned from one status to another. + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + // The reason for the condition's last transition. + Reason string `json:"reason"` + // A human readable message indicating details about the transition. + Message string `json:"message"` +} + +// RolloutConditionType defines the conditions of Rollout +type RolloutConditionType string + +// These are valid conditions of a rollout. +const ( + // RolloutConditionProgressing means the rollout is progressing. Progress for a rollout is + // considered when a new replica set is created or adopted, when pods scale + // up or old pods scale down, or when the services are updated. Progress is not estimated + // for paused rollouts. + RolloutConditionProgressing RolloutConditionType = "Progressing" + // Progressing Reason + ProgressingReasonInitializing = "Initializing" + ProgressingReasonInRolling = "InRolling" + ProgressingReasonFinalising = "Finalising" + ProgressingReasonCompleted = "Completed" + ProgressingReasonCancelling = "Cancelling" + ProgressingReasonPaused = "Paused" + + // RolloutConditionSucceeded indicates whether rollout is succeeded or failed. + RolloutConditionSucceeded RolloutConditionType = "Succeeded" + + // Terminating condition + RolloutConditionTerminating RolloutConditionType = "Terminating" + // Terminating Reason + TerminatingReasonInTerminating = "InTerminating" + TerminatingReasonCompleted = "Completed" +) + +// CanaryStatus status fields that only pertain to the canary rollout +type CanaryStatus struct { + // observedWorkloadGeneration is the most recent generation observed for this Rollout ref workload generation. + ObservedWorkloadGeneration int64 `json:"observedWorkloadGeneration,omitempty"` + // ObservedRolloutID will record the newest spec.RolloutID if status.canaryRevision equals to workload.updateRevision + ObservedRolloutID string `json:"observedRolloutID,omitempty"` + // RolloutHash from rollout.spec object + RolloutHash string `json:"rolloutHash,omitempty"` + // StableRevision indicates the revision of stable pods + StableRevision string `json:"stableRevision,omitempty"` + // CanaryRevision is calculated by rollout based on podTemplateHash, and the internal logic flow uses + // It may be different from rs podTemplateHash in different k8s versions, so it cannot be used as service selector label + CanaryRevision string `json:"canaryRevision"` + // pod template hash is used as service selector label + PodTemplateHash string `json:"podTemplateHash"` + // CanaryReplicas the numbers of canary revision pods + CanaryReplicas int32 `json:"canaryReplicas"` + // CanaryReadyReplicas the numbers of ready canary revision pods + CanaryReadyReplicas int32 `json:"canaryReadyReplicas"` + // CurrentStepIndex defines the current step of the rollout is on. If the current step index is null, the + // controller will execute the rollout. + // +optional + CurrentStepIndex int32 `json:"currentStepIndex"` + CurrentStepState CanaryStepState `json:"currentStepState"` + Message string `json:"message,omitempty"` + LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"` +} + +type CanaryStepState string + +const ( + CanaryStepStateUpgrade CanaryStepState = "StepUpgrade" + CanaryStepStateTrafficRouting CanaryStepState = "StepTrafficRouting" + CanaryStepStateMetricsAnalysis CanaryStepState = "StepMetricsAnalysis" + CanaryStepStatePaused CanaryStepState = "StepPaused" + CanaryStepStateReady CanaryStepState = "StepReady" + CanaryStepStateCompleted CanaryStepState = "Completed" +) + +// RolloutPhase are a set of phases that this rollout +type RolloutPhase string + +const ( + // RolloutPhaseInitial indicates a rollout is Initial + RolloutPhaseInitial RolloutPhase = "Initial" + // RolloutPhaseHealthy indicates a rollout is healthy + RolloutPhaseHealthy RolloutPhase = "Healthy" + // RolloutPhaseProgressing indicates a rollout is not yet healthy but still making progress towards a healthy state + RolloutPhaseProgressing RolloutPhase = "Progressing" + // RolloutPhaseTerminating indicates a rollout is terminated + RolloutPhaseTerminating RolloutPhase = "Terminating" + // RolloutPhaseDisabled indicates a rollout is disabled + RolloutPhaseDisabled RolloutPhase = "Disabled" + // RolloutPhaseDisabling indicates a rollout is disabling and releasing resources + RolloutPhaseDisabling RolloutPhase = "Disabling" +) + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="STATUS",type="string",JSONPath=".status.phase",description="The rollout status phase" +// +kubebuilder:printcolumn:name="CANARY_STEP",type="integer",JSONPath=".status.canaryStatus.currentStepIndex",description="The rollout canary status step" +// +kubebuilder:printcolumn:name="CANARY_STATE",type="string",JSONPath=".status.canaryStatus.currentStepState",description="The rollout canary status step state" +// +kubebuilder:printcolumn:name="MESSAGE",type="string",JSONPath=".status.message",description="The rollout canary status message" +// +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=".metadata.creationTimestamp" +// +kubebuilder:storageversion +// Rollout is the Schema for the rollouts API +type Rollout struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec RolloutSpec `json:"spec,omitempty"` + Status RolloutStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// RolloutList contains a list of Rollout +type RolloutList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Rollout `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Rollout{}, &RolloutList{}) +} diff --git a/api/v1beta1/rollouthistory_conversion.go b/api/v1beta1/rollouthistory_conversion.go new file mode 100644 index 0000000..25f4a75 --- /dev/null +++ b/api/v1beta1/rollouthistory_conversion.go @@ -0,0 +1,3 @@ +package v1beta1 + +func (*RolloutHistory) Hub() {} diff --git a/api/v1beta1/rollouthistory_types.go b/api/v1beta1/rollouthistory_types.go new file mode 100644 index 0000000..16b4076 --- /dev/null +++ b/api/v1beta1/rollouthistory_types.go @@ -0,0 +1,151 @@ +/* +Copyright 2022 The Kruise Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// RolloutHistorySpec defines the desired state of RolloutHistory +type RolloutHistorySpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Rollout indicates information of the rollout related with rollouthistory + Rollout RolloutInfo `json:"rollout,omitempty"` + // Workload indicates information of the workload, such as cloneset, deployment, advanced statefulset + Workload WorkloadInfo `json:"workload,omitempty"` + // Service indicates information of the service related with workload + Service ServiceInfo `json:"service,omitempty"` + // TrafficRouting indicates information of traffic route related with workload + TrafficRouting TrafficRoutingInfo `json:"trafficRouting,omitempty"` +} + +type NameAndSpecData struct { + // Name indicates the name of object ref, such as rollout name, workload name, ingress name, etc. + Name string `json:"name"` + // Data indecates the spec of object ref + // +kubebuilder:pruning:PreserveUnknownFields + // +kubebuilder:validation:Schemaless + Data runtime.RawExtension `json:"data,omitempty"` +} + +// RolloutInfo indicates information of the rollout related +type RolloutInfo struct { + // RolloutID indicates the new rollout + // if there is no new RolloutID this time, ignore it and not execute RolloutHistory + RolloutID string `json:"rolloutID"` + NameAndSpecData `json:",inline"` +} + +// ServiceInfo indicates information of the service related +type ServiceInfo struct { + NameAndSpecData `json:",inline"` +} + +// TrafficRoutingInfo indicates information of Gateway API or Ingress +type TrafficRoutingInfo struct { + // IngressRef indicates information of ingress + // +optional + Ingress *IngressInfo `json:"ingress,omitempty"` + // HTTPRouteRef indacates information of Gateway API + // +optional + HTTPRoute *HTTPRouteInfo `json:"httpRoute,omitempty"` +} + +// IngressInfo indicates information of the ingress related +type IngressInfo struct { + NameAndSpecData `json:",inline"` +} + +// HTTPRouteInfo indicates information of gateway API +type HTTPRouteInfo struct { + NameAndSpecData `json:",inline"` +} + +// WorkloadInfo indicates information of the workload, such as cloneset, deployment, advanced statefulset +type WorkloadInfo struct { + metav1.TypeMeta `json:",inline"` + NameAndSpecData `json:",inline"` +} + +// RolloutHistoryStatus defines the observed state of RolloutHistory +type RolloutHistoryStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Phase indicates phase of RolloutHistory, just "" or "completed" + Phase string `json:"phase,omitempty"` + // CanarySteps indicates the pods released each step + CanarySteps []CanaryStepInfo `json:"canarySteps,omitempty"` +} + +// CanaryStepInfo indicates the pods for a revision +type CanaryStepInfo struct { + // CanaryStepIndex indicates step this revision + CanaryStepIndex int32 `json:"canaryStepIndex,omitempty"` + // Pods indicates the pods information + Pods []Pod `json:"pods,omitempty"` +} + +// Pod indicates the information of a pod, including name, ip, node_name. +type Pod struct { + // Name indicates the node name + Name string `json:"name,omitempty"` + // IP indicates the pod ip + IP string `json:"ip,omitempty"` + // NodeName indicates the node which pod is located at + NodeName string `json:"nodeName,omitempty"` + // todo + // State indicates whether the pod is ready or not + // State string `json:"state, omitempty"` +} + +// Phase indicates rollouthistory phase +const ( + PhaseCompleted string = "completed" +) + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// RolloutHistory is the Schema for the rollouthistories API +type RolloutHistory struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec RolloutHistorySpec `json:"spec,omitempty"` + Status RolloutHistoryStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// RolloutHistoryList contains a list of RolloutHistory +type RolloutHistoryList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []RolloutHistory `json:"items"` +} + +func init() { + SchemeBuilder.Register(&RolloutHistory{}, &RolloutHistoryList{}) +} diff --git a/api/v1beta1/trafficrouting_conversion.go b/api/v1beta1/trafficrouting_conversion.go new file mode 100644 index 0000000..3cc5cf7 --- /dev/null +++ b/api/v1beta1/trafficrouting_conversion.go @@ -0,0 +1,3 @@ +package v1beta1 + +func (*TrafficRouting) Hub() {} diff --git a/api/v1beta1/trafficrouting_types.go b/api/v1beta1/trafficrouting_types.go new file mode 100644 index 0000000..660e600 --- /dev/null +++ b/api/v1beta1/trafficrouting_types.go @@ -0,0 +1,154 @@ +/* +Copyright 2023 The Kruise Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" +) + +const ( + ProgressingRolloutFinalizerPrefix = "progressing.rollouts.kruise.io" +) + +// TrafficRoutingRef hosts all the different configuration for supported service meshes to enable more fine-grained traffic routing +type TrafficRoutingRef struct { + // Service holds the name of a service which selects pods with stable version and don't select any pods with canary version. + Service string `json:"service"` + // Optional duration in seconds the traffic provider(e.g. nginx ingress controller) consumes the service, ingress configuration changes gracefully. + GracePeriodSeconds int32 `json:"gracePeriodSeconds,omitempty"` + // Ingress holds Ingress specific configuration to route traffic, e.g. Nginx, Alb. + Ingress *IngressTrafficRouting `json:"ingress,omitempty"` + // Gateway holds Gateway specific configuration to route traffic + // Gateway configuration only supports >= v0.4.0 (v1alpha2). + Gateway *GatewayTrafficRouting `json:"gateway,omitempty"` +} + +// IngressTrafficRouting configuration for ingress controller to control traffic routing +type IngressTrafficRouting struct { + // ClassType refers to the type of `Ingress`. + // current support nginx, aliyun-alb. default is nginx. + // +optional + ClassType string `json:"classType,omitempty"` + // Name refers to the name of an `Ingress` resource in the same namespace as the `Rollout` + Name string `json:"name"` +} + +// GatewayTrafficRouting configuration for gateway api +type GatewayTrafficRouting struct { + // HTTPRouteName refers to the name of an `HTTPRoute` resource in the same namespace as the `Rollout` + HTTPRouteName *string `json:"httpRouteName,omitempty"` + // TCPRouteName *string `json:"tcpRouteName,omitempty"` + // UDPRouteName *string `json:"udpRouteName,omitempty"` +} + +type TrafficRoutingSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // ObjectRef indicates trafficRouting ref + ObjectRef []TrafficRoutingRef `json:"objectRef"` + // trafficrouting strategy + Strategy TrafficRoutingStrategy `json:"strategy"` +} + +type TrafficRoutingStrategy struct { + // Weight indicate how many percentage of traffic the canary pods should receive + // +optional + Weight *int32 `json:"weight,omitempty"` + // Set overwrites the request with the given header (name, value) + // before the action. + // + // Input: + // GET /foo HTTP/1.1 + // my-header: foo + // + // requestHeaderModifier: + // set: + // - name: "my-header" + // value: "bar" + // + // Output: + // GET /foo HTTP/1.1 + // my-header: bar + // + // +optional + RequestHeaderModifier *gatewayv1alpha2.HTTPRequestHeaderFilter `json:"requestHeaderModifier,omitempty"` + // Matches define conditions used for matching the incoming HTTP requests to canary service. + // Each match is independent, i.e. this rule will be matched if **any** one of the matches is satisfied. + // If Gateway API, current only support one match. + // And cannot support both weight and matches, if both are configured, then matches takes precedence. + Matches []HttpRouteMatch `json:"matches,omitempty"` +} + +type TrafficRoutingStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // observedGeneration is the most recent generation observed for this Rollout. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // Phase is the trafficRouting phase. + Phase TrafficRoutingPhase `json:"phase,omitempty"` + // Message provides details on why the rollout is in its current phase + Message string `json:"message,omitempty"` +} + +// TrafficRoutingPhase are a set of phases that this rollout +type TrafficRoutingPhase string + +const ( + // TrafficRoutingPhaseInitial indicates a traffic routing is Initial + TrafficRoutingPhaseInitial TrafficRoutingPhase = "Initial" + // TrafficRoutingPhaseHealthy indicates a traffic routing is healthy. + // This means that Ingress and Service Resources exist. + TrafficRoutingPhaseHealthy TrafficRoutingPhase = "Healthy" + // TrafficRoutingPhaseProgressing indicates a traffic routing is not yet healthy but still making progress towards a healthy state + TrafficRoutingPhaseProgressing TrafficRoutingPhase = "Progressing" + // TrafficRoutingPhaseFinalizing indicates the trafficRouting progress is complete, and is running recycle operations. + TrafficRoutingPhaseFinalizing TrafficRoutingPhase = "Finalizing" + // TrafficRoutingPhaseTerminating indicates a traffic routing is terminated + TrafficRoutingPhaseTerminating TrafficRoutingPhase = "Terminating" +) + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="STATUS",type="string",JSONPath=".status.phase",description="The TrafficRouting status phase" +// +kubebuilder:printcolumn:name="MESSAGE",type="string",JSONPath=".status.message",description="The TrafficRouting canary status message" +// +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=".metadata.creationTimestamp" +// +kubebuilder:storageversion +// TrafficRouting is the Schema for the TrafficRoutings API +type TrafficRouting struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec TrafficRoutingSpec `json:"spec,omitempty"` + Status TrafficRoutingStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// TrafficRoutingList contains a list of TrafficRouting +type TrafficRoutingList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []TrafficRouting `json:"items"` +} + +func init() { + SchemeBuilder.Register(&TrafficRouting{}, &TrafficRoutingList{}) +} diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 0000000..3d59aa8 --- /dev/null +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,979 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2022 The Kruise Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/gateway-api/apis/v1alpha2" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BatchRelease) DeepCopyInto(out *BatchRelease) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BatchRelease. +func (in *BatchRelease) DeepCopy() *BatchRelease { + if in == nil { + return nil + } + out := new(BatchRelease) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BatchRelease) 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 *BatchReleaseCanaryStatus) DeepCopyInto(out *BatchReleaseCanaryStatus) { + *out = *in + if in.BatchReadyTime != nil { + in, out := &in.BatchReadyTime, &out.BatchReadyTime + *out = (*in).DeepCopy() + } + if in.NoNeedUpdateReplicas != nil { + in, out := &in.NoNeedUpdateReplicas, &out.NoNeedUpdateReplicas + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BatchReleaseCanaryStatus. +func (in *BatchReleaseCanaryStatus) DeepCopy() *BatchReleaseCanaryStatus { + if in == nil { + return nil + } + out := new(BatchReleaseCanaryStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BatchReleaseList) DeepCopyInto(out *BatchReleaseList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]BatchRelease, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BatchReleaseList. +func (in *BatchReleaseList) DeepCopy() *BatchReleaseList { + if in == nil { + return nil + } + out := new(BatchReleaseList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BatchReleaseList) 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 *BatchReleaseSpec) DeepCopyInto(out *BatchReleaseSpec) { + *out = *in + in.TargetRef.DeepCopyInto(&out.TargetRef) + in.ReleasePlan.DeepCopyInto(&out.ReleasePlan) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BatchReleaseSpec. +func (in *BatchReleaseSpec) DeepCopy() *BatchReleaseSpec { + if in == nil { + return nil + } + out := new(BatchReleaseSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BatchReleaseStatus) DeepCopyInto(out *BatchReleaseStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]RolloutCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.CanaryStatus.DeepCopyInto(&out.CanaryStatus) + if in.CollisionCount != nil { + in, out := &in.CollisionCount, &out.CollisionCount + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BatchReleaseStatus. +func (in *BatchReleaseStatus) DeepCopy() *BatchReleaseStatus { + if in == nil { + return nil + } + out := new(BatchReleaseStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CanaryStatus) DeepCopyInto(out *CanaryStatus) { + *out = *in + if in.LastUpdateTime != nil { + in, out := &in.LastUpdateTime, &out.LastUpdateTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryStatus. +func (in *CanaryStatus) DeepCopy() *CanaryStatus { + if in == nil { + return nil + } + out := new(CanaryStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CanaryStep) DeepCopyInto(out *CanaryStep) { + *out = *in + in.TrafficRoutingStrategy.DeepCopyInto(&out.TrafficRoutingStrategy) + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(intstr.IntOrString) + **out = **in + } + in.Pause.DeepCopyInto(&out.Pause) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryStep. +func (in *CanaryStep) DeepCopy() *CanaryStep { + if in == nil { + return nil + } + out := new(CanaryStep) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CanaryStepInfo) DeepCopyInto(out *CanaryStepInfo) { + *out = *in + if in.Pods != nil { + in, out := &in.Pods, &out.Pods + *out = make([]Pod, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryStepInfo. +func (in *CanaryStepInfo) DeepCopy() *CanaryStepInfo { + if in == nil { + return nil + } + out := new(CanaryStepInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CanaryStrategy) DeepCopyInto(out *CanaryStrategy) { + *out = *in + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = make([]CanaryStep, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.TrafficRoutings != nil { + in, out := &in.TrafficRoutings, &out.TrafficRoutings + *out = make([]TrafficRoutingRef, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.FailureThreshold != nil { + in, out := &in.FailureThreshold, &out.FailureThreshold + *out = new(intstr.IntOrString) + **out = **in + } + if in.PatchPodTemplateMetadata != nil { + in, out := &in.PatchPodTemplateMetadata, &out.PatchPodTemplateMetadata + *out = new(PatchPodTemplateMetadata) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryStrategy. +func (in *CanaryStrategy) DeepCopy() *CanaryStrategy { + if in == nil { + return nil + } + out := new(CanaryStrategy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayTrafficRouting) DeepCopyInto(out *GatewayTrafficRouting) { + *out = *in + if in.HTTPRouteName != nil { + in, out := &in.HTTPRouteName, &out.HTTPRouteName + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayTrafficRouting. +func (in *GatewayTrafficRouting) DeepCopy() *GatewayTrafficRouting { + if in == nil { + return nil + } + out := new(GatewayTrafficRouting) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HTTPRouteInfo) DeepCopyInto(out *HTTPRouteInfo) { + *out = *in + in.NameAndSpecData.DeepCopyInto(&out.NameAndSpecData) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRouteInfo. +func (in *HTTPRouteInfo) DeepCopy() *HTTPRouteInfo { + if in == nil { + return nil + } + out := new(HTTPRouteInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HttpRouteMatch) DeepCopyInto(out *HttpRouteMatch) { + *out = *in + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]v1alpha2.HTTPHeaderMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HttpRouteMatch. +func (in *HttpRouteMatch) DeepCopy() *HttpRouteMatch { + if in == nil { + return nil + } + out := new(HttpRouteMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IngressInfo) DeepCopyInto(out *IngressInfo) { + *out = *in + in.NameAndSpecData.DeepCopyInto(&out.NameAndSpecData) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressInfo. +func (in *IngressInfo) DeepCopy() *IngressInfo { + if in == nil { + return nil + } + out := new(IngressInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IngressTrafficRouting) DeepCopyInto(out *IngressTrafficRouting) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressTrafficRouting. +func (in *IngressTrafficRouting) DeepCopy() *IngressTrafficRouting { + if in == nil { + return nil + } + out := new(IngressTrafficRouting) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NameAndSpecData) DeepCopyInto(out *NameAndSpecData) { + *out = *in + in.Data.DeepCopyInto(&out.Data) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NameAndSpecData. +func (in *NameAndSpecData) DeepCopy() *NameAndSpecData { + if in == nil { + return nil + } + out := new(NameAndSpecData) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectRef) DeepCopyInto(out *ObjectRef) { + *out = *in + if in.WorkloadRef != nil { + in, out := &in.WorkloadRef, &out.WorkloadRef + *out = new(WorkloadRef) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectRef. +func (in *ObjectRef) DeepCopy() *ObjectRef { + if in == nil { + return nil + } + out := new(ObjectRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PatchPodTemplateMetadata) DeepCopyInto(out *PatchPodTemplateMetadata) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PatchPodTemplateMetadata. +func (in *PatchPodTemplateMetadata) DeepCopy() *PatchPodTemplateMetadata { + if in == nil { + return nil + } + out := new(PatchPodTemplateMetadata) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Pod) DeepCopyInto(out *Pod) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Pod. +func (in *Pod) DeepCopy() *Pod { + if in == nil { + return nil + } + out := new(Pod) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReleaseBatch) DeepCopyInto(out *ReleaseBatch) { + *out = *in + out.CanaryReplicas = in.CanaryReplicas +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReleaseBatch. +func (in *ReleaseBatch) DeepCopy() *ReleaseBatch { + if in == nil { + return nil + } + out := new(ReleaseBatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReleasePlan) DeepCopyInto(out *ReleasePlan) { + *out = *in + if in.Batches != nil { + in, out := &in.Batches, &out.Batches + *out = make([]ReleaseBatch, len(*in)) + copy(*out, *in) + } + if in.BatchPartition != nil { + in, out := &in.BatchPartition, &out.BatchPartition + *out = new(int32) + **out = **in + } + if in.FailureThreshold != nil { + in, out := &in.FailureThreshold, &out.FailureThreshold + *out = new(intstr.IntOrString) + **out = **in + } + if in.PatchPodTemplateMetadata != nil { + in, out := &in.PatchPodTemplateMetadata, &out.PatchPodTemplateMetadata + *out = new(PatchPodTemplateMetadata) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReleasePlan. +func (in *ReleasePlan) DeepCopy() *ReleasePlan { + if in == nil { + return nil + } + out := new(ReleasePlan) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Rollout) DeepCopyInto(out *Rollout) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Rollout. +func (in *Rollout) DeepCopy() *Rollout { + if in == nil { + return nil + } + out := new(Rollout) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Rollout) 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 *RolloutCondition) DeepCopyInto(out *RolloutCondition) { + *out = *in + in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime) + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutCondition. +func (in *RolloutCondition) DeepCopy() *RolloutCondition { + if in == nil { + return nil + } + out := new(RolloutCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutHistory) DeepCopyInto(out *RolloutHistory) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutHistory. +func (in *RolloutHistory) DeepCopy() *RolloutHistory { + if in == nil { + return nil + } + out := new(RolloutHistory) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RolloutHistory) 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 *RolloutHistoryList) DeepCopyInto(out *RolloutHistoryList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]RolloutHistory, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutHistoryList. +func (in *RolloutHistoryList) DeepCopy() *RolloutHistoryList { + if in == nil { + return nil + } + out := new(RolloutHistoryList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RolloutHistoryList) 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 *RolloutHistorySpec) DeepCopyInto(out *RolloutHistorySpec) { + *out = *in + in.Rollout.DeepCopyInto(&out.Rollout) + in.Workload.DeepCopyInto(&out.Workload) + in.Service.DeepCopyInto(&out.Service) + in.TrafficRouting.DeepCopyInto(&out.TrafficRouting) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutHistorySpec. +func (in *RolloutHistorySpec) DeepCopy() *RolloutHistorySpec { + if in == nil { + return nil + } + out := new(RolloutHistorySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutHistoryStatus) DeepCopyInto(out *RolloutHistoryStatus) { + *out = *in + if in.CanarySteps != nil { + in, out := &in.CanarySteps, &out.CanarySteps + *out = make([]CanaryStepInfo, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutHistoryStatus. +func (in *RolloutHistoryStatus) DeepCopy() *RolloutHistoryStatus { + if in == nil { + return nil + } + out := new(RolloutHistoryStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutInfo) DeepCopyInto(out *RolloutInfo) { + *out = *in + in.NameAndSpecData.DeepCopyInto(&out.NameAndSpecData) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutInfo. +func (in *RolloutInfo) DeepCopy() *RolloutInfo { + if in == nil { + return nil + } + out := new(RolloutInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutList) DeepCopyInto(out *RolloutList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Rollout, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutList. +func (in *RolloutList) DeepCopy() *RolloutList { + if in == nil { + return nil + } + out := new(RolloutList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RolloutList) 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 *RolloutPause) DeepCopyInto(out *RolloutPause) { + *out = *in + if in.Duration != nil { + in, out := &in.Duration, &out.Duration + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutPause. +func (in *RolloutPause) DeepCopy() *RolloutPause { + if in == nil { + return nil + } + out := new(RolloutPause) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutSpec) DeepCopyInto(out *RolloutSpec) { + *out = *in + in.ObjectRef.DeepCopyInto(&out.ObjectRef) + in.Strategy.DeepCopyInto(&out.Strategy) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutSpec. +func (in *RolloutSpec) DeepCopy() *RolloutSpec { + if in == nil { + return nil + } + out := new(RolloutSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutStatus) DeepCopyInto(out *RolloutStatus) { + *out = *in + if in.CanaryStatus != nil { + in, out := &in.CanaryStatus, &out.CanaryStatus + *out = new(CanaryStatus) + (*in).DeepCopyInto(*out) + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]RolloutCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutStatus. +func (in *RolloutStatus) DeepCopy() *RolloutStatus { + if in == nil { + return nil + } + out := new(RolloutStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutStrategy) DeepCopyInto(out *RolloutStrategy) { + *out = *in + if in.Canary != nil { + in, out := &in.Canary, &out.Canary + *out = new(CanaryStrategy) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutStrategy. +func (in *RolloutStrategy) DeepCopy() *RolloutStrategy { + if in == nil { + return nil + } + out := new(RolloutStrategy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceInfo) DeepCopyInto(out *ServiceInfo) { + *out = *in + in.NameAndSpecData.DeepCopyInto(&out.NameAndSpecData) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceInfo. +func (in *ServiceInfo) DeepCopy() *ServiceInfo { + if in == nil { + return nil + } + out := new(ServiceInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficRouting) DeepCopyInto(out *TrafficRouting) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficRouting. +func (in *TrafficRouting) DeepCopy() *TrafficRouting { + if in == nil { + return nil + } + out := new(TrafficRouting) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TrafficRouting) 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 *TrafficRoutingInfo) DeepCopyInto(out *TrafficRoutingInfo) { + *out = *in + if in.Ingress != nil { + in, out := &in.Ingress, &out.Ingress + *out = new(IngressInfo) + (*in).DeepCopyInto(*out) + } + if in.HTTPRoute != nil { + in, out := &in.HTTPRoute, &out.HTTPRoute + *out = new(HTTPRouteInfo) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficRoutingInfo. +func (in *TrafficRoutingInfo) DeepCopy() *TrafficRoutingInfo { + if in == nil { + return nil + } + out := new(TrafficRoutingInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficRoutingList) DeepCopyInto(out *TrafficRoutingList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]TrafficRouting, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficRoutingList. +func (in *TrafficRoutingList) DeepCopy() *TrafficRoutingList { + if in == nil { + return nil + } + out := new(TrafficRoutingList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TrafficRoutingList) 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 *TrafficRoutingRef) DeepCopyInto(out *TrafficRoutingRef) { + *out = *in + if in.Ingress != nil { + in, out := &in.Ingress, &out.Ingress + *out = new(IngressTrafficRouting) + **out = **in + } + if in.Gateway != nil { + in, out := &in.Gateway, &out.Gateway + *out = new(GatewayTrafficRouting) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficRoutingRef. +func (in *TrafficRoutingRef) DeepCopy() *TrafficRoutingRef { + if in == nil { + return nil + } + out := new(TrafficRoutingRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficRoutingSpec) DeepCopyInto(out *TrafficRoutingSpec) { + *out = *in + if in.ObjectRef != nil { + in, out := &in.ObjectRef, &out.ObjectRef + *out = make([]TrafficRoutingRef, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.Strategy.DeepCopyInto(&out.Strategy) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficRoutingSpec. +func (in *TrafficRoutingSpec) DeepCopy() *TrafficRoutingSpec { + if in == nil { + return nil + } + out := new(TrafficRoutingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficRoutingStatus) DeepCopyInto(out *TrafficRoutingStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficRoutingStatus. +func (in *TrafficRoutingStatus) DeepCopy() *TrafficRoutingStatus { + if in == nil { + return nil + } + out := new(TrafficRoutingStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrafficRoutingStrategy) DeepCopyInto(out *TrafficRoutingStrategy) { + *out = *in + if in.Weight != nil { + in, out := &in.Weight, &out.Weight + *out = new(int32) + **out = **in + } + if in.RequestHeaderModifier != nil { + in, out := &in.RequestHeaderModifier, &out.RequestHeaderModifier + *out = new(v1alpha2.HTTPRequestHeaderFilter) + (*in).DeepCopyInto(*out) + } + if in.Matches != nil { + in, out := &in.Matches, &out.Matches + *out = make([]HttpRouteMatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrafficRoutingStrategy. +func (in *TrafficRoutingStrategy) DeepCopy() *TrafficRoutingStrategy { + if in == nil { + return nil + } + out := new(TrafficRoutingStrategy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkloadInfo) DeepCopyInto(out *WorkloadInfo) { + *out = *in + out.TypeMeta = in.TypeMeta + in.NameAndSpecData.DeepCopyInto(&out.NameAndSpecData) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadInfo. +func (in *WorkloadInfo) DeepCopy() *WorkloadInfo { + if in == nil { + return nil + } + out := new(WorkloadInfo) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkloadRef) DeepCopyInto(out *WorkloadRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadRef. +func (in *WorkloadRef) DeepCopy() *WorkloadRef { + if in == nil { + return nil + } + out := new(WorkloadRef) + in.DeepCopyInto(out) + return out +} diff --git a/config/certmanager/certificate.yaml b/config/certmanager/certificate.yaml new file mode 100644 index 0000000..db4f939 --- /dev/null +++ b/config/certmanager/certificate.yaml @@ -0,0 +1,39 @@ +# The following manifests contain a self-signed issuer CR and a certificate CR. +# More document can be found at https://docs.cert-manager.io +# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes. +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/name: issuer + app.kubernetes.io/instance: selfsigned-issuer + app.kubernetes.io/component: certificate + app.kubernetes.io/created-by: rollouts + app.kubernetes.io/part-of: rollouts + app.kubernetes.io/managed-by: kustomize + name: selfsigned-issuer + namespace: system +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/name: certificate + app.kubernetes.io/instance: serving-cert + app.kubernetes.io/component: certificate + app.kubernetes.io/created-by: rollouts + app.kubernetes.io/part-of: rollouts + app.kubernetes.io/managed-by: kustomize + name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml + namespace: system +spec: + # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize + dnsNames: + - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc + - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local + issuerRef: + kind: Issuer + name: selfsigned-issuer + secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize diff --git a/config/certmanager/kustomization.yaml b/config/certmanager/kustomization.yaml new file mode 100644 index 0000000..bebea5a --- /dev/null +++ b/config/certmanager/kustomization.yaml @@ -0,0 +1,5 @@ +resources: +- certificate.yaml + +configurations: +- kustomizeconfig.yaml diff --git a/config/certmanager/kustomizeconfig.yaml b/config/certmanager/kustomizeconfig.yaml new file mode 100644 index 0000000..e631f77 --- /dev/null +++ b/config/certmanager/kustomizeconfig.yaml @@ -0,0 +1,16 @@ +# This configuration is for teaching kustomize how to update name ref and var substitution +nameReference: +- kind: Issuer + group: cert-manager.io + fieldSpecs: + - kind: Certificate + group: cert-manager.io + path: spec/issuerRef/name + +varReference: +- kind: Certificate + group: cert-manager.io + path: spec/commonName +- kind: Certificate + group: cert-manager.io + path: spec/dnsNames diff --git a/config/crd/bases/rollouts.kruise.io_batchreleases.yaml b/config/crd/bases/rollouts.kruise.io_batchreleases.yaml index 421b07f..8156159 100644 --- a/config/crd/bases/rollouts.kruise.io_batchreleases.yaml +++ b/config/crd/bases/rollouts.kruise.io_batchreleases.yaml @@ -273,6 +273,263 @@ spec: storage: true subresources: status: {} + - additionalPrinterColumns: + - jsonPath: .spec.targetReference.workloadRef.kind + name: KIND + type: string + - jsonPath: .status.phase + name: PHASE + type: string + - jsonPath: .status.canaryStatus.currentBatch + name: BATCH + type: integer + - jsonPath: .status.canaryStatus.batchState + name: BATCH-STATE + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1beta1 + 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: BatchReleaseSpec defines how to describe an update between + different compRevision + properties: + releasePlan: + description: ReleasePlan is the details on how to rollout the resources + properties: + batchPartition: + description: All pods in the batches up to the batchPartition + (included) will have the target resource specification while + the rest still is the stable revision. This is designed for + the operators to manually rollout. Default is nil, which means + no partition and will release all batches. BatchPartition start + from 0. + format: int32 + type: integer + batches: + description: 'Batches is the details on each batch of the ReleasePlan. + Users can specify their batch plan in this field, such as: batches: + - canaryReplicas: 1 # batches 0 - canaryReplicas: 2 # batches + 1 - canaryReplicas: 5 # batches 2 Not that these canaryReplicas + should be a non-decreasing sequence.' + items: + description: ReleaseBatch is used to describe how each batch + release should be + properties: + canaryReplicas: + anyOf: + - type: integer + - type: string + description: 'CanaryReplicas is the number of upgraded pods + that should have in this batch. it can be an absolute + number (ex: 5) or a percentage of workload replicas. batches[i].canaryReplicas + should less than or equal to batches[j].canaryReplicas + if i < j.' + x-kubernetes-int-or-string: true + required: + - canaryReplicas + type: object + type: array + failureThreshold: + anyOf: + - type: integer + - type: string + description: FailureThreshold indicates how many failed pods can + be tolerated in all upgraded pods. Only when FailureThreshold + are satisfied, Rollout can enter ready state. If FailureThreshold + is nil, Rollout will use the MaxUnavailable of workload as its + FailureThreshold. Defaults to nil. + x-kubernetes-int-or-string: true + finalizingPolicy: + description: FinalizingPolicy define the behavior of controller + when phase enter Finalizing Defaults to "Immediate" + type: string + patchPodTemplateMetadata: + description: PatchPodTemplateMetadata indicates patch configuration(e.g. + labels, annotations) to the canary deployment podTemplateSpec.metadata + only support for canary deployment + properties: + annotations: + additionalProperties: + type: string + description: annotations + type: object + labels: + additionalProperties: + type: string + description: labels + type: object + type: object + rolloutID: + description: RolloutID indicates an id for each rollout progress + type: string + type: object + targetReference: + description: TargetRef contains the GVK and name of the workload that + we need to upgrade to. + properties: + workloadRef: + description: WorkloadRef contains enough information to let you + identify a workload for Rollout Batch release of the bypass + properties: + apiVersion: + description: API Version of the referent + type: string + kind: + description: Kind of the referent + type: string + name: + description: Name of the referent + type: string + required: + - apiVersion + - kind + - name + type: object + type: object + required: + - releasePlan + - targetReference + type: object + status: + description: BatchReleaseStatus defines the observed state of a release + plan + properties: + canaryStatus: + description: CanaryStatus describes the state of the canary rollout. + properties: + batchReadyTime: + description: BatchReadyTime is the ready timestamp of the current + batch or the last batch. This field is updated once a batch + ready, and the batches[x].pausedSeconds relies on this field + to calculate the real-time duration. + format: date-time + type: string + batchState: + description: CurrentBatchState indicates the release state of + the current batch. + type: string + currentBatch: + description: The current batch the rollout is working on/blocked, + it starts from 0 + format: int32 + type: integer + noNeedUpdateReplicas: + description: the number of pods that no need to rollback in rollback + scene. + format: int32 + type: integer + updatedReadyReplicas: + description: UpdatedReadyReplicas is the number upgraded Pods + that have a Ready Condition. + format: int32 + type: integer + updatedReplicas: + description: UpdatedReplicas is the number of upgraded Pods. + format: int32 + type: integer + required: + - currentBatch + type: object + collisionCount: + description: Count of hash collisions for creating canary Deployment. + The controller uses this field as a collision avoidance mechanism + when it needs to create the name for the newest canary Deployment. + format: int32 + type: integer + conditions: + description: Conditions represents the observed process state of each + phase during executing the release plan. + items: + description: RolloutCondition describes the state of a rollout at + a certain point. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. + format: date-time + type: string + lastUpdateTime: + description: The last time this condition was updated. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Phase of the condition, one of True, False, Unknown. + type: string + type: + description: Type of rollout condition. + type: string + required: + - message + - reason + - status + - type + type: object + type: array + observedGeneration: + description: ObservedGeneration is the most recent generation observed + for this BatchRelease. It corresponds to this BatchRelease's generation, + which is updated on mutation by the API Server, and only if BatchRelease + Spec was changed, its generation will increase 1. + format: int64 + type: integer + observedReleasePlanHash: + description: ObservedReleasePlanHash is a hash code of observed itself + spec.releasePlan. + type: string + observedRolloutID: + description: ObservedRolloutID is the most recent rollout-id observed + for this BatchRelease. If RolloutID was changed, we will restart + to roll out from batch 0, to ensure the batch-id and rollout-id + labels of Pods are correct. + type: string + observedWorkloadReplicas: + description: ObservedWorkloadReplicas is observed replicas of target + referenced workload. This field is designed to deal with scaling + event during rollout, if this field changed, it means that the workload + is scaling during rollout. + format: int32 + type: integer + phase: + description: Phase is the release plan phase, which indicates the + current state of release plan state machine in BatchRelease controller. + type: string + stableRevision: + description: StableRevision is the pod-template-hash of stable revision + pod template. + type: string + updateRevision: + description: UpdateRevision is the pod-template-hash of update revision + pod template. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} status: acceptedNames: kind: "" diff --git a/config/crd/bases/rollouts.kruise.io_rollouthistories.yaml b/config/crd/bases/rollouts.kruise.io_rollouthistories.yaml index 23bd9c6..a3741c6 100644 --- a/config/crd/bases/rollouts.kruise.io_rollouthistories.yaml +++ b/config/crd/bases/rollouts.kruise.io_rollouthistories.yaml @@ -168,6 +168,158 @@ spec: storage: true subresources: status: {} + - name: v1beta1 + schema: + openAPIV3Schema: + description: RolloutHistory is the Schema for the rollouthistories API + 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: RolloutHistorySpec defines the desired state of RolloutHistory + properties: + rollout: + description: Rollout indicates information of the rollout related + with rollouthistory + properties: + data: + description: Data indecates the spec of object ref + x-kubernetes-preserve-unknown-fields: true + name: + description: Name indicates the name of object ref, such as rollout + name, workload name, ingress name, etc. + type: string + rolloutID: + description: RolloutID indicates the new rollout if there is no + new RolloutID this time, ignore it and not execute RolloutHistory + type: string + required: + - name + - rolloutID + type: object + service: + description: Service indicates information of the service related + with workload + properties: + data: + description: Data indecates the spec of object ref + x-kubernetes-preserve-unknown-fields: true + name: + description: Name indicates the name of object ref, such as rollout + name, workload name, ingress name, etc. + type: string + required: + - name + type: object + trafficRouting: + description: TrafficRouting indicates information of traffic route + related with workload + properties: + httpRoute: + description: HTTPRouteRef indacates information of Gateway API + properties: + data: + description: Data indecates the spec of object ref + x-kubernetes-preserve-unknown-fields: true + name: + description: Name indicates the name of object ref, such as + rollout name, workload name, ingress name, etc. + type: string + required: + - name + type: object + ingress: + description: IngressRef indicates information of ingress + properties: + data: + description: Data indecates the spec of object ref + x-kubernetes-preserve-unknown-fields: true + name: + description: Name indicates the name of object ref, such as + rollout name, workload name, ingress name, etc. + type: string + required: + - name + type: object + type: object + workload: + description: Workload indicates information of the workload, such + as cloneset, deployment, advanced statefulset + 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 + data: + description: Data indecates the spec of object ref + x-kubernetes-preserve-unknown-fields: true + 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 + name: + description: Name indicates the name of object ref, such as rollout + name, workload name, ingress name, etc. + type: string + required: + - name + type: object + type: object + status: + description: RolloutHistoryStatus defines the observed state of RolloutHistory + properties: + canarySteps: + description: CanarySteps indicates the pods released each step + items: + description: CanaryStepInfo indicates the pods for a revision + properties: + canaryStepIndex: + description: CanaryStepIndex indicates step this revision + format: int32 + type: integer + pods: + description: Pods indicates the pods information + items: + description: Pod indicates the information of a pod, including + name, ip, node_name. + properties: + ip: + description: IP indicates the pod ip + type: string + name: + description: Name indicates the node name + type: string + nodeName: + description: NodeName indicates the node which pod is + located at + type: string + type: object + type: array + type: object + type: array + phase: + description: Phase indicates phase of RolloutHistory, just "" or "completed" + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} status: acceptedNames: kind: "" diff --git a/config/crd/bases/rollouts.kruise.io_rollouts.yaml b/config/crd/bases/rollouts.kruise.io_rollouts.yaml index 5e189d6..5e2730c 100644 --- a/config/crd/bases/rollouts.kruise.io_rollouts.yaml +++ b/config/crd/bases/rollouts.kruise.io_rollouts.yaml @@ -505,6 +505,495 @@ spec: storage: true subresources: status: {} + - additionalPrinterColumns: + - description: The rollout status phase + jsonPath: .status.phase + name: STATUS + type: string + - description: The rollout canary status step + jsonPath: .status.canaryStatus.currentStepIndex + name: CANARY_STEP + type: integer + - description: The rollout canary status step state + jsonPath: .status.canaryStatus.currentStepState + name: CANARY_STATE + type: string + - description: The rollout canary status message + jsonPath: .status.message + name: MESSAGE + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: Rollout is the Schema for the rollouts API + 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: RolloutSpec defines the desired state of Rollout + properties: + disabled: + default: false + description: if a rollout disabled, then the rollout would not watch + changes of workload + type: boolean + objectRef: + description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + Important: Run "make" to regenerate code after modifying this file + ObjectRef indicates workload' + properties: + workloadRef: + description: WorkloadRef contains enough information to let you + identify a workload for Rollout Batch release of the bypass + properties: + apiVersion: + description: API Version of the referent + type: string + kind: + description: Kind of the referent + type: string + name: + description: Name of the referent + type: string + required: + - apiVersion + - kind + - name + type: object + type: object + rolloutID: + description: DeprecatedRolloutID is the deprecated field. It is recommended + that configure RolloutId in workload.annotations[rollouts.kruise.io/rollout-id]. + RolloutID should be changed before each workload revision publication. + It is to distinguish consecutive multiple workload publications + and rollout progress. + type: string + strategy: + description: rollout strategy + properties: + canary: + description: CanaryStrategy defines parameters for a Replica Based + Canary + properties: + failureThreshold: + anyOf: + - type: integer + - type: string + description: FailureThreshold indicates how many failed pods + can be tolerated in all upgraded pods. Only when FailureThreshold + are satisfied, Rollout can enter ready state. If FailureThreshold + is nil, Rollout will use the MaxUnavailable of workload + as its FailureThreshold. Defaults to nil. + x-kubernetes-int-or-string: true + patchPodTemplateMetadata: + description: PatchPodTemplateMetadata indicates patch configuration(e.g. + labels, annotations) to the canary deployment podTemplateSpec.metadata + only support for canary deployment + properties: + annotations: + additionalProperties: + type: string + description: annotations + type: object + labels: + additionalProperties: + type: string + description: labels + type: object + type: object + steps: + description: Steps define the order of phases to execute release + in batches(20%, 40%, 60%, 80%, 100%) + items: + description: CanaryStep defines a step of a canary workload. + properties: + matches: + description: Matches define conditions used for matching + the incoming HTTP requests to canary service. Each + match is independent, i.e. this rule will be matched + if **any** one of the matches is satisfied. If Gateway + API, current only support one match. And cannot support + both weight and matches, if both are configured, then + matches takes precedence. + items: + properties: + headers: + description: Headers specifies HTTP request header + matchers. Multiple match values are ANDed together, + meaning, a request must match all the specified + headers to select the route. + items: + description: HTTPHeaderMatch describes how to + select a HTTP route by matching HTTP request + headers. + properties: + name: + description: "Name is the name of the HTTP + Header to be matched. Name matching MUST + be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, only the first entry with + an equivalent name MUST be considered + for a match. Subsequent entries with an + equivalent header name MUST be ignored. + Due to the case-insensitivity of header + names, \"foo\" and \"Foo\" are considered + equivalent. \n When a header is repeated + in an HTTP request, it is implementation-specific + behavior as to how this is represented. + Generally, proxies should follow the guidance + from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 + regarding processing a repeated header, + with special handling for \"Set-Cookie\"." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: "Type specifies how to match + against the value of the header. \n Support: + Core (Exact) \n Support: Custom (RegularExpression) + \n Since RegularExpression HeaderMatchType + has custom conformance, implementations + can support POSIX, PCRE or any other dialects + of regular expressions. Please read the + implementation's documentation to determine + the supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP + Header to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + type: object + type: array + pause: + description: Pause defines a pause stage for a rollout, + manual or auto + properties: + duration: + description: Duration the amount of time to wait + before moving to the next step. + format: int32 + type: integer + type: object + replicas: + anyOf: + - type: integer + - type: string + description: 'Replicas is the number of expected canary + pods in this batch it can be an absolute number (ex: + 5) or a percentage of total pods.' + x-kubernetes-int-or-string: true + requestHeaderModifier: + description: "Set overwrites the request with the given + header (name, value) before the action. \n Input: + \ GET /foo HTTP/1.1 my-header: foo \n requestHeaderModifier: + \ set: - name: \"my-header\" value: \"bar\" + \n Output: GET /foo HTTP/1.1 my-header: bar" + properties: + add: + description: "Add adds the given header(s) (name, + value) to the request before the action. It appends + to any existing values associated with the header + name. \n Input: GET /foo HTTP/1.1 my-header: + foo \n Config: add: - name: \"my-header\" + \ value: \"bar\" \n Output: GET /foo HTTP/1.1 + \ my-header: foo my-header: bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP + Header to be matched. Name matching MUST + be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are + considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the + HTTP request before the action. The value of Remove + is a list of HTTP header names. Note that the + header names are case-insensitive (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo + \ my-header2: bar my-header3: baz \n Config: + \ remove: [\"my-header1\", \"my-header3\"] \n + Output: GET /foo HTTP/1.1 my-header2: bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with the + given header (name, value) before the action. + \n Input: GET /foo HTTP/1.1 my-header: foo + \n Config: set: - name: \"my-header\" value: + \"bar\" \n Output: GET /foo HTTP/1.1 my-header: + bar" + items: + description: HTTPHeader represents an HTTP Header + name and value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP + Header to be matched. Name matching MUST + be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, the first entry with an equivalent + name MUST be considered for a match. Subsequent + entries with an equivalent header name MUST + be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are + considered equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header + to be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + weight: + description: Weight indicate how many percentage of + traffic the canary pods should receive + format: int32 + type: integer + type: object + type: array + trafficRoutings: + description: TrafficRoutings hosts all the supported service + meshes supported to enable more fine-grained traffic routing + and current only support one TrafficRouting + items: + description: TrafficRoutingRef hosts all the different configuration + for supported service meshes to enable more fine-grained + traffic routing + properties: + gateway: + description: Gateway holds Gateway specific configuration + to route traffic Gateway configuration only supports + >= v0.4.0 (v1alpha2). + properties: + httpRouteName: + description: HTTPRouteName refers to the name of + an `HTTPRoute` resource in the same namespace + as the `Rollout` + type: string + type: object + gracePeriodSeconds: + description: Optional duration in seconds the traffic + provider(e.g. nginx ingress controller) consumes the + service, ingress configuration changes gracefully. + format: int32 + type: integer + ingress: + description: Ingress holds Ingress specific configuration + to route traffic, e.g. Nginx, Alb. + properties: + classType: + description: ClassType refers to the type of `Ingress`. + current support nginx, aliyun-alb. default is + nginx. + type: string + name: + description: Name refers to the name of an `Ingress` + resource in the same namespace as the `Rollout` + type: string + required: + - name + type: object + service: + description: Service holds the name of a service which + selects pods with stable version and don't select + any pods with canary version. + type: string + required: + - service + type: object + type: array + type: object + paused: + description: Paused indicates that the Rollout is paused. Default + value is false + type: boolean + type: object + required: + - objectRef + - strategy + type: object + status: + description: RolloutStatus defines the observed state of Rollout + properties: + canaryStatus: + description: Canary describes the state of the canary rollout + properties: + canaryReadyReplicas: + description: CanaryReadyReplicas the numbers of ready canary revision + pods + format: int32 + type: integer + canaryReplicas: + description: CanaryReplicas the numbers of canary revision pods + format: int32 + type: integer + canaryRevision: + description: CanaryRevision is calculated by rollout based on + podTemplateHash, and the internal logic flow uses It may be + different from rs podTemplateHash in different k8s versions, + so it cannot be used as service selector label + type: string + currentStepIndex: + description: CurrentStepIndex defines the current step of the + rollout is on. If the current step index is null, the controller + will execute the rollout. + format: int32 + type: integer + currentStepState: + type: string + lastUpdateTime: + format: date-time + type: string + message: + type: string + observedRolloutID: + description: ObservedRolloutID will record the newest spec.RolloutID + if status.canaryRevision equals to workload.updateRevision + type: string + observedWorkloadGeneration: + description: observedWorkloadGeneration is the most recent generation + observed for this Rollout ref workload generation. + format: int64 + type: integer + podTemplateHash: + description: pod template hash is used as service selector label + type: string + rolloutHash: + description: RolloutHash from rollout.spec object + type: string + stableRevision: + description: StableRevision indicates the revision of stable pods + type: string + required: + - canaryReadyReplicas + - canaryReplicas + - canaryRevision + - currentStepState + - podTemplateHash + type: object + conditions: + description: Conditions a list of conditions a rollout can have. + items: + description: RolloutCondition describes the state of a rollout at + a certain point. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. + format: date-time + type: string + lastUpdateTime: + description: The last time this condition was updated. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Phase of the condition, one of True, False, Unknown. + type: string + type: + description: Type of rollout condition. + type: string + required: + - message + - reason + - status + - type + type: object + type: array + message: + description: Message provides details on why the rollout is in its + current phase + type: string + observedGeneration: + description: observedGeneration is the most recent generation observed + for this Rollout. + format: int64 + type: integer + phase: + description: BlueGreenStatus *BlueGreenStatus `json:"blueGreenStatus,omitempty"` + Phase is the rollout phase. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} status: acceptedNames: kind: "" diff --git a/config/crd/bases/rollouts.kruise.io_trafficroutings.yaml b/config/crd/bases/rollouts.kruise.io_trafficroutings.yaml index 68775c5..b988e53 100644 --- a/config/crd/bases/rollouts.kruise.io_trafficroutings.yaml +++ b/config/crd/bases/rollouts.kruise.io_trafficroutings.yaml @@ -292,6 +292,282 @@ spec: storage: true subresources: status: {} + - additionalPrinterColumns: + - description: The TrafficRouting status phase + jsonPath: .status.phase + name: STATUS + type: string + - description: The TrafficRouting canary status message + jsonPath: .status.message + name: MESSAGE + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: TrafficRouting is the Schema for the TrafficRoutings API + 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: + properties: + objectRef: + description: ObjectRef indicates trafficRouting ref + items: + description: TrafficRoutingRef hosts all the different configuration + for supported service meshes to enable more fine-grained traffic + routing + properties: + gateway: + description: Gateway holds Gateway specific configuration to + route traffic Gateway configuration only supports >= v0.4.0 + (v1alpha2). + properties: + httpRouteName: + description: HTTPRouteName refers to the name of an `HTTPRoute` + resource in the same namespace as the `Rollout` + type: string + type: object + gracePeriodSeconds: + description: Optional duration in seconds the traffic provider(e.g. + nginx ingress controller) consumes the service, ingress configuration + changes gracefully. + format: int32 + type: integer + ingress: + description: Ingress holds Ingress specific configuration to + route traffic, e.g. Nginx, Alb. + properties: + classType: + description: ClassType refers to the type of `Ingress`. + current support nginx, aliyun-alb. default is nginx. + type: string + name: + description: Name refers to the name of an `Ingress` resource + in the same namespace as the `Rollout` + type: string + required: + - name + type: object + service: + description: Service holds the name of a service which selects + pods with stable version and don't select any pods with canary + version. + type: string + required: + - service + type: object + type: array + strategy: + description: trafficrouting strategy + properties: + matches: + description: Matches define conditions used for matching the incoming + HTTP requests to canary service. Each match is independent, + i.e. this rule will be matched if **any** one of the matches + is satisfied. If Gateway API, current only support one match. + And cannot support both weight and matches, if both are configured, + then matches takes precedence. + items: + properties: + headers: + description: Headers specifies HTTP request header matchers. + Multiple match values are ANDed together, meaning, a request + must match all the specified headers to select the route. + items: + description: HTTPHeaderMatch describes how to select a + HTTP route by matching HTTP request headers. + properties: + name: + description: "Name is the name of the HTTP Header + to be matched. Name matching MUST be case insensitive. + (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent header + names, only the first entry with an equivalent name + MUST be considered for a match. Subsequent entries + with an equivalent header name MUST be ignored. + Due to the case-insensitivity of header names, \"foo\" + and \"Foo\" are considered equivalent. \n When a + header is repeated in an HTTP request, it is implementation-specific + behavior as to how this is represented. Generally, + proxies should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 + regarding processing a repeated header, with special + handling for \"Set-Cookie\"." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + description: "Type specifies how to match against + the value of the header. \n Support: Core (Exact) + \n Support: Custom (RegularExpression) \n Since + RegularExpression HeaderMatchType has custom conformance, + implementations can support POSIX, PCRE or any other + dialects of regular expressions. Please read the + implementation's documentation to determine the + supported dialect." + enum: + - Exact + - RegularExpression + type: string + value: + description: Value is the value of HTTP Header to + be matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + type: object + type: array + requestHeaderModifier: + description: "Set overwrites the request with the given header + (name, value) before the action. \n Input: GET /foo HTTP/1.1 + \ my-header: foo \n requestHeaderModifier: set: - name: + \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 + \ my-header: bar" + properties: + add: + description: "Add adds the given header(s) (name, value) to + the request before the action. It appends to any existing + values associated with the header name. \n Input: GET + /foo HTTP/1.1 my-header: foo \n Config: add: - name: + \"my-header\" value: \"bar\" \n Output: GET /foo HTTP/1.1 + \ my-header: foo my-header: bar" + items: + description: HTTPHeader represents an HTTP Header name and + value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to + be matched. Name matching MUST be case insensitive. + (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent header names, + the first entry with an equivalent name MUST be considered + for a match. Subsequent entries with an equivalent + header name MUST be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be + matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + description: "Remove the given header(s) from the HTTP request + before the action. The value of Remove is a list of HTTP + header names. Note that the header names are case-insensitive + (see https://datatracker.ietf.org/doc/html/rfc2616#section-4.2). + \n Input: GET /foo HTTP/1.1 my-header1: foo my-header2: + bar my-header3: baz \n Config: remove: [\"my-header1\", + \"my-header3\"] \n Output: GET /foo HTTP/1.1 my-header2: + bar" + items: + type: string + maxItems: 16 + type: array + set: + description: "Set overwrites the request with the given header + (name, value) before the action. \n Input: GET /foo HTTP/1.1 + \ my-header: foo \n Config: set: - name: \"my-header\" + \ value: \"bar\" \n Output: GET /foo HTTP/1.1 my-header: + bar" + items: + description: HTTPHeader represents an HTTP Header name and + value as defined by RFC 7230. + properties: + name: + description: "Name is the name of the HTTP Header to + be matched. Name matching MUST be case insensitive. + (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent header names, + the first entry with an equivalent name MUST be considered + for a match. Subsequent entries with an equivalent + header name MUST be ignored. Due to the case-insensitivity + of header names, \"foo\" and \"Foo\" are considered + equivalent." + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + description: Value is the value of HTTP Header to be + matched. + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + weight: + description: Weight indicate how many percentage of traffic the + canary pods should receive + format: int32 + type: integer + type: object + required: + - objectRef + - strategy + type: object + status: + properties: + message: + description: Message provides details on why the rollout is in its + current phase + type: string + observedGeneration: + description: observedGeneration is the most recent generation observed + for this Rollout. + format: int64 + type: integer + phase: + description: Phase is the trafficRouting phase. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} status: acceptedNames: kind: "" diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 205d70d..8a48101 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -11,14 +11,18 @@ resources: patchesStrategicMerge: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. # patches here are for enabling the conversion webhook for each CRD -#- patches/webhook_in_rollouts.yaml +- patches/webhook_in_rollouts.yaml #- patches/webhook_in_batchreleases.yaml +#- patches/webhook_in_trafficroutings.yaml +#- patches/webhook_in_rollouthistories.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. # patches here are for enabling the CA injection for each CRD #- patches/cainjection_in_rollouts.yaml #- patches/cainjection_in_batchreleases.yaml +#- patches/cainjection_in_trafficroutings.yaml +#- patches/cainjection_in_rollouthistories.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/cainjection_in_rollouthistories.yaml b/config/crd/patches/cainjection_in_rollouthistories.yaml new file mode 100644 index 0000000..8a46cb5 --- /dev/null +++ b/config/crd/patches/cainjection_in_rollouthistories.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: rollouthistories.rollouts.kruise.io diff --git a/config/crd/patches/cainjection_in_trafficroutings.yaml b/config/crd/patches/cainjection_in_trafficroutings.yaml new file mode 100644 index 0000000..30cad6d --- /dev/null +++ b/config/crd/patches/cainjection_in_trafficroutings.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: trafficroutings.rollouts.kruise.io diff --git a/config/crd/patches/webhook_in_rollouthistories.yaml b/config/crd/patches/webhook_in_rollouthistories.yaml new file mode 100644 index 0000000..8f426a0 --- /dev/null +++ b/config/crd/patches/webhook_in_rollouthistories.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: rollouthistories.rollouts.kruise.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/crd/patches/webhook_in_trafficroutings.yaml b/config/crd/patches/webhook_in_trafficroutings.yaml new file mode 100644 index 0000000..18d41e8 --- /dev/null +++ b/config/crd/patches/webhook_in_trafficroutings.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: trafficroutings.rollouts.kruise.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index 05a508b..6b66ab8 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -36,7 +36,7 @@ patchesStrategicMerge: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml -#- manager_webhook_patch.yaml +- manager_webhook_patch.yaml # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. diff --git a/config/default/manager_webhook_patch.yaml b/config/default/manager_webhook_patch.yaml new file mode 100644 index 0000000..891125e --- /dev/null +++ b/config/default/manager_webhook_patch.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: kruise-rollout-webhook-certs diff --git a/config/default/webhookcainjection_patch.yaml b/config/default/webhookcainjection_patch.yaml new file mode 100644 index 0000000..d398ef7 --- /dev/null +++ b/config/default/webhookcainjection_patch.yaml @@ -0,0 +1,29 @@ +# This patch add annotation to admission webhook config and +# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + labels: + app.kubernetes.io/name: mutatingwebhookconfiguration + app.kubernetes.io/instance: mutating-webhook-configuration + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: rollouts + app.kubernetes.io/part-of: rollouts + app.kubernetes.io/managed-by: kustomize + name: mutating-webhook-configuration + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + labels: + app.kubernetes.io/name: validatingwebhookconfiguration + app.kubernetes.io/instance: validating-webhook-configuration + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: rollouts + app.kubernetes.io/part-of: rollouts + app.kubernetes.io/managed-by: kustomize + name: validating-webhook-configuration + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index f8ae707..c207571 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -1,4 +1,10 @@ apiVersion: v1 +kind: Secret +metadata: + name: webhook-certs + namespace: system +--- +apiVersion: v1 kind: Namespace metadata: labels: diff --git a/config/rbac/rollouthistory_editor_role.yaml b/config/rbac/rollouthistory_editor_role.yaml new file mode 100644 index 0000000..c48c231 --- /dev/null +++ b/config/rbac/rollouthistory_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit rollouthistories. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: rollouthistory-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: rollouts + app.kubernetes.io/part-of: rollouts + app.kubernetes.io/managed-by: kustomize + name: rollouthistory-editor-role +rules: +- apiGroups: + - rollouts.kruise.io + resources: + - rollouthistories + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - rollouts.kruise.io + resources: + - rollouthistories/status + verbs: + - get diff --git a/config/rbac/rollouthistory_viewer_role.yaml b/config/rbac/rollouthistory_viewer_role.yaml new file mode 100644 index 0000000..3333bc3 --- /dev/null +++ b/config/rbac/rollouthistory_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view rollouthistories. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: rollouthistory-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: rollouts + app.kubernetes.io/part-of: rollouts + app.kubernetes.io/managed-by: kustomize + name: rollouthistory-viewer-role +rules: +- apiGroups: + - rollouts.kruise.io + resources: + - rollouthistories + verbs: + - get + - list + - watch +- apiGroups: + - rollouts.kruise.io + resources: + - rollouthistories/status + verbs: + - get diff --git a/config/rbac/trafficrouting_editor_role.yaml b/config/rbac/trafficrouting_editor_role.yaml new file mode 100644 index 0000000..1413021 --- /dev/null +++ b/config/rbac/trafficrouting_editor_role.yaml @@ -0,0 +1,31 @@ +# permissions for end users to edit trafficroutings. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: trafficrouting-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: rollouts + app.kubernetes.io/part-of: rollouts + app.kubernetes.io/managed-by: kustomize + name: trafficrouting-editor-role +rules: +- apiGroups: + - rollouts.kruise.io + resources: + - trafficroutings + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - rollouts.kruise.io + resources: + - trafficroutings/status + verbs: + - get diff --git a/config/rbac/trafficrouting_viewer_role.yaml b/config/rbac/trafficrouting_viewer_role.yaml new file mode 100644 index 0000000..6127f9c --- /dev/null +++ b/config/rbac/trafficrouting_viewer_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to view trafficroutings. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: trafficrouting-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: rollouts + app.kubernetes.io/part-of: rollouts + app.kubernetes.io/managed-by: kustomize + name: trafficrouting-viewer-role +rules: +- apiGroups: + - rollouts.kruise.io + resources: + - trafficroutings + verbs: + - get + - list + - watch +- apiGroups: + - rollouts.kruise.io + resources: + - trafficroutings/status + verbs: + - get diff --git a/config/samples/rollouts_v1beta1_batchrelease.yaml b/config/samples/rollouts_v1beta1_batchrelease.yaml new file mode 100644 index 0000000..428780b --- /dev/null +++ b/config/samples/rollouts_v1beta1_batchrelease.yaml @@ -0,0 +1,12 @@ +apiVersion: rollouts.kruise.io/v1beta1 +kind: BatchRelease +metadata: + labels: + app.kubernetes.io/name: batchrelease + app.kubernetes.io/instance: batchrelease-sample + app.kubernetes.io/part-of: rollouts + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: rollouts + name: batchrelease-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/rollouts_v1beta1_rollout.yaml b/config/samples/rollouts_v1beta1_rollout.yaml new file mode 100644 index 0000000..07f4b97 --- /dev/null +++ b/config/samples/rollouts_v1beta1_rollout.yaml @@ -0,0 +1,12 @@ +apiVersion: rollouts.kruise.io/v1beta1 +kind: Rollout +metadata: + labels: + app.kubernetes.io/name: rollout + app.kubernetes.io/instance: rollout-sample + app.kubernetes.io/part-of: rollouts + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: rollouts + name: rollout-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/rollouts_v1beta1_rollouthistory.yaml b/config/samples/rollouts_v1beta1_rollouthistory.yaml new file mode 100644 index 0000000..108b35a --- /dev/null +++ b/config/samples/rollouts_v1beta1_rollouthistory.yaml @@ -0,0 +1,12 @@ +apiVersion: rollouts.kruise.io/v1beta1 +kind: RolloutHistory +metadata: + labels: + app.kubernetes.io/name: rollouthistory + app.kubernetes.io/instance: rollouthistory-sample + app.kubernetes.io/part-of: rollouts + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: rollouts + name: rollouthistory-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/rollouts_v1beta1_trafficrouting.yaml b/config/samples/rollouts_v1beta1_trafficrouting.yaml new file mode 100644 index 0000000..cc90e66 --- /dev/null +++ b/config/samples/rollouts_v1beta1_trafficrouting.yaml @@ -0,0 +1,12 @@ +apiVersion: rollouts.kruise.io/v1beta1 +kind: TrafficRouting +metadata: + labels: + app.kubernetes.io/name: trafficrouting + app.kubernetes.io/instance: trafficrouting-sample + app.kubernetes.io/part-of: rollouts + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: rollouts + name: trafficrouting-sample +spec: + # TODO(user): Add fields here diff --git a/main.go b/main.go index 4668265..9eecfb9 100644 --- a/main.go +++ b/main.go @@ -22,15 +22,6 @@ import ( kruisev1aplphal1 "github.com/openkruise/kruise-api/apps/v1alpha1" kruisev1beta1 "github.com/openkruise/kruise-api/apps/v1beta1" - rolloutsv1alpha1 "github.com/openkruise/rollouts/api/v1alpha1" - br "github.com/openkruise/rollouts/pkg/controller/batchrelease" - "github.com/openkruise/rollouts/pkg/controller/deployment" - "github.com/openkruise/rollouts/pkg/controller/rollout" - "github.com/openkruise/rollouts/pkg/controller/rollouthistory" - "github.com/openkruise/rollouts/pkg/controller/trafficrouting" - utilclient "github.com/openkruise/rollouts/pkg/util/client" - utilfeature "github.com/openkruise/rollouts/pkg/util/feature" - "github.com/openkruise/rollouts/pkg/webhook" "github.com/spf13/pflag" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" "k8s.io/apimachinery/pkg/runtime" @@ -42,9 +33,21 @@ import ( "sigs.k8s.io/controller-runtime/pkg/healthz" gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + rolloutsv1alpha1 "github.com/openkruise/rollouts/api/v1alpha1" + br "github.com/openkruise/rollouts/pkg/controller/batchrelease" + "github.com/openkruise/rollouts/pkg/controller/deployment" + "github.com/openkruise/rollouts/pkg/controller/rollout" + "github.com/openkruise/rollouts/pkg/controller/rollouthistory" + "github.com/openkruise/rollouts/pkg/controller/trafficrouting" + utilclient "github.com/openkruise/rollouts/pkg/util/client" + utilfeature "github.com/openkruise/rollouts/pkg/util/feature" + "github.com/openkruise/rollouts/pkg/webhook" + // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. _ "k8s.io/client-go/plugin/pkg/client/auth" + + rolloutsv1beta1 "github.com/openkruise/rollouts/api/v1beta1" //+kubebuilder:scaffold:imports ) @@ -60,6 +63,7 @@ func init() { utilruntime.Must(rolloutsv1alpha1.AddToScheme(scheme)) utilruntime.Must(gatewayv1alpha2.AddToScheme(scheme)) utilruntime.Must(admissionregistrationv1.AddToScheme(scheme)) + utilruntime.Must(rolloutsv1beta1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme }