Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interactive cli opt #4166

Merged
merged 6 commits into from
Jan 26, 2018
Merged

Conversation

mrballcb
Copy link
Contributor

Sometimes when doing a kops rolling-update, I might want to ssh to a new master or new node to check that some component is configured properly, has started, or just in general look around to make sure it's behaving properly before it updates every instance in the cluster. Especially if I know a breaking change is being deployed, I'd like to have kops wait after performing the update on each host, not on a timer, but wait until I specifically allow it to continue.

This PR adds a kops cli option, --interactive, that pauses after each instance gets updated. It prints out a prompt:

Continue? (Y)es, (N)o, (A)lwaysYes: [Y]

...and waits for admin approval before continuing on to the next instance. Pressing "y" or "Y" will continue. The default is "Y"es, so pressing Enter will also continue. Pressing "n" or "N" could maybe be enhanced to print out some useful information (summary, where you stopped, etc) but for now it merely exits kops immediately with exitcode 3 so that it does not deploy any more rolling updates. Pressing "a" or "A" clears the Interactive flag and it will no longer prompt after updating each instance going forward.

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Dec 28, 2017
@mrballcb
Copy link
Contributor Author

mrballcb commented Dec 28, 2017

There are a few things I don’t like and I feel warrant discussion:

  1. Adding “strings” and “bufio” imports to the pkg/instancegroups/instancegroups.go file.
  2. Output looks so drastically different from the surrounding glog.* functions, it’s kind of jarring.
  3. I feel like it should be in a shared util module instead of directly in the file. (But I don’t see it being usable anywhere else, so what would be the gain?)
  4. Implementation of “AlwaysYes” feels hackish, and pending my understanding of pointers as implemented in go, maybe downright wrong or unsafe.

@mrballcb
Copy link
Contributor Author

/assign @chrislovecnm

@chrislovecnm
Copy link
Contributor

/ok-to-test

@k8s-ci-robot k8s-ci-robot removed the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Jan 5, 2018
Copy link
Contributor

@chrislovecnm chrislovecnm left a comment

Choose a reason for hiding this comment

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

Lots of comments for yah, and I know you are new to go, so I hope I provided enough detail. Ping me on slack if you have more questions or on #kops-dev

stop_prompting = false
reader := bufio.NewReader(os.Stdin)
glog.Infof("Pausing after finished %q", upgradedHost)
fmt.Printf("Continue? (Y)es, (N)o, (A)lwaysYes: [Y] ")
Copy link
Contributor

Choose a reason for hiding this comment

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

so should we just fmt.Printf? What looks better UX wise?

val = strings.ToLower(val)
switch val {
case "y", "", "\n":
glog.V(4).Infof("Continuing with next host (response %q)\n", val)
Copy link
Contributor

Choose a reason for hiding this comment

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

fmt.Printf?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't quite understand this comment. I was attempting to make a log message that only shows up for higher verbosity levels. Are you saying that you'd rather no output for this?

Now I'm wondering if I should just omit the test for "y" altogether. "n" means stop, "a" means no more prompts, anything else should be treated as "y". If you won't want any glog output, I can just omit that whole case "y" section and it should behave the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I ended up just completely getting rid of the case "y" section. Only [nN] or [aA] make something different happen (stop and no more prompting, respectively). Anything else is a default "y".

@@ -65,6 +67,32 @@ func NewRollingUpdateInstanceGroup(cloud fi.Cloud, cloudGroup *cloudinstances.Cl
}, nil
}

// User input routine copied from vendor/google.golang.org/api/examples/gmail.go
func PromptInteractive(upgradedHost string) (stop_prompting bool) {
Copy link
Contributor

Choose a reason for hiding this comment

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

GoLang likes stopPrompting instead of stop_prompting :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Also promptInteractive instead, no need to make it public, and https://blog.golang.org/godoc-documenting-go-code

The tldr; on the documentation is.

  1. start with the func name. promptInteractive
  2. write a sentence and end it with a period.

Copy link
Contributor

Choose a reason for hiding this comment

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

How about func promptInteractive(upgradedHost string) (stopPrompting bool, err error)? Then you would be able to return the error up the stack.

fmt.Printf("Continue? (Y)es, (N)o, (A)lwaysYes: [Y] ")
val := ""
var err error
if val, err = reader.ReadString('\n'); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we use the endline option in golang that is platform independent? Eventually windows yay.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Switched from using bufio Reader to bufio Scanner.

@@ -65,6 +67,32 @@ func NewRollingUpdateInstanceGroup(cloud fi.Cloud, cloudGroup *cloudinstances.Cl
}, nil
}

// User input routine copied from vendor/google.golang.org/api/examples/gmail.go
func PromptInteractive(upgradedHost string) (stop_prompting bool) {
stop_prompting = false
Copy link
Contributor

Choose a reason for hiding this comment

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

camel case please

val := ""
var err error
if val, err = reader.ReadString('\n'); err != nil {
glog.Fatalf("unable to interpret input: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

so instead of glog.Fatal please log and return an err. I think you are eating the error a bit here.

@@ -169,6 +197,13 @@ func (r *RollingUpdateInstanceGroup) RollingUpdate(rollingUpdateData *RollingUpd

glog.Warningf("Cluster validation failed after removing instance, proceeding since fail-on-validate is set to false: %v", err)
}
if rollingUpdateData.Interactive {
var stop_prompting bool = PromptInteractive(nodeName)
Copy link
Contributor

Choose a reason for hiding this comment

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

you should be able to do

stopPrompting, err := PromptInteractive(nodeName)

Test if err is nil, and if not return it up the stack.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Implemented in this manner.

@chrislovecnm
Copy link
Contributor

Thanks for the PR!! @mrballcb lot of tweaks for yah to make it more Go and less Perl :) I know you mentioned Go looks a lot like Perl when we chatted.

stop_prompting = false
reader := bufio.NewReader(os.Stdin)
glog.Infof("Pausing after finished %q", upgradedHost)
fmt.Printf("Continue? (Y)es, (N)o, (A)lwaysYes: [Y] ")

Choose a reason for hiding this comment

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

fmt.Printf without any parameters here. fmt.Print will print without a newline

@mrballcb
Copy link
Contributor Author

I took the current set of patches and applied it to the release-1.8 branch. I built and tested kops with these patches against a test cluster, and put the output of these into gists so you can see what the output looks like. This is normal verbosity level.

Answered [A]lwaysYes:
https://gist.github.com/mrballcb/c6ae28c7ef4754c36da6bd81055a8550

Answered default:
https://gist.github.com/mrballcb/7899624679cc45c16e6d396ece9e688e

Answerd [N]o:
https://gist.github.com/mrballcb/6733184bb4d5aebd8841e746f00a0030

@chrislovecnm
Copy link
Contributor

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jan 26, 2018
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: chrislovecnm, mrballcb

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jan 26, 2018
@k8s-ci-robot k8s-ci-robot merged commit 923118e into kubernetes:master Jan 26, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants