From 8060b66482778cefda8c8d5f384b5ff22c078762 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Wed, 22 Jun 2022 15:45:00 +0300 Subject: [PATCH 1/3] feat: Rename config-ssh `--diff` to `--dry-run` Since the intent between diff and dry-run are different, this change allows for interactive prompts to be shown during `--dry-run`, previously prompts were disabled. Dry-run can also be chanied with `--yes` and `--use-previous-options` for non-interactive modes. Dry-run is like a normal run with changes replaced by diff. Fixes #2530 --- cli/configssh.go | 86 +++++++++++++++---------------------------- cli/configssh_test.go | 20 ++++++++++ 2 files changed, 49 insertions(+), 57 deletions(-) diff --git a/cli/configssh.go b/cli/configssh.go index bf34cacdcfdc5..f9abe7badb8c7 100644 --- a/cli/configssh.go +++ b/cli/configssh.go @@ -57,13 +57,6 @@ func (o sshConfigOptions) equal(other sshConfigOptions) bool { return slices.Equal(opt1, opt2) } -func (o sshConfigOptions) asArgs() (args []string) { - for _, opt := range o.sshOptions { - args = append(args, "--ssh-option", fmt.Sprintf("%q", opt)) - } - return args -} - func (o sshConfigOptions) asList() (list []string) { for _, opt := range o.sshOptions { list = append(list, fmt.Sprintf("ssh-option: %s", opt)) @@ -140,11 +133,8 @@ func configSSH() *cobra.Command { sshConfigOpts sshConfigOptions usePreviousOpts bool coderConfigFile string - showDiff bool + dryRun bool skipProxyCommand bool - - // Diff should exit with status 1 when files differ. - filesDiffer bool ) cmd := &cobra.Command{ Annotations: workspaceCommand, @@ -156,14 +146,9 @@ func configSSH() *cobra.Command { ` + cliui.Styles.Code.Render("$ coder config-ssh -o ForwardAgent=yes") + ` - - You can use -D (or --diff) to display the changes that will be made. + - You can use --dry-run (or -n) to see the changes that will be made. - ` + cliui.Styles.Code.Render("$ coder config-ssh --diff"), - PostRun: func(cmd *cobra.Command, args []string) { - if showDiff && filesDiffer { - os.Exit(1) //nolint: revive - } - }, + ` + cliui.Styles.Code.Render("$ coder config-ssh --dry-run"), RunE: func(cmd *cobra.Command, args []string) error { client, err := createClient(cmd) if err != nil { @@ -173,7 +158,9 @@ func configSSH() *cobra.Command { recvWorkspaceConfigs := sshPrepareWorkspaceConfigs(cmd.Context(), client) out := cmd.OutOrStdout() - if showDiff { + if dryRun { + // Print everything except diff to stderr so + // that it's possible to capture the diff. out = cmd.OutOrStderr() } binaryFile, err := currentBinPath(out) @@ -186,7 +173,6 @@ func configSSH() *cobra.Command { return xerrors.Errorf("user home dir failed: %w", err) } - sshConfigFileOrig := sshConfigFile if strings.HasPrefix(sshConfigFile, "~/") { sshConfigFile = filepath.Join(homedir, sshConfigFile[2:]) } @@ -221,7 +207,7 @@ func configSSH() *cobra.Command { // or when a previous config does not exist. if usePreviousOpts && lastConfig != nil { sshConfigOpts = *lastConfig - } else if !showDiff && lastConfig != nil && !sshConfigOpts.equal(*lastConfig) { + } else if lastConfig != nil && !sshConfigOpts.equal(*lastConfig) { newOpts := sshConfigOpts.asList() newOptsMsg := "\n\n New options: none" if len(newOpts) > 0 { @@ -244,7 +230,10 @@ func configSSH() *cobra.Command { // Selecting "no" will use the last config. sshConfigOpts = *lastConfig } - _, _ = fmt.Fprint(out, "\n") + // Only print when prompts are shown. + if yes, _ := cmd.Flags().GetBool("yes"); !yes { + _, _ = fmt.Fprint(out, "\n") + } } configModified := configRaw @@ -316,15 +305,21 @@ func configSSH() *cobra.Command { configModified = buf.Bytes() } - if showDiff { - if len(changes) > 0 { - // Write to stderr to avoid dirtying the diff output. - _, _ = fmt.Fprint(out, "The following changes will be made to your SSH configuration:\n\n") - for _, change := range changes { - _, _ = fmt.Fprintf(out, " * %s\n", change) - } + if len(changes) > 0 { + _, err = cliui.Prompt(cmd, cliui.PromptOptions{ + Text: fmt.Sprintf("The following changes will be made to your SSH configuration:\n\n * %s\n\n Continue?", strings.Join(changes, "\n * ")), + IsConfirm: true, + }) + if err != nil { + return nil } + // Only print when prompts are shown. + if yes, _ := cmd.Flags().GetBool("yes"); !yes { + _, _ = fmt.Fprint(out, "\n") + } + } + if dryRun { color := isTTYOut(cmd) diffFns := []func() ([]byte, error){ func() ([]byte, error) { return diffBytes(sshConfigFile, configRaw, configModified, color) }, @@ -340,34 +335,11 @@ func configSSH() *cobra.Command { return xerrors.Errorf("diff failed: %w", err) } if len(diff) > 0 { - filesDiffer = true - // Always write to stdout. + // Write diff to stdout. _, _ = fmt.Fprintf(cmd.OutOrStdout(), "\n%s", diff) } } - - return nil - } - - if len(changes) > 0 { - // In diff mode we don't prompt re-using the previous - // configuration, so we output the entire command. - var args []string - if sshConfigFileOrig != sshDefaultConfigFileName { - args = append(args, "--ssh-config-file", sshConfigFileOrig) - } - args = append(args, sshConfigOpts.asArgs()...) - args = append(args, "--diff") - diffCommand := fmt.Sprintf("$ %s %s", cmd.CommandPath(), strings.Join(args, " ")) - _, err = cliui.Prompt(cmd, cliui.PromptOptions{ - Text: fmt.Sprintf("The following changes will be made to your SSH configuration:\n\n * %s\n\n To see changes, run diff:\n\n %s\n\n Continue?", strings.Join(changes, "\n * "), diffCommand), - IsConfirm: true, - }) - if err != nil { - return nil - } - _, _ = fmt.Fprint(out, "\n") - + } else { if !bytes.Equal(configRaw, configModified) { err = writeWithTempFileAndMove(sshConfigFile, bytes.NewReader(configModified)) if err != nil { @@ -394,7 +366,7 @@ func configSSH() *cobra.Command { } cliflag.StringVarP(cmd.Flags(), &sshConfigFile, "ssh-config-file", "", "CODER_SSH_CONFIG_FILE", sshDefaultConfigFileName, "Specifies the path to an SSH config.") cmd.Flags().StringArrayVarP(&sshConfigOpts.sshOptions, "ssh-option", "o", []string{}, "Specifies additional SSH options to embed in each host stanza.") - cmd.Flags().BoolVarP(&showDiff, "diff", "D", false, "Show diff of changes that will be made.") + cmd.Flags().BoolVarP(&dryRun, "dry-run", "n", false, "Perform a trial run with no changes made, showing a diff at the end.") cmd.Flags().BoolVarP(&skipProxyCommand, "skip-proxy-command", "", false, "Specifies whether the ProxyCommand option should be skipped. Useful for testing.") _ = cmd.Flags().MarkHidden("skip-proxy-command") cliflag.BoolVarP(cmd.Flags(), &usePreviousOpts, "use-previous-options", "", "CODER_SSH_USE_PREVIOUS_OPTIONS", false, "Specifies whether or not to keep options from previous run of config-ssh.") @@ -575,7 +547,7 @@ func diffBytes(name string, b1, b2 []byte, color bool) ([]byte, error) { if color { opts = append(opts, write.TerminalColor()) } - err := diff.Text(name, name+".new", b1, b2, &buf, opts...) + err := diff.Text(name, name, b1, b2, &buf, opts...) if err != nil { return nil, err } @@ -584,7 +556,7 @@ func diffBytes(name string, b1, b2 []byte, color bool) ([]byte, error) { // // Example: // --- /home/user/.ssh/config - // +++ /home/user/.ssh/config.new + // +++ /home/user/.ssh/config if bytes.Count(b, []byte{'\n'}) == 2 { b = nil } diff --git a/cli/configssh_test.go b/cli/configssh_test.go index e937f6171d019..df3aa0b99f872 100644 --- a/cli/configssh_test.go +++ b/cli/configssh_test.go @@ -494,6 +494,26 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) { "--yes", }, }, + { + name: "Do not overwrite config when using --dry-run", + writeConfig: writeConfig{ + ssh: strings.Join([]string{ + baseHeader, + "", + }, "\n"), + }, + wantConfig: wantConfig{ + ssh: strings.Join([]string{ + baseHeader, + "", + }, "\n"), + }, + args: []string{ + "--ssh-option", "ForwardAgent=yes", + "--dry-run", + "--yes", + }, + }, // Tests for deprecated split coder config. { From e0ed1af99d3fb863584f0ccd18e95f1a02685ee9 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Wed, 22 Jun 2022 15:51:28 +0300 Subject: [PATCH 2/3] fix: Add dry-run disclaimer --- cli/configssh.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/configssh.go b/cli/configssh.go index f9abe7badb8c7..c97e5ca252c3e 100644 --- a/cli/configssh.go +++ b/cli/configssh.go @@ -306,8 +306,12 @@ func configSSH() *cobra.Command { } if len(changes) > 0 { + dryRunDisclaimer := "" + if dryRun { + dryRunDisclaimer = " (dry-run, no changed will be made)" + } _, err = cliui.Prompt(cmd, cliui.PromptOptions{ - Text: fmt.Sprintf("The following changes will be made to your SSH configuration:\n\n * %s\n\n Continue?", strings.Join(changes, "\n * ")), + Text: fmt.Sprintf("The following changes will be made to your SSH configuration:\n\n * %s\n\n Continue?%s", strings.Join(changes, "\n * "), dryRunDisclaimer), IsConfirm: true, }) if err != nil { From a0a59f66553b1050803623d86e6ed3f002192feb Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Wed, 22 Jun 2022 16:38:08 +0300 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Cian Johnston --- cli/configssh.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/configssh.go b/cli/configssh.go index c97e5ca252c3e..238fcf592f9e8 100644 --- a/cli/configssh.go +++ b/cli/configssh.go @@ -146,7 +146,7 @@ func configSSH() *cobra.Command { ` + cliui.Styles.Code.Render("$ coder config-ssh -o ForwardAgent=yes") + ` - - You can use --dry-run (or -n) to see the changes that will be made. + - You can use --dry-run (or -n) to see the changes that would be made. ` + cliui.Styles.Code.Render("$ coder config-ssh --dry-run"), RunE: func(cmd *cobra.Command, args []string) error { @@ -308,7 +308,7 @@ func configSSH() *cobra.Command { if len(changes) > 0 { dryRunDisclaimer := "" if dryRun { - dryRunDisclaimer = " (dry-run, no changed will be made)" + dryRunDisclaimer = " (dry-run, no changes will be made)" } _, err = cliui.Prompt(cmd, cliui.PromptOptions{ Text: fmt.Sprintf("The following changes will be made to your SSH configuration:\n\n * %s\n\n Continue?%s", strings.Join(changes, "\n * "), dryRunDisclaimer), pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy