diff --git a/pkg/cmd/describe/describe_rollout.go b/pkg/cmd/describe/describe_rollout.go index 50294b5..b809cd2 100644 --- a/pkg/cmd/describe/describe_rollout.go +++ b/pkg/cmd/describe/describe_rollout.go @@ -28,9 +28,11 @@ import ( kruiseappsv1alpha1 "github.com/openkruise/kruise-api/apps/v1alpha1" kruiseappsv1beta1 "github.com/openkruise/kruise-api/apps/v1beta1" - rolloutsv1beta1 "github.com/openkruise/kruise-rollout-api/client/clientset/versioned" + rolloutsapi "github.com/openkruise/kruise-rollout-api/client/clientset/versioned" + rolloutv1alpha1types "github.com/openkruise/kruise-rollout-api/client/clientset/versioned/typed/rollouts/v1alpha1" rolloutsv1beta1types "github.com/openkruise/kruise-rollout-api/client/clientset/versioned/typed/rollouts/v1beta1" - rolloutsapi "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1" + rolloutsapiv1alpha1 "github.com/openkruise/kruise-rollout-api/rollouts/v1alpha1" + rolloutsapiv1beta1 "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1" internalapi "github.com/openkruise/kruise-tools/pkg/api" internalpolymorphichelpers "github.com/openkruise/kruise-tools/pkg/internal/polymorphichelpers" "github.com/spf13/cobra" @@ -66,15 +68,16 @@ var ( type DescribeRolloutOptions struct { genericclioptions.IOStreams - Builder func() *resource.Builder - Namespace string - EnforceNamespace bool - Resources []string - RolloutViewerFn func(runtime.Object) (*rolloutsapi.Rollout, error) - Watch bool - NoColor bool - TimeoutSeconds int - RolloutsClient rolloutsv1beta1types.RolloutInterface + Builder func() *resource.Builder + Namespace string + EnforceNamespace bool + Resources []string + RolloutViewerFn func(runtime.Object) (interface{}, error) + Watch bool + NoColor bool + TimeoutSeconds int + RolloutsV1beta1Client rolloutsv1beta1types.RolloutInterface + RolloutsV1alpha1Client rolloutv1alpha1types.RolloutInterface } type WorkloadInfo struct { @@ -101,6 +104,20 @@ type WorkloadInfo struct { UpdateRevision string } +type RolloutInfo struct { + Name string + Namespace string + Phase string + Message string + ObservedGeneration int64 + Generation int64 + CurrentStepIndex int32 + CurrentStepState string + Strategy rolloutsapiv1beta1.CanaryStrategy + TrafficRoutingRef string + WorkloadRef RolloutWorkloadRef +} + func NewCmdDescribeRollout(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { o := &DescribeRolloutOptions{IOStreams: streams} cmd := &cobra.Command{ @@ -151,11 +168,13 @@ func (o *DescribeRolloutOptions) Complete(f cmdutil.Factory, args []string) erro return err } - rolloutsClientset, err := rolloutsv1beta1.NewForConfig(config) + rolloutsClientset, err := rolloutsapi.NewForConfig(config) if err != nil { return err } - o.RolloutsClient = rolloutsClientset.RolloutsV1beta1().Rollouts(o.Namespace) + o.RolloutsV1beta1Client = rolloutsClientset.RolloutsV1beta1().Rollouts(o.Namespace) + + o.RolloutsV1alpha1Client = rolloutsClientset.RolloutsV1alpha1().Rollouts(o.Namespace) return nil } @@ -207,9 +226,20 @@ func (o *DescribeRolloutOptions) watchRollout(r *resource.Result) error { } info := infos[0] - watcher, err := o.RolloutsClient.Watch(context.TODO(), metav1.ListOptions{ - FieldSelector: "metadata.name=" + info.Name, - }) + var watcher watch.Interface + + switch info.Object.(type) { + case *rolloutsapiv1beta1.Rollout: + watcher, err = o.RolloutsV1beta1Client.Watch(context.TODO(), metav1.ListOptions{ + FieldSelector: "metadata.name=" + info.Name, + }) + case *rolloutsapiv1alpha1.Rollout: + watcher, err = o.RolloutsV1alpha1Client.Watch(context.TODO(), metav1.ListOptions{ + FieldSelector: "metadata.name=" + info.Name, + }) + default: + return fmt.Errorf("unsupported rollout type %T", info.Object) + } if err != nil { return err @@ -235,10 +265,17 @@ func (o *DescribeRolloutOptions) watchRolloutUpdates(ctx context.Context, watche return nil } if event.Type == watch.Added || event.Type == watch.Modified { - if rollout, ok := event.Object.(*rolloutsapi.Rollout); ok { - o.clearScreen() - o.printRolloutInfo(rollout) + var rollout interface{} + switch obj := event.Object.(type) { + case *rolloutsapiv1beta1.Rollout: + rollout = obj + case *rolloutsapiv1alpha1.Rollout: + rollout = obj + default: + continue } + o.clearScreen() + o.printRolloutInfo(rollout) } case <-ctx.Done(): return ctx.Err() @@ -250,8 +287,16 @@ func (o *DescribeRolloutOptions) clearScreen() { fmt.Fprint(o.Out, "\033[2J\033[H") } -func (o *DescribeRolloutOptions) GetResources(rollout *rolloutsapi.Rollout) (*WorkloadInfo, error) { - resources := []string{rollout.Spec.WorkloadRef.Kind + "/" + rollout.Spec.WorkloadRef.Name} +type RolloutWorkloadRef struct { + Kind string + Name string + StableRevision string + CanaryRevision string + PodTemplateHash string +} + +func (o *DescribeRolloutOptions) GetResources(rollout RolloutWorkloadRef) (*WorkloadInfo, error) { + resources := []string{rollout.Kind + "/" + rollout.Name} r := o.Builder(). WithScheme(internalapi.GetScheme(), scheme.Scheme.PrioritizedVersionsAllGroups()...). NamespaceParam(o.Namespace).DefaultNamespace(). @@ -319,8 +364,8 @@ func (o *DescribeRolloutOptions) GetResources(rollout *rolloutsapi.Rollout) (*Wo return nil, fmt.Errorf("unsupported workload kind %T", obj) } - workloadInfo.CurrentRevision = rollout.Status.CanaryStatus.StableRevision - workloadInfo.UpdateRevision = rollout.Status.CanaryStatus.CanaryRevision + workloadInfo.CurrentRevision = rollout.StableRevision + workloadInfo.UpdateRevision = rollout.CanaryRevision var labelSelectorParam string switch obj.(type) { @@ -330,9 +375,9 @@ func (o *DescribeRolloutOptions) GetResources(rollout *rolloutsapi.Rollout) (*Wo labelSelectorParam = "controller-revision-hash" } - SelectorParam := rollout.Status.CanaryStatus.PodTemplateHash + SelectorParam := rollout.PodTemplateHash if SelectorParam == "" { - SelectorParam = rollout.Status.CanaryStatus.StableRevision + SelectorParam = rollout.StableRevision } // Fetch pods @@ -385,7 +430,7 @@ func (o *DescribeRolloutOptions) GetResources(rollout *rolloutsapi.Rollout) (*Wo restartCount += int(containerStatus.RestartCount) } - podInfo.Restarts = fmt.Sprintf("%v", strconv.Itoa(int(restartCount))) + podInfo.Restarts = strconv.Itoa(restartCount) } // Calculate ready status @@ -435,20 +480,20 @@ func (o *DescribeRolloutOptions) colorizeIcon(phase string) string { return "" } switch phase { - case string(rolloutsapi.RolloutPhaseHealthy), string(corev1.PodRunning): + case string(rolloutsapiv1beta1.RolloutPhaseHealthy), string(corev1.PodRunning): return "\033[32m✔\033[0m" - case string(rolloutsapi.RolloutPhaseProgressing), string(corev1.PodPending): + case string(rolloutsapiv1beta1.RolloutPhaseProgressing), string(corev1.PodPending): return "\033[33m⚠\033[0m" - case string(rolloutsapi.RolloutPhaseDisabled), string(corev1.PodUnknown), string(rolloutsapi.RolloutPhaseTerminating), string(rolloutsapi.RolloutPhaseDisabling), string(corev1.PodFailed): + case string(rolloutsapiv1beta1.RolloutPhaseDisabled), string(corev1.PodUnknown), string(rolloutsapiv1beta1.RolloutPhaseTerminating), string(rolloutsapiv1beta1.RolloutPhaseDisabling), string(corev1.PodFailed): return "\033[31m✘\033[0m" - case string(rolloutsapi.RolloutPhaseInitial): + case string(rolloutsapiv1beta1.RolloutPhaseInitial): return "\033[33m⚠\033[0m" default: return "" } } -func (o *DescribeRolloutOptions) printTrafficRouting(trafficRouting []rolloutsapi.TrafficRoutingRef) { +func (o *DescribeRolloutOptions) printTrafficRouting(trafficRouting []rolloutsapiv1beta1.TrafficRoutingRef) { fmt.Fprint(o.Out, "Traffic Routings:\n") for _, trafficRouting := range trafficRouting { fmt.Fprintf(o.Out, tableFormat, " - Service: ", trafficRouting.Service) @@ -472,88 +517,156 @@ func (o *DescribeRolloutOptions) printTrafficRouting(trafficRouting []rolloutsap } } -func (o *DescribeRolloutOptions) printRolloutInfo(rollout *rolloutsapi.Rollout) { - // Name, Namespace, Status, Message - fmt.Fprintf(o.Out, tableFormat, "Name:", rollout.Name) - fmt.Fprintf(o.Out, tableFormat, "Namespace:", rollout.Namespace) - if rollout.Status.ObservedGeneration == rollout.GetObjectMeta().GetGeneration() { - fmt.Fprintf(o.Out, tableFormat, "Status:", o.colorizeIcon(string(rollout.Status.Phase))+" "+string(rollout.Status.Phase)) +func convertCustomNetworkRefs(refs []rolloutsapiv1alpha1.CustomNetworkRef) []rolloutsapiv1beta1.ObjectRef { + var result []rolloutsapiv1beta1.ObjectRef + for _, ref := range refs { + result = append(result, rolloutsapiv1beta1.ObjectRef{ + Name: ref.Name, + Kind: ref.Kind, + APIVersion: ref.APIVersion, + }) + } + return result +} - if rollout.Status.Message != "" { - fmt.Fprintf(o.Out, tableFormat, "Message:", rollout.Status.Message) +func extractRolloutInfo(obj interface{}) *RolloutInfo { + info := &RolloutInfo{} + + switch r := obj.(type) { + case *rolloutsapiv1beta1.Rollout: + info.Name = r.Name + info.Namespace = r.Namespace + info.Phase = string(r.Status.Phase) + info.Message = r.Status.Message + info.ObservedGeneration = r.Status.ObservedGeneration + info.Generation = r.GetObjectMeta().GetGeneration() + info.CurrentStepIndex = r.Status.CanaryStatus.CurrentStepIndex + info.CurrentStepState = string(r.Status.CanaryStatus.CurrentStepState) + info.WorkloadRef = RolloutWorkloadRef{ + Kind: r.Spec.WorkloadRef.Kind, + Name: r.Spec.WorkloadRef.Name, + StableRevision: r.Status.CanaryStatus.StableRevision, + CanaryRevision: r.Status.CanaryStatus.CanaryRevision, + PodTemplateHash: r.Status.CanaryStatus.PodTemplateHash, + } + + if r.Spec.Strategy.Canary != nil { + info.TrafficRoutingRef = r.Spec.Strategy.Canary.TrafficRoutingRef + } + + case *rolloutsapiv1alpha1.Rollout: + info.Name = r.Name + info.Namespace = r.Namespace + info.Phase = string(r.Status.Phase) + info.Message = r.Status.Message + info.ObservedGeneration = r.Status.ObservedGeneration + info.Generation = r.GetObjectMeta().GetGeneration() + info.CurrentStepIndex = r.Status.CanaryStatus.CurrentStepIndex + info.CurrentStepState = string(r.Status.CanaryStatus.CurrentStepState) + info.WorkloadRef = RolloutWorkloadRef{ + Kind: r.Spec.ObjectRef.WorkloadRef.Kind, + Name: r.Spec.ObjectRef.WorkloadRef.Name, + StableRevision: r.Status.CanaryStatus.StableRevision, + CanaryRevision: r.Status.CanaryStatus.CanaryRevision, + PodTemplateHash: r.Status.CanaryStatus.PodTemplateHash, + } + + if r.Spec.Strategy.Canary != nil { + info.TrafficRoutingRef = r.ObjectMeta.Annotations["rollouts.kruise.io/trafficrouting"] } } - // Strategy - fmt.Fprintf(o.Out, tableFormat, "Strategy:", "Canary") + if obj.(*rolloutsapiv1beta1.Rollout).Spec.Strategy.Canary != nil { + info.Strategy = *obj.(*rolloutsapiv1beta1.Rollout).Spec.Strategy.Canary + } - if canary := rollout.Spec.Strategy.Canary; canary != nil { - fmt.Fprintf(o.Out, tableFormat, " Step:", strconv.Itoa(int(rollout.Status.CanaryStatus.CurrentStepIndex))+"/"+strconv.Itoa(len(canary.Steps))) - fmt.Fprint(o.Out, " Steps:\n") - currentStepIndex := int(rollout.Status.CanaryStatus.CurrentStepIndex) - for i, step := range canary.Steps { - isCurrentStep := (i + 1) == currentStepIndex - if isCurrentStep { - fmt.Fprint(o.Out, "\033[32m") - } + return info +} - if step.Replicas != nil { - fmt.Fprintf(o.Out, tableFormat, " - Replicas: ", step.Replicas) - } - if step.Traffic != nil { - fmt.Fprintf(o.Out, tableFormat, " Traffic: ", *step.Traffic) - } +func (o *DescribeRolloutOptions) fetchAndPrintTrafficRoutingRef(ref string) { + r := o.Builder(). + WithScheme(internalapi.GetScheme(), scheme.Scheme.PrioritizedVersionsAllGroups()...). + NamespaceParam(o.Namespace).DefaultNamespace(). + ResourceNames("trafficroutings.rollouts.kruise.io", ref). + ContinueOnError(). + Latest(). + Flatten(). + Do() - if step.Matches != nil { - fmt.Fprintln(o.Out, " Matches: ") - for _, match := range step.Matches { - fmt.Fprintln(o.Out, " - Headers: ") - for _, path := range match.Headers { - fmt.Fprintf(o.Out, tableFormat, " - Name:", path.Name) - fmt.Fprintf(o.Out, tableFormat, " Value:", path.Value) - fmt.Fprintf(o.Out, tableFormat, " Type:", *path.Type) - } - } - } + if err := r.Err(); err != nil { + fmt.Fprintf(o.Out, "Error getting TrafficRoutingRef: %v\n", err) + return + } - if isCurrentStep { - fmt.Fprintf(o.Out, tableFormat, " State:", rollout.Status.CanaryStatus.CurrentStepState) - fmt.Fprint(o.Out, "\033[0m") // Reset color - } + err := r.Visit(func(info *resource.Info, err error) error { + if err != nil { + return err + } + trafficRouting, ok := info.Object.(*rolloutsapiv1alpha1.TrafficRouting) + if !ok { + return fmt.Errorf("expected *rolloutsapiv1alpha1.TrafficRouting") } - // Traffic Routings - if len(rollout.Spec.Strategy.Canary.TrafficRoutings) > 0 { - o.printTrafficRouting(rollout.Spec.Strategy.Canary.TrafficRoutings) + var trafficRoutingRef []rolloutsapiv1beta1.TrafficRoutingRef + for _, ref := range trafficRouting.Spec.ObjectRef { + trafficRoutingRef = append(trafficRoutingRef, rolloutsapiv1beta1.TrafficRoutingRef{ + Service: ref.Service, + Ingress: (*rolloutsapiv1beta1.IngressTrafficRouting)(ref.Ingress), + Gateway: (*rolloutsapiv1beta1.GatewayTrafficRouting)(ref.Gateway), + CustomNetworkRefs: convertCustomNetworkRefs(ref.CustomNetworkRefs), + }) } - if rollout.Spec.Strategy.Canary.TrafficRoutingRef != "" { - // r := o.Builder(). - // WithScheme(internalapi.GetScheme(), scheme.Scheme.PrioritizedVersionsAllGroups()...). - // NamespaceParam(o.Namespace).DefaultNamespace(). - // ResourceNames("trafficrouting.rollouts.kruise.io", rollout.Spec.Strategy.Canary.TrafficRoutingRef). - // ContinueOnError(). - // Latest(). - // Flatten(). - // Do() - - // if err := r.Err(); err != nil { - // fmt.Fprintf(o.Out, "Error getting TrafficRoutingRef: %v\n", err) - // return - // } + o.printTrafficRouting(trafficRoutingRef) + + return nil + }) + + if err != nil { + return + } +} + +func (o *DescribeRolloutOptions) printRolloutInfo(rollout interface{}) { + info := extractRolloutInfo(rollout) + // Print basic info + fmt.Fprintf(o.Out, tableFormat, "Name:", info.Name) + fmt.Fprintf(o.Out, tableFormat, "Namespace:", info.Namespace) + + if info.ObservedGeneration == info.Generation { + fmt.Fprintf(o.Out, tableFormat, "Status:", o.colorizeIcon(info.Phase)+" "+info.Phase) + if info.Message != "" { + fmt.Fprintf(o.Out, tableFormat, "Message:", info.Message) } } - // Workload - info, err := o.GetResources(rollout) + // Print strategy + fmt.Fprintf(o.Out, tableFormat, "Strategy:", "Canary") + fmt.Fprintf(o.Out, tableFormat, " Step:", strconv.Itoa(int(info.CurrentStepIndex))+"/"+strconv.Itoa(len(info.Strategy.Steps))) + + // Print steps + fmt.Fprint(o.Out, " Steps:\n") + o.printSteps(info) + + // Print traffic routing if available + if len(info.Strategy.TrafficRoutings) > 0 { + o.printTrafficRouting(info.Strategy.TrafficRoutings) + } + + if info.TrafficRoutingRef != "" { + o.fetchAndPrintTrafficRoutingRef(info.TrafficRoutingRef) + } + + // Print workload info + workloadInfo, err := o.GetResources(info.WorkloadRef) if err != nil { fmt.Fprintf(o.Out, "Error getting resources: %v\n", err) return } - // Images - for i, image := range info.Images { + // Print images + for i, image := range workloadInfo.Images { if i == 0 { fmt.Fprintf(o.Out, tableFormat, "Images:", image) } else { @@ -561,37 +674,80 @@ func (o *DescribeRolloutOptions) printRolloutInfo(rollout *rolloutsapi.Rollout) } } - // Revisions - fmt.Fprintf(o.Out, tableFormat, "Current Revision:", info.CurrentRevision) - fmt.Fprintf(o.Out, tableFormat, "Update Revision:", info.UpdateRevision) - - // Replicas - if rollout.Status.ObservedGeneration == rollout.GetObjectMeta().GetGeneration() { - fmt.Fprint(o.Out, "Replicas:\n") - fmt.Fprintf(o.Out, tableFormat, " Desired:", info.Replicas.Desired) - fmt.Fprintf(o.Out, tableFormat, " Updated:", info.Replicas.Updated) - fmt.Fprintf(o.Out, tableFormat, " Current:", info.Replicas.Current) - fmt.Fprintf(o.Out, tableFormat, " Ready:", info.Replicas.Ready) - fmt.Fprintf(o.Out, tableFormat, " Available:", info.Replicas.Available) - } - - if len(info.Pod) > 0 { - w := tabwriter.NewWriter(o.Out, 0, 0, 2, ' ', 0) - fmt.Fprintln(w, "NAME\tREADY\tBATCH ID\tREVISION\tAGE\tRESTARTS\tSTATUS") - - for _, pod := range info.Pod { - fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s %s\n", - pod.Name, - pod.Ready, - pod.BatchID, - pod.Revision, - pod.Age, - pod.Restarts, - o.colorizeIcon(pod.Status), - pod.Status, - ) + // Print revisions + fmt.Fprintf(o.Out, tableFormat, "Current Revision:", workloadInfo.CurrentRevision) + fmt.Fprintf(o.Out, tableFormat, "Update Revision:", workloadInfo.UpdateRevision) + + // Print replicas + if info.ObservedGeneration == info.Generation { + o.printReplicas(workloadInfo) + } + + // Print pods + if len(workloadInfo.Pod) > 0 { + o.printPods(workloadInfo) + } +} + +func (o *DescribeRolloutOptions) printSteps(info *RolloutInfo) { + currentStepIndex := int(info.CurrentStepIndex) + + for i, step := range info.Strategy.Steps { + isCurrentStep := (i + 1) == currentStepIndex + if isCurrentStep { + fmt.Fprint(o.Out, "\033[32m") + } + + if step.Replicas != nil { + fmt.Fprintf(o.Out, tableFormat, " - Replicas: ", step.Replicas) + } + if step.Traffic != nil { + fmt.Fprintf(o.Out, tableFormat, " Traffic: ", *step.Traffic) + } + + if len(step.Matches) > 0 { + fmt.Fprintln(o.Out, " Matches: ") + for _, match := range step.Matches { + fmt.Fprintln(o.Out, " - Headers: ") + for _, header := range match.Headers { + fmt.Fprintf(o.Out, tableFormat, " - Name:", header.Name) + fmt.Fprintf(o.Out, tableFormat, " Value:", header.Value) + fmt.Fprintf(o.Out, tableFormat, " Type:", *header.Type) + } + } + } + + if isCurrentStep { + fmt.Fprintf(o.Out, tableFormat, " State:", info.CurrentStepState) + fmt.Fprint(o.Out, "\033[0m") } - w.Flush() } +} + +func (o *DescribeRolloutOptions) printReplicas(info *WorkloadInfo) { + fmt.Fprint(o.Out, "Replicas:\n") + fmt.Fprintf(o.Out, tableFormat, " Desired:", info.Replicas.Desired) + fmt.Fprintf(o.Out, tableFormat, " Updated:", info.Replicas.Updated) + fmt.Fprintf(o.Out, tableFormat, " Current:", info.Replicas.Current) + fmt.Fprintf(o.Out, tableFormat, " Ready:", info.Replicas.Ready) + fmt.Fprintf(o.Out, tableFormat, " Available:", info.Replicas.Available) +} +func (o *DescribeRolloutOptions) printPods(info *WorkloadInfo) { + w := tabwriter.NewWriter(o.Out, 0, 0, 2, ' ', 0) + fmt.Fprintln(w, "NAME\tREADY\tBATCH ID\tREVISION\tAGE\tRESTARTS\tSTATUS") + + for _, pod := range info.Pod { + fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s %s\n", + pod.Name, + pod.Ready, + pod.BatchID, + pod.Revision, + pod.Age, + pod.Restarts, + o.colorizeIcon(pod.Status), + pod.Status, + ) + } + w.Flush() } diff --git a/pkg/internal/polymorphichelpers/interface.go b/pkg/internal/polymorphichelpers/interface.go index eedf74b..523e0b4 100644 --- a/pkg/internal/polymorphichelpers/interface.go +++ b/pkg/internal/polymorphichelpers/interface.go @@ -19,7 +19,6 @@ package polymorphichelpers import ( "time" - rolloutsapi "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" @@ -52,7 +51,7 @@ type StatusViewerFunc func(mapping *meta.RESTMapping) (StatusViewer, error) // StatusViewerFn gives a way to easily override the function for unit testing if needed var StatusViewerFn StatusViewerFunc = statusViewer -type RolloutViewerFunc func(obj runtime.Object) (*rolloutsapi.Rollout, error) +type RolloutViewerFunc func(obj runtime.Object) (interface{}, error) var RolloutViewerFn RolloutViewerFunc = rolloutViewer diff --git a/pkg/internal/polymorphichelpers/rolloutviewer.go b/pkg/internal/polymorphichelpers/rolloutviewer.go index 8d79efb..ac2a396 100644 --- a/pkg/internal/polymorphichelpers/rolloutviewer.go +++ b/pkg/internal/polymorphichelpers/rolloutviewer.go @@ -21,14 +21,18 @@ import ( "k8s.io/apimachinery/pkg/runtime" - rolloutschema "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1" + rolloutv1alpha1 "github.com/openkruise/kruise-rollout-api/rollouts/v1alpha1" + rolloutv1beta1 "github.com/openkruise/kruise-rollout-api/rollouts/v1beta1" ) // statusViewer returns a StatusViewer for printing rollout status. -func rolloutViewer(obj runtime.Object) (*rolloutschema.Rollout, error) { - rollout, ok := obj.(*rolloutschema.Rollout) - if !ok { - return nil, fmt.Errorf("Object is not a rollout") +func rolloutViewer(obj runtime.Object) (interface{}, error) { + if rollout, ok := obj.(*rolloutv1beta1.Rollout); ok { + return rollout, nil } - return rollout, nil + if rollout, ok := obj.(*rolloutv1alpha1.Rollout); ok { + return rollout, nil + } + + return nil, fmt.Errorf("unknown rollout type: %T", obj) }