Skip to content

Commit 5583faa

Browse files
Merge pull request #2023 from wking/oc-adm-upgrade-recommend-verbosity
OTA-1539: pkg/cli/admin/upgrade/recommend: Add a --quiet option
2 parents 3a5722f + 59f624e commit 5583faa

File tree

1 file changed

+77
-41
lines changed

1 file changed

+77
-41
lines changed

pkg/cli/admin/upgrade/recommend/recommend.go

Lines changed: 77 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func New(f kcmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command
6363
flags.StringVar(&o.rawVersion, "version", o.rawVersion, "Select a particular target release to display by version.")
6464

6565
if kcmdutil.FeatureGate("OC_ENABLE_CMD_UPGRADE_RECOMMEND_ACCEPT").IsEnabled() {
66+
flags.BoolVar(&o.quiet, "quiet", o.quiet, "When --quiet is true and --version is set, only print unaccepted issue names.")
6667
flags.StringSliceVar(&o.accept, "accept", o.accept, "Comma-delimited names for issues that you find acceptable. With --version, any unaccepted issues will result in a non-zero exit code.")
6768
}
6869

@@ -80,6 +81,9 @@ type options struct {
8081
showOutdatedReleases bool
8182
precheckEnabled bool
8283

84+
// quiet configures the verbosity of output. When 'quiet' is true and 'version' is set, only print unaccepted issue names.
85+
quiet bool
86+
8387
// rawVersion is parsed into version by options.Complete. Do not consume it directly outside of that early option handling.
8488
rawVersion string
8589

@@ -115,7 +119,11 @@ func (o *options) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string
115119
}
116120
}
117121

118-
if o.rawVersion != "" {
122+
if o.rawVersion == "" {
123+
if o.quiet {
124+
return errors.New("--quiet can only be set when --version is set")
125+
}
126+
} else {
119127
if o.showOutdatedReleases {
120128
return errors.New("when --version is set, --show-outdated-releases is unnecessary")
121129
}
@@ -154,15 +162,19 @@ func (o *options) Run(ctx context.Context) error {
154162
if accept.Has(string(clusterStatusFailing)) {
155163
acceptContext = "accepted "
156164
}
157-
fmt.Fprintf(o.Out, "%s%s=%s:\n\n Reason: %s\n Message: %s\n\n", acceptContext, c.Type, c.Status, c.Reason, strings.ReplaceAll(c.Message, "\n", "\n "))
165+
if !o.quiet {
166+
fmt.Fprintf(o.Out, "%s%s=%s:\n\n Reason: %s\n Message: %s\n\n", acceptContext, c.Type, c.Status, c.Reason, strings.ReplaceAll(c.Message, "\n", "\n "))
167+
}
158168
issues.Insert(string(clusterStatusFailing))
159169
}
160170
} else {
161171
acceptContext := ""
162172
if accept.Has(string(clusterStatusFailing)) {
163173
acceptContext = "accepted "
164174
}
165-
fmt.Fprintf(o.ErrOut, "%swarning: No current %s info, see `oc describe clusterversion` for more details.\n", acceptContext, clusterStatusFailing)
175+
if !o.quiet {
176+
fmt.Fprintf(o.ErrOut, "%swarning: No current %s info, see `oc describe clusterversion` for more details.\n", acceptContext, clusterStatusFailing)
177+
}
166178
issues.Insert(string(clusterStatusFailing))
167179
}
168180

@@ -171,14 +183,18 @@ func (o *options) Run(ctx context.Context) error {
171183
if accept.Has(string(configv1.OperatorProgressing)) {
172184
acceptContext = "accepted "
173185
}
174-
fmt.Fprintf(o.Out, "%sinfo: An update is in progress. You may wish to let this update complete before requesting a new update.\n %s\n\n", acceptContext, strings.ReplaceAll(c.Message, "\n", "\n "))
186+
if !o.quiet {
187+
fmt.Fprintf(o.Out, "%sinfo: An update is in progress. You may wish to let this update complete before requesting a new update.\n %s\n\n", acceptContext, strings.ReplaceAll(c.Message, "\n", "\n "))
188+
}
175189
issues.Insert(string(configv1.OperatorProgressing))
176190
}
177191

178192
if o.precheckEnabled {
179193
conditions, err := o.precheck(ctx)
180194
if err != nil {
181-
fmt.Fprintf(o.Out, "Failed to check for at least some preconditions: %v\n", err)
195+
if !o.quiet {
196+
fmt.Fprintf(o.Out, "Failed to check for at least some preconditions: %v\n", err)
197+
}
182198
issues.Insert("FailedToCompletePrecheck")
183199
}
184200
var happyConditions []string
@@ -196,40 +212,48 @@ func (o *options) Run(ctx context.Context) error {
196212
}
197213
}
198214
}
199-
if len(happyConditions) > 0 {
200-
sort.Strings(happyConditions)
201-
fmt.Fprintf(o.Out, "The following conditions found no cause for concern in updating this cluster to later releases: %s\n\n", strings.Join(happyConditions, ", "))
202-
}
203-
if len(acceptedConditions) > 0 {
204-
sort.Strings(acceptedConditions)
205-
fmt.Fprintf(o.Out, "The following conditions found cause for concern in updating this cluster to later releases, but were explicitly accepted via --accept: %s\n\n", strings.Join(acceptedConditions, ", "))
206-
}
207-
if len(unhappyConditions) > 0 {
208-
sort.Strings(unhappyConditions)
209-
fmt.Fprintf(o.Out, "The following conditions found cause for concern in updating this cluster to later releases: %s\n\n", strings.Join(unhappyConditions, ", "))
210215

211-
for _, c := range conditions {
212-
if c.Status != metav1.ConditionTrue {
213-
fmt.Fprintf(o.Out, "%s=%s:\n\n Reason: %s\n Message: %s\n\n", c.Type, c.Status, c.Reason, strings.ReplaceAll(c.Message, "\n", "\n "))
216+
if !o.quiet {
217+
if len(happyConditions) > 0 {
218+
sort.Strings(happyConditions)
219+
fmt.Fprintf(o.Out, "The following conditions found no cause for concern in updating this cluster to later releases: %s\n\n", strings.Join(happyConditions, ", "))
220+
}
221+
if len(acceptedConditions) > 0 {
222+
sort.Strings(acceptedConditions)
223+
fmt.Fprintf(o.Out, "The following conditions found cause for concern in updating this cluster to later releases, but were explicitly accepted via --accept: %s\n\n", strings.Join(acceptedConditions, ", "))
224+
}
225+
if len(unhappyConditions) > 0 {
226+
sort.Strings(unhappyConditions)
227+
fmt.Fprintf(o.Out, "The following conditions found cause for concern in updating this cluster to later releases: %s\n\n", strings.Join(unhappyConditions, ", "))
228+
229+
for _, c := range conditions {
230+
if c.Status != metav1.ConditionTrue {
231+
fmt.Fprintf(o.Out, "%s=%s:\n\n Reason: %s\n Message: %s\n\n", c.Type, c.Status, c.Reason, strings.ReplaceAll(c.Message, "\n", "\n "))
232+
}
214233
}
215234
}
216235
}
217236
}
218237

219238
if c := findClusterOperatorStatusCondition(cv.Status.Conditions, configv1.RetrievedUpdates); c != nil && c.Status != configv1.ConditionTrue {
220-
fmt.Fprintf(o.ErrOut, "warning: Cannot refresh available updates:\n Reason: %s\n Message: %s\n\n", c.Reason, strings.ReplaceAll(c.Message, "\n", "\n "))
239+
if !o.quiet {
240+
fmt.Fprintf(o.ErrOut, "warning: Cannot refresh available updates:\n Reason: %s\n Message: %s\n\n", c.Reason, strings.ReplaceAll(c.Message, "\n", "\n "))
241+
}
242+
issues.Insert("CannotRetrieveUpdates")
221243
}
222244

223-
if cv.Spec.Channel != "" {
224-
if cv.Spec.Upstream == "" {
225-
fmt.Fprint(o.Out, "Upstream update service is unset, so the cluster will use an appropriate default.\n")
226-
} else {
227-
fmt.Fprintf(o.Out, "Upstream update service: %s\n", cv.Spec.Upstream)
228-
}
229-
if len(cv.Status.Desired.Channels) > 0 {
230-
fmt.Fprintf(o.Out, "Channel: %s (available channels: %s)\n", cv.Spec.Channel, strings.Join(cv.Status.Desired.Channels, ", "))
231-
} else {
232-
fmt.Fprintf(o.Out, "Channel: %s\n", cv.Spec.Channel)
245+
if !o.quiet {
246+
if cv.Spec.Channel != "" {
247+
if cv.Spec.Upstream == "" {
248+
fmt.Fprint(o.Out, "Upstream update service is unset, so the cluster will use an appropriate default.\n")
249+
} else {
250+
fmt.Fprintf(o.Out, "Upstream update service: %s\n", cv.Spec.Upstream)
251+
}
252+
if len(cv.Status.Desired.Channels) > 0 {
253+
fmt.Fprintf(o.Out, "Channel: %s (available channels: %s)\n", cv.Spec.Channel, strings.Join(cv.Status.Desired.Channels, ", "))
254+
} else {
255+
fmt.Fprintf(o.Out, "Channel: %s\n", cv.Spec.Channel)
256+
}
233257
}
234258
}
235259

@@ -238,7 +262,9 @@ func (o *options) Run(ctx context.Context) error {
238262
for i, update := range cv.Status.ConditionalUpdates {
239263
version, err := semver.Parse(update.Release.Version)
240264
if err != nil {
241-
fmt.Fprintf(o.ErrOut, "warning: Cannot parse SemVer available update %q: %v", update.Release.Version, err)
265+
if !o.quiet {
266+
fmt.Fprintf(o.ErrOut, "warning: Cannot parse SemVer available update %q: %v", update.Release.Version, err)
267+
}
242268
continue
243269
}
244270

@@ -263,7 +289,9 @@ func (o *options) Run(ctx context.Context) error {
263289

264290
version, err := semver.Parse(update.Version)
265291
if err != nil {
266-
fmt.Fprintf(o.ErrOut, "warning: Cannot parse SemVer available update %q: %v", update.Version, err)
292+
if !o.quiet {
293+
fmt.Fprintf(o.ErrOut, "warning: Cannot parse SemVer available update %q: %v", update.Version, err)
294+
}
267295
continue
268296
}
269297

@@ -277,8 +305,10 @@ func (o *options) Run(ctx context.Context) error {
277305
}
278306

279307
if c := findClusterOperatorStatusCondition(cv.Status.Conditions, configv1.OperatorUpgradeable); c != nil && c.Status == configv1.ConditionFalse {
280-
if err := injectUpgradeableAsCondition(cv.Status.Desired.Version, c, majorMinorBuckets); err != nil {
281-
fmt.Fprintf(o.ErrOut, "warning: Cannot inject %s=%s as a conditional update risk: %s\n\nReason: %s\n Message: %s\n\n", c.Type, c.Status, err, c.Reason, strings.ReplaceAll(c.Message, "\n", "\n "))
308+
if err := injectUpgradeableAsCondition(cv.Status.Desired.Version, c, majorMinorBuckets); err != nil && !o.quiet {
309+
if !o.quiet {
310+
fmt.Fprintf(o.ErrOut, "warning: Cannot inject %s=%s as a conditional update risk: %s\n\nReason: %s\n Message: %s\n\n", c.Type, c.Status, err, c.Reason, strings.ReplaceAll(c.Message, "\n", "\n "))
311+
}
282312
}
283313
}
284314

@@ -294,21 +324,27 @@ func (o *options) Run(ctx context.Context) error {
294324
} else {
295325
for _, update := range minor {
296326
if update.Release.Version == o.version.String() {
297-
fmt.Fprintln(o.Out)
327+
if !o.quiet {
328+
fmt.Fprintln(o.Out)
329+
}
298330
if c := notRecommendedCondition(update); c == nil {
299-
fmt.Fprintf(o.Out, "Update to %s has no known issues relevant to this cluster.\nImage: %s\nRelease URL: %s\n", update.Release.Version, update.Release.Image, update.Release.URL)
331+
if !o.quiet {
332+
fmt.Fprintf(o.Out, "Update to %s has no known issues relevant to this cluster.\nImage: %s\nRelease URL: %s\n", update.Release.Version, update.Release.Image, update.Release.URL)
333+
}
300334
} else {
301-
acceptContext := ""
302-
if accept.Has("ConditionalUpdateRisk") {
303-
acceptContext = "accepted "
335+
if !o.quiet {
336+
acceptContext := ""
337+
if accept.Has("ConditionalUpdateRisk") {
338+
acceptContext = "accepted "
339+
}
340+
fmt.Fprintf(o.Out, "Update to %s %s=%s:\nImage: %s\nRelease URL: %s\nReason: %s%s\nMessage: %s\n", update.Release.Version, c.Type, c.Status, update.Release.Image, update.Release.URL, acceptContext, c.Reason, strings.ReplaceAll(c.Message, "\n", "\n "))
304341
}
305-
fmt.Fprintf(o.Out, "Update to %s %s=%s:\nImage: %s\nRelease URL: %s\nReason: %s%s\nMessage: %s\n", update.Release.Version, c.Type, c.Status, update.Release.Image, update.Release.URL, acceptContext, c.Reason, strings.ReplaceAll(c.Message, "\n", "\n "))
306342
issues.Insert("ConditionalUpdateRisk")
307343
}
308344
unaccepted := issues.Difference(accept)
309345
if unaccepted.Len() > 0 {
310346
return fmt.Errorf("issues that apply to this cluster but which were not included in --accept: %s", strings.Join(sets.List(unaccepted), ","))
311-
} else if issues.Len() > 0 {
347+
} else if issues.Len() > 0 && !o.quiet {
312348
fmt.Fprintf(o.Out, "Update to %s has no known issues relevant to this cluster other than the accepted %s.\n", update.Release.Version, strings.Join(sets.List(issues), ","))
313349
}
314350
return nil

0 commit comments

Comments
 (0)