Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions contrib/completions/bash/oc
Original file line number Diff line number Diff line change
Expand Up @@ -6873,13 +6873,74 @@ _oc_adm_uncordon()
noun_aliases=()
}

_oc_adm_upgrade_channel()
{
last_command="oc_adm_upgrade_channel"

command_aliases=()

commands=()

flags=()
two_word_flags=()
local_nonpersistent_flags=()
flags_with_completion=()
flags_completion=()

flags+=("--allow-explicit-channel")
local_nonpersistent_flags+=("--allow-explicit-channel")
flags+=("--as=")
two_word_flags+=("--as")
flags+=("--as-group=")
two_word_flags+=("--as-group")
flags+=("--cache-dir=")
two_word_flags+=("--cache-dir")
flags+=("--certificate-authority=")
two_word_flags+=("--certificate-authority")
flags+=("--client-certificate=")
two_word_flags+=("--client-certificate")
flags+=("--client-key=")
two_word_flags+=("--client-key")
flags+=("--cluster=")
two_word_flags+=("--cluster")
flags+=("--context=")
two_word_flags+=("--context")
flags+=("--insecure-skip-tls-verify")
flags+=("--kubeconfig=")
two_word_flags+=("--kubeconfig")
flags+=("--match-server-version")
flags+=("--namespace=")
two_word_flags+=("--namespace")
flags_with_completion+=("--namespace")
flags_completion+=("__oc_get_namespaces")
two_word_flags+=("-n")
flags_with_completion+=("-n")
flags_completion+=("__oc_get_namespaces")
flags+=("--request-timeout=")
two_word_flags+=("--request-timeout")
flags+=("--server=")
two_word_flags+=("--server")
two_word_flags+=("-s")
flags+=("--tls-server-name=")
two_word_flags+=("--tls-server-name")
flags+=("--token=")
two_word_flags+=("--token")
flags+=("--user=")
two_word_flags+=("--user")

must_have_one_flag=()
must_have_one_noun=()
noun_aliases=()
}

_oc_adm_upgrade()
{
last_command="oc_adm_upgrade"

command_aliases=()

commands=()
commands+=("channel")

flags=()
two_word_flags=()
Expand Down
61 changes: 61 additions & 0 deletions contrib/completions/zsh/oc
Original file line number Diff line number Diff line change
Expand Up @@ -6973,13 +6973,74 @@ _oc_adm_uncordon()
noun_aliases=()
}

_oc_adm_upgrade_channel()
{
last_command="oc_adm_upgrade_channel"

command_aliases=()

commands=()

flags=()
two_word_flags=()
local_nonpersistent_flags=()
flags_with_completion=()
flags_completion=()

flags+=("--allow-explicit-channel")
local_nonpersistent_flags+=("--allow-explicit-channel")
flags+=("--as=")
two_word_flags+=("--as")
flags+=("--as-group=")
two_word_flags+=("--as-group")
flags+=("--cache-dir=")
two_word_flags+=("--cache-dir")
flags+=("--certificate-authority=")
two_word_flags+=("--certificate-authority")
flags+=("--client-certificate=")
two_word_flags+=("--client-certificate")
flags+=("--client-key=")
two_word_flags+=("--client-key")
flags+=("--cluster=")
two_word_flags+=("--cluster")
flags+=("--context=")
two_word_flags+=("--context")
flags+=("--insecure-skip-tls-verify")
flags+=("--kubeconfig=")
two_word_flags+=("--kubeconfig")
flags+=("--match-server-version")
flags+=("--namespace=")
two_word_flags+=("--namespace")
flags_with_completion+=("--namespace")
flags_completion+=("__oc_get_namespaces")
two_word_flags+=("-n")
flags_with_completion+=("-n")
flags_completion+=("__oc_get_namespaces")
flags+=("--request-timeout=")
two_word_flags+=("--request-timeout")
flags+=("--server=")
two_word_flags+=("--server")
two_word_flags+=("-s")
flags+=("--tls-server-name=")
two_word_flags+=("--tls-server-name")
flags+=("--token=")
two_word_flags+=("--token")
flags+=("--user=")
two_word_flags+=("--user")

must_have_one_flag=()
must_have_one_noun=()
noun_aliases=()
}

_oc_adm_upgrade()
{
last_command="oc_adm_upgrade"

command_aliases=()

commands=()
commands+=("channel")

flags=()
two_word_flags=()
Expand Down
127 changes: 127 additions & 0 deletions pkg/cli/admin/upgrade/channel/channel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Package channel contains a command for setting a cluster's update channel.
package channel

import (
"context"
"fmt"
"strings"

configv1client "github.com/openshift/client-go/config/clientset/versioned"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
kcmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/templates"
)

func NewOptions(streams genericclioptions.IOStreams) *Options {
return &Options{
IOStreams: streams,
}
}

func New(f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
o := NewOptions(streams)
cmd := &cobra.Command{
Use: "channel CHANNEL",
Short: "Set or clear the update channel",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oc adm upgrade channel candidate-4.6

Is not intuitive IMO. We need a verb or flag to make it intuitive e.g. oc adm upgrade channel --to candidate-4.6

Copy link
Member

@LalatenduMohanty LalatenduMohanty Oct 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to compile this PR to test the user experience but getting in to some error because I am using go 1.15.2

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebased onto master, and it compiles in the CI presubmits. What error were you seeing?

/remove-lifecycle stale

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can compile the PR successfully now.

Long: templates.LongDesc(`
Set or clear the update channel.
This command will set or clear the update channel, which impacts the list of updates
recommended for the cluster.
If there is a list of acceptable channels and the desired channel is not in that list,
you must pass --allow-explicit-channel to allow channel change to proceed.
`),
Run: func(cmd *cobra.Command, args []string) {
kcmdutil.CheckErr(o.Complete(f, cmd, args))
kcmdutil.CheckErr(o.Run())
},
}
flags := cmd.Flags()
flags.BoolVar(&o.AllowExplicitChannel, "allow-explicit-channel", o.AllowExplicitChannel, "Change the channel, even if there is a list of acceptable channels and the desired channel is not in that list.")
return cmd
}

type Options struct {
genericclioptions.IOStreams

Channel string

AllowExplicitChannel bool

Client configv1client.Interface
}

func (o *Options) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error {
if len(args) > 1 {
return kcmdutil.UsageErrorf(cmd, "multiple positional arguments given")
} else if len(args) == 1 {
o.Channel = args[0]
}

cfg, err := f.ToRESTConfig()
if err != nil {
return err
}
client, err := configv1client.NewForConfig(cfg)
if err != nil {
return err
}
o.Client = client
return nil
}

func (o *Options) Run() error {
ctx := context.TODO()
cv, err := o.Client.ConfigV1().ClusterVersions().Get(ctx, "version", metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return fmt.Errorf("no cluster version information available - you must be connected to an OpenShift version 4 server to fetch the current version")
}
return err
}

if o.Channel == cv.Spec.Channel {
if cv.Spec.Channel == "" {
fmt.Fprint(o.Out, "info: Cluster channel is already clear\n")
} else {
fmt.Fprintf(o.Out, "info: Cluster is already in %s\n", cv.Spec.Channel)
}
return nil
}

if len(cv.Status.Desired.Channels) > 0 {
found := false
for _, channel := range cv.Status.Desired.Channels {
if channel == o.Channel {
found = true
break
}
}
if !found {
if !o.AllowExplicitChannel {
return fmt.Errorf("the requested channel %q is not one of the available channels (%s), you must pass --allow-explicit-channel to continue\n", o.Channel, strings.Join(cv.Status.Desired.Channels, ", "))
}
if o.Channel != "" {
fmt.Fprintf(o.ErrOut, "warning: The requested channel %q is not one of the available channels (%s). You have used --allow-explicit-channel to proceed anyway.\n", o.Channel, strings.Join(cv.Status.Desired.Channels, ", "))
}
}
} else if o.Channel != "" {
fmt.Fprintf(o.ErrOut, "warning: No channels known to be compatible with the current version %q; unable to validate %q.\n", cv.Status.Desired.Version, o.Channel)
}

if o.Channel == "" {
fmt.Fprintf(o.ErrOut, "warning: Clearing channel %q; cluster will no longer request available update recommendations.\n", cv.Spec.Channel)
}

cv.Spec.Channel = o.Channel

if _, err = o.Client.ConfigV1().ClusterVersions().Update(ctx, cv, metav1.UpdateOptions{}); err != nil {
return fmt.Errorf("unable to set channel: %w", err)
}

return nil
}
18 changes: 18 additions & 0 deletions pkg/cli/admin/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
configv1 "github.com/openshift/api/config/v1"
configv1client "github.com/openshift/client-go/config/clientset/versioned"
imagereference "github.com/openshift/library-go/pkg/image/reference"

"github.com/openshift/oc/pkg/cli/admin/upgrade/channel"
)

func NewOptions(streams genericclioptions.IOStreams) *Options {
Expand Down Expand Up @@ -83,6 +85,9 @@ func New(f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command
flags.BoolVar(&o.Force, "force", o.Force, "Forcefully upgrade the cluster even when upgrade release image validation fails and the cluster is reporting errors.")
flags.BoolVar(&o.AllowExplicitUpgrade, "allow-explicit-upgrade", o.AllowExplicitUpgrade, "Upgrade even if the upgrade target is not listed in the available versions list.")
flags.BoolVar(&o.AllowUpgradeWithWarnings, "allow-upgrade-with-warnings", o.AllowUpgradeWithWarnings, "Upgrade even if an upgrade is in process or a cluster error is blocking the update.")

cmd.AddCommand(channel.New(f, streams))

return cmd
}

Expand Down Expand Up @@ -328,6 +333,19 @@ func (o *Options) Run() error {
fmt.Fprintf(o.Out, "Upgradeable=False\n\n Reason: %s\n Message: %s\n\n", c.Reason, c.Message)
}

if cv.Spec.Channel != "" {
if cv.Spec.Upstream == "" {
fmt.Fprint(o.Out, "Upstream is unset, so the cluster will use an appropriate default.\n")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/an appropriate default/ the default/ . Because we do not have multiple upstream options.

} else {
fmt.Fprintf(o.Out, "Upstream: %s\n", cv.Spec.Upstream)
}
if len(cv.Status.Desired.Channels) > 0 {
fmt.Fprintf(o.Out, "Channel: %s (available channels: %s)\n", cv.Spec.Channel, strings.Join(cv.Status.Desired.Channels, ", "))
} else {
fmt.Fprintf(o.Out, "Channel: %s\n", cv.Spec.Channel)
}
}

if len(cv.Status.AvailableUpdates) > 0 {
fmt.Fprintf(o.Out, "Updates:\n\n")
w := tabwriter.NewWriter(o.Out, 0, 2, 1, ' ', 0)
Expand Down