-
Notifications
You must be signed in to change notification settings - Fork 0
/
runner.go
141 lines (129 loc) · 4.48 KB
/
runner.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package runner provides utilities to execute commands.
package runner
import (
"bytes"
"errors"
"fmt"
"log"
"os"
"os/exec"
"strings"
)
// Runner is the interface to execute commands.
type Runner interface {
CmdRun(cmd *exec.Cmd) error
CmdOutput(cmd *exec.Cmd) ([]byte, error)
CmdCombinedOutput(cmd *exec.Cmd) ([]byte, error)
}
// Default is the Runner that executes the command by default.
type Default struct{}
// CmdRun executes the command.
func (*Default) CmdRun(cmd *exec.Cmd) error {
log.Printf("Running: %v", cmd.Args)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("%v: %s", err, stderr.String())
}
return nil
}
// CmdOutput executes the command and returns the command stdout.
func (*Default) CmdOutput(cmd *exec.Cmd) ([]byte, error) {
log.Printf("Running: %v", cmd.Args)
var stderr bytes.Buffer
cmd.Stderr = &stderr
b, err := cmd.Output()
if err != nil {
return b, fmt.Errorf("%v: %s", err, stderr.String())
}
return b, nil
}
// CmdCombinedOutput executes the command and returns the command stdout and stderr.
func (*Default) CmdCombinedOutput(cmd *exec.Cmd) ([]byte, error) {
log.Printf("Running: %v", cmd.Args)
return cmd.CombinedOutput()
}
func contains(s string, subs ...string) bool {
for _, sub := range subs {
if !strings.Contains(s, sub) {
return false
}
}
return true
}
// Fake is the Runner that only prints command information and does not run it.
type Fake struct{}
// CmdRun prints the command information.
func (*Fake) CmdRun(cmd *exec.Cmd) error {
cmdStr := strings.Join(cmd.Args, " ")
switch {
case contains(cmdStr, "cp"):
// In dry_run mode, stil execute commands that copy Terraform modules and configs
// to the Terraform working directory so that users can find them.
return (&Default{}).CmdRun(cmd)
default:
log.Printf("Dry run call: %s", strings.Join(cmd.Args, " "))
return nil
}
}
// CmdOutput prints the command information.
func (*Fake) CmdOutput(cmd *exec.Cmd) ([]byte, error) {
log.Printf("Dry run call: %s", strings.Join(cmd.Args, " "))
cmdStr := strings.Join(cmd.Args, " ")
switch {
case contains(cmdStr, "projects describe"):
return nil, errors.New("")
case contains(cmdStr, "logging sinks describe audit-logs-to-bigquery", "--format json"):
return []byte("{}"), nil
case contains(cmdStr, "config get-value account", "--format json"):
return []byte(`"dryrun@dryrun.com"`), nil
case contains(cmdStr, "projects get-iam-policy"):
return []byte("{}"), nil
case contains(cmdStr, "service-accounts list", "--filter email:forseti-server-gcp-*", "--format json"):
return []byte(`[{"email": "forseti-server-gcp-dryrun@dryrun.iam.gserviceaccount.com"}]`), nil
case contains(cmdStr, "gsutil ls"):
return []byte("gs://forseti-server-dryrun"), nil
case contains(cmdStr, "iam service-accounts list --format json --filter email:forseti-server-gcp-*"):
return []byte(`[{"email": forseti-sa@@forseti-project.iam.gserviceaccount.com"}]`), nil
case contains(cmdStr, "monitoring channels list"):
return []byte("[]"), nil
case contains(cmdStr, "monitoring channels create"):
return []byte(`{"name": "projects/dryrun/notificationChannels/dryrun"}`), nil
case contains(cmdStr, "monitoring policies list"):
return []byte("[]"), nil
case contains(cmdStr, "compute instances list"):
return []byte("[]"), nil
case contains(cmdStr, "terraform output -json project_number"):
return []byte("\"11111\""), nil
default:
return nil, nil
}
}
// CmdCombinedOutput prints the command information.
func (*Fake) CmdCombinedOutput(cmd *exec.Cmd) ([]byte, error) {
log.Printf("Dry run call: %s", strings.Join(cmd.Args, " "))
cmdStr := strings.Join(cmd.Args, " ")
switch {
case contains(cmdStr, "deployment-manager deployments list", "--format json"):
return []byte("[]"), nil
case contains(cmdStr, "monitoring policies list"):
return []byte(""), nil
default:
return nil, nil
}
}