Skip to content

Commit 4c00c45

Browse files
author
David Gamero
committed
fake command runner
1 parent 5822226 commit 4c00c45

File tree

6 files changed

+73
-62
lines changed

6 files changed

+73
-62
lines changed

cmd/setup-gh.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ application and service principle, and will configure that application to trust
3131
RunE: func(cmd *cobra.Command, args []string) error {
3232
ctx := cmd.Context()
3333

34+
gh := providers.NewGhClient()
3435
providers.EnsureAzCli()
35-
providers.EnsureGhCli()
3636

3737
azCred, err := cred.GetCred()
3838
if err != nil {
@@ -44,14 +44,14 @@ application and service principle, and will configure that application to trust
4444
}
4545
sc.AzClient = az
4646

47-
err = fillSetUpConfig(sc)
47+
err = fillSetUpConfig(sc, gh)
4848
if err != nil {
4949
return fmt.Errorf("filling setup config: %w", err)
5050
}
5151

5252
s := spinner.CreateSpinner("--> Setting up Github OIDC...")
5353
s.Start()
54-
err = runProviderSetUp(ctx, sc, s)
54+
err = runProviderSetUp(ctx, sc, s, gh)
5555
s.Stop()
5656
if err != nil {
5757
return err
@@ -73,7 +73,7 @@ application and service principle, and will configure that application to trust
7373
return cmd
7474
}
7575

76-
func fillSetUpConfig(sc *providers.SetUpCmd) error {
76+
func fillSetUpConfig(sc *providers.SetUpCmd, gh providers.GhClient) error {
7777
if sc.TenantId == "" {
7878
tenandId, err := providers.PromptTenantId(sc.AzClient, context.Background())
7979
if err != nil {
@@ -130,7 +130,7 @@ func fillSetUpConfig(sc *providers.SetUpCmd) error {
130130
}
131131

132132
if sc.Repo == "" {
133-
repo, err := PromptGitHubRepoWithOwner()
133+
repo, err := PromptGitHubRepoWithOwner(gh)
134134
if err != nil {
135135
return fmt.Errorf("prompting github repo: %w", err)
136136
}
@@ -140,11 +140,11 @@ func fillSetUpConfig(sc *providers.SetUpCmd) error {
140140
return nil
141141
}
142142

143-
func runProviderSetUp(ctx context.Context, sc *providers.SetUpCmd, s spinner.Spinner) error {
143+
func runProviderSetUp(ctx context.Context, sc *providers.SetUpCmd, s spinner.Spinner, gh providers.GhClient) error {
144144
provider := strings.ToLower(sc.Provider)
145145
if provider == "azure" {
146146
// call azure provider logic
147-
return providers.InitiateAzureOIDCFlow(ctx, sc, s)
147+
return providers.InitiateAzureOIDCFlow(ctx, sc, s, gh)
148148

149149
} else {
150150
// call logic for user-submitted provider
@@ -192,7 +192,7 @@ func PromptAppName(az providers.AzClientInterface, defaultAppName string) (strin
192192
func getSubscriptionID() string {
193193
validate := func(input string) error {
194194
if input == "" {
195-
return errors.New("Invalid subscription id")
195+
return errors.New("invalid subscription id")
196196
}
197197
return nil
198198
}
@@ -231,8 +231,8 @@ func PromptResourceGroup(az providers.AzClientInterface, subscriptionID string)
231231
return rg, nil
232232
}
233233

234-
func PromptGitHubRepoWithOwner() (string, error) {
235-
defaultRepoNameWithOwner, err := providers.GetRepoNameWithOwner()
234+
func PromptGitHubRepoWithOwner(gh providers.GhClient) (string, error) {
235+
defaultRepoNameWithOwner, err := gh.GetRepoNameWithOwner()
236236
if err != nil {
237237
return "", err
238238
}
@@ -254,14 +254,14 @@ func PromptGitHubRepoWithOwner() (string, error) {
254254
}
255255

256256
log.Debug("Validating github repo...")
257-
if err := providers.IsValidGhRepo(repo); err != nil {
257+
if err := gh.IsValidGhRepo(repo); err != nil {
258258
confirmMissingRepoPrompt := promptui.Prompt{
259259
Label: "Unable to confirm this repo exists. Do you want to proceed anyway?",
260260
IsConfirm: true,
261261
}
262262
_, err := confirmMissingRepoPrompt.Run()
263263
if err != nil {
264-
return PromptGitHubRepoWithOwner()
264+
return PromptGitHubRepoWithOwner(gh)
265265
}
266266
} else {
267267
log.Debugf("Github repo %q is valid", repo)

cmd/setup-gh_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ func TestSetUpConfig(t *testing.T) {
2121
mockSetUpCmd.TenantId = "123456789"
2222
s := spinner.CreateSpinner("--> Setting up Github OIDC...")
2323

24-
fillSetUpConfig(mockSetUpCmd)
24+
gh := &providers.GhCliClient{}
25+
fillSetUpConfig(mockSetUpCmd, gh)
2526

26-
err := runProviderSetUp(ctx, mockSetUpCmd, s)
27+
err := runProviderSetUp(ctx, mockSetUpCmd, s, gh)
2728

2829
assert.True(t, err == nil)
2930
}

pkg/providers/azure.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,20 @@ type SetUpCmd struct {
3232

3333
const AZURE_CONTRIBUTOR_ROLE_ID = "b24988ac-6180-42a0-ab88-20f7382dd24c"
3434

35-
func InitiateAzureOIDCFlow(ctx context.Context, sc *SetUpCmd, s spinner.Spinner) error {
35+
func InitiateAzureOIDCFlow(ctx context.Context, sc *SetUpCmd, s spinner.Spinner, gh GhClient) error {
3636
log.Debug("Commencing github connection with azure...")
3737

38-
EnsureGhCliInstalled()
39-
EnsureGhCliLoggedIn()
4038
s.Start()
4139

42-
if err := sc.ValidateSetUpConfig(); err != nil {
40+
if err := sc.ValidateSetUpConfig(gh); err != nil {
4341
return err
4442
}
4543

46-
if AzAppExists(sc.AppName) {
47-
return errors.New("app already exists")
48-
} else if err := sc.createAzApp(); err != nil {
49-
return err
44+
if !AzAppExists(sc.AppName) {
45+
err := sc.createAzApp()
46+
if err != nil {
47+
return err
48+
}
5049
}
5150

5251
if err := sc.CreateServicePrincipal(); err != nil {
@@ -126,7 +125,7 @@ func (sc *SetUpCmd) createAzApp() error {
126125
}
127126

128127
func (sc *SetUpCmd) CreateServicePrincipal() error {
129-
log.Debug("Creating Azure service principal...")
128+
log.Debug("creating Azure service principal...")
130129
start := time.Now()
131130
log.Debug(start)
132131

@@ -138,7 +137,7 @@ func (sc *SetUpCmd) CreateServicePrincipal() error {
138137
return err
139138
}
140139

141-
log.Debug("Checking sp was created...")
140+
log.Debug("checking sp was created...")
142141
if sc.ServicePrincipalExists() {
143142
log.Debug("Service principal created successfully!")
144143
end := time.Since(start)
@@ -184,13 +183,13 @@ func PromptTenantId(azc AzClientInterface, ctx context.Context) (string, error)
184183
return selectedTenant, nil
185184
}
186185
if len(tenants) > 1 {
187-
prompts.Select[armsubscription.TenantIDDescription]("{{.TenantID}}", tenants, &prompts.SelectOpt[armsubscription.TenantIDDescription]{})
186+
prompts.Select[armsubscription.TenantIDDescription]("Select the tenant you want to use", tenants, &prompts.SelectOpt[armsubscription.TenantIDDescription]{})
188187
}
189188

190189
return selectedTenant, nil
191190
}
192191

193-
func (sc *SetUpCmd) ValidateSetUpConfig() error {
192+
func (sc *SetUpCmd) ValidateSetUpConfig(gh GhClient) error {
194193
log.Debug("Checking that provided information is valid...")
195194

196195
if err := IsSubscriptionIdValid(sc.SubscriptionID); err != nil {
@@ -205,7 +204,7 @@ func (sc *SetUpCmd) ValidateSetUpConfig() error {
205204
return errors.New("invalid app name")
206205
}
207206

208-
if err := IsValidGhRepo(sc.Repo); err != nil {
207+
if err := gh.IsValidGhRepo(sc.Repo); err != nil {
209208
return err
210209
}
211210

pkg/providers/commandrunner.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ type CommandRunner interface {
1111
}
1212

1313
type DefaultCommandRunner struct{}
14+
var _ CommandRunner = &DefaultCommandRunner{}
1415

1516
func (d *DefaultCommandRunner) RunCommand(args ...string) (string, error) {
1617
cmd := exec.Command(args[0], args[1:]...)
@@ -22,6 +23,7 @@ type FakeCommandRunner struct {
2223
Output string
2324
ErrStr string
2425
}
26+
var _ CommandRunner = &FakeCommandRunner{}
2527

2628
func (f *FakeCommandRunner) RunCommand(args ...string) (string, error) {
2729
if f.ErrStr != "" {

pkg/providers/ghcli.go

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package providers
22

33
import (
44
"fmt"
5-
"os"
6-
"os/exec"
75
"strings"
86

97
log "github.com/sirupsen/logrus"
@@ -15,45 +13,60 @@ type SubLabel struct {
1513
}
1614

1715
// EnsureGhCliInstalled ensures that the Github CLI is installed and the user is logged in
18-
func EnsureGhCli() {
19-
EnsureGhCliInstalled()
16+
func (gh GhCliClient) EnsureGhCli() {
17+
gh.EnsureGhCliInstalled()
18+
gh.EnsureGhCliLoggedIn()
19+
}
20+
21+
type GhClient interface {
22+
EnsureGhCli()
2023
EnsureGhCliLoggedIn()
24+
IsLoggedInToGh() bool
25+
LogInToGh() error
26+
IsValidGhRepo(repo string) error
27+
GetRepoNameWithOwner() (string, error)
2128
}
2229

23-
type GhClient struct {
30+
var _ GhClient = &GhCliClient{}
31+
32+
type GhCliClient struct {
2433
CommandRunner CommandRunner
2534
}
2635

27-
func NewGhClient() *GhClient {
28-
return &GhClient{
36+
func NewGhClient() *GhCliClient {
37+
gh := &GhCliClient{
2938
CommandRunner: &DefaultCommandRunner{},
3039
}
40+
gh.EnsureGhCli()
41+
return gh
3142
}
3243

33-
func EnsureGhCliInstalled() {
44+
func (gh GhCliClient) exec(args ...string) (string, error) {
45+
return gh.CommandRunner.RunCommand(args...)
46+
}
47+
48+
func (gh GhCliClient) EnsureGhCliInstalled() {
3449
log.Debug("Checking that github cli is installed...")
35-
ghCmd := exec.Command("gh")
36-
_, err := ghCmd.CombinedOutput()
50+
_, err := gh.exec("gh")
3751
if err != nil {
3852
log.Fatal("Error: The github cli is required to complete this process. Find installation instructions at this link: https://github.com/cli/cli#installation")
3953
}
4054

4155
log.Debug("Github cli found!")
4256
}
4357

44-
func EnsureGhCliLoggedIn() {
45-
EnsureGhCliInstalled()
46-
if !IsLoggedInToGh() {
47-
if err := LogInToGh(); err != nil {
58+
func (gh GhCliClient) EnsureGhCliLoggedIn() {
59+
gh.EnsureGhCliInstalled()
60+
if !gh.IsLoggedInToGh() {
61+
if err := gh.LogInToGh(); err != nil {
4862
log.Fatal("Error: unable to log in to github")
4963
}
5064
}
5165
}
5266

53-
func IsLoggedInToGh() bool {
67+
func (gh GhCliClient) IsLoggedInToGh() bool {
5468
log.Debug("Checking that user is logged in to github...")
55-
ghCmd := exec.Command("gh", "auth", "status")
56-
out, err := ghCmd.CombinedOutput()
69+
out, err := gh.exec("gh", "auth", "status")
5770
if err != nil {
5871
fmt.Printf(string(out))
5972
return false
@@ -64,43 +77,33 @@ func IsLoggedInToGh() bool {
6477

6578
}
6679

67-
func LogInToGh() error {
80+
func (gh GhCliClient) LogInToGh() error {
6881
log.Debug("Logging user in to github...")
69-
ghCmd := exec.Command("gh", "auth", "login")
70-
ghCmd.Stdin = os.Stdin
71-
ghCmd.Stdout = os.Stdout
72-
ghCmd.Stderr = os.Stderr
73-
err := ghCmd.Run()
82+
_, err := gh.exec("gh", "auth", "login")
7483
if err != nil {
7584
return err
7685
}
7786

7887
return nil
7988
}
8089

81-
func IsValidGhRepo(repo string) error {
82-
listReposCmd := exec.Command("gh", "repo", "view", repo)
83-
_, err := listReposCmd.CombinedOutput()
90+
func (gh GhCliClient) IsValidGhRepo(repo string) error {
91+
_, err := gh.exec("gh", "repo", "view", repo)
8492
if err != nil {
8593
log.Debug("Github repo " + repo + "not found")
8694
return err
8795
}
8896
return nil
8997
}
9098

91-
func GetRepoNameWithOwner() (string, error) {
99+
func (gh GhCliClient) GetRepoNameWithOwner() (string, error) {
92100
repoNameWithOwner := ""
93-
GetRepoNameWithOwnerCmd := exec.Command("gh", "repo", "view", "--json", "nameWithOwner", "-q", ".nameWithOwner")
94-
out, err := GetRepoNameWithOwnerCmd.CombinedOutput()
101+
out, err := gh.exec("gh", "repo", "view", "--json", "nameWithOwner", "-q", ".nameWithOwner")
95102
if err != nil {
96103
log.Fatal("getting github repo name with owner")
97104
return repoNameWithOwner, err
98105
}
99-
if out == nil {
100-
log.Fatal("github repo name nil from cli")
101-
return repoNameWithOwner, fmt.Errorf("github repo name with owner not found")
102-
}
103-
if len(out) == 0 {
106+
if out == "" {
104107
log.Fatal("github repo name empty from gh cli")
105108
return repoNameWithOwner, fmt.Errorf("github repo name empty from gh cli")
106109
}

pkg/providers/ghcli_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,11 @@ import (
55
)
66

77
func TestHasGhCli(t *testing.T) {
8-
EnsureGhCliInstalled()
8+
cr := &FakeCommandRunner{
9+
Output: "gh version 1.0.0",
10+
}
11+
gh := &GhCliClient{
12+
CommandRunner: cr,
13+
}
14+
gh.EnsureGhCliInstalled()
915
}

0 commit comments

Comments
 (0)