Skip to content

Commit 0e35b54

Browse files
akerl-unprivakerl
authored andcommitted
add confirmation prompt (#24)
* add confirmation prompt * update changelog
1 parent 9e6d8e5 commit 0e35b54

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 2.1.1 / 2019-08-19
2+
3+
* [FEATURE] Show confirmation prompt before running xargs
4+
15
# 2.1.0 / 2019-08-19
26

37
* [FEATURE] Add xargs subcommand

cmd/xargs.go

+7
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func init() {
2727
xargsCmd.Flags().StringP("prompt", "p", "", "Choose prompt to use")
2828
xargsCmd.Flags().BoolP("yubikey", "y", false, "Use Yubikey for MFA")
2929
xargsCmd.Flags().StringP("command", "c", "", "Command to execute")
30+
xargsCmd.Flags().Bool("skipconfirm", false, "Skip confirmation prompt")
3031
}
3132

3233
// revive:disable-next-line:cyclomatic
@@ -66,6 +67,11 @@ func xargsRunner(cmd *cobra.Command, args []string) error {
6667
return fmt.Errorf("command must be provided via --command / -c")
6768
}
6869

70+
skipConfirm, err := flags.GetBool("skipconfirm")
71+
if err != nil {
72+
return err
73+
}
74+
6975
pack := cartogram.Pack{}
7076
if err := pack.Load(); err != nil {
7177
return err
@@ -90,6 +96,7 @@ func xargsRunner(cmd *cobra.Command, args []string) error {
9096
Args: args,
9197
RoleNames: []string{flagRole},
9298
ProfileNames: []string{flagProfile},
99+
SkipConfirm: skipConfirm,
93100
}
94101

95102
results, err := processor.ExecString(commandStr)

multi/main.go

+35
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package multi
22

33
import (
4+
"bufio"
5+
"fmt"
46
"os"
57
"strings"
68
"time"
@@ -22,6 +24,7 @@ type Processor struct {
2224
Args []string
2325
RoleNames []string
2426
ProfileNames []string
27+
SkipConfirm bool
2528
}
2629

2730
// ExecString runs a command string against a set of accounts
@@ -39,6 +42,10 @@ func (p Processor) Exec(cmd []string) (map[string]creds.ExecResult, error) {
3942
return map[string]creds.ExecResult{}, err
4043
}
4144

45+
if !p.confirm(paths) {
46+
return map[string]creds.ExecResult{}, fmt.Errorf("aborted by user")
47+
}
48+
4249
inputCh := make(chan workerInput, len(paths))
4350
outputCh := make(chan workerOutput, len(paths))
4451
refreshCh := make(chan time.Time)
@@ -82,6 +89,34 @@ func (p Processor) Exec(cmd []string) (map[string]creds.ExecResult, error) {
8289
return output, nil
8390
}
8491

92+
func (p Processor) confirm(paths []travel.Path) bool {
93+
if p.SkipConfirm {
94+
return true
95+
}
96+
fmt.Fprintln(os.Stderr, "Will run on the following accounts:")
97+
for _, item := range paths {
98+
accountID := item[len(item)-1].Account
99+
ok, account := p.Grapher.Pack.Lookup(accountID)
100+
if !ok {
101+
fmt.Fprintf(os.Stderr, "Failed account lookup: %s\n", accountID)
102+
return false
103+
}
104+
fmt.Fprintf(os.Stderr, " %s -- %s\n", account.Account, account.Tags)
105+
}
106+
fmt.Fprintln(os.Stderr, "Type 'yes' to confirm")
107+
confirmReader := bufio.NewReader(os.Stdin)
108+
confirmInput, err := confirmReader.ReadString('\n')
109+
if err != nil {
110+
fmt.Fprintf(os.Stderr, "Error reading prompt: %s", err)
111+
return false
112+
}
113+
cleanedInput := strings.TrimSpace(confirmInput)
114+
if cleanedInput != "yes" {
115+
return false
116+
}
117+
return true
118+
}
119+
85120
type workerInput struct {
86121
Path travel.Path
87122
Options travel.TraverseOptions

0 commit comments

Comments
 (0)