Skip to content

Commit 3b95788

Browse files
committed
v0.1.8 org create standalone and refinement
1 parent e75e108 commit 3b95788

32 files changed

+746
-1392
lines changed

api/openapi.gen.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,22 @@ var rootDef = CmdDef{
141141
},
142142
},
143143
},
144+
{
145+
Name: "org",
146+
147+
Use: "org [flags]",
148+
Args: cobra.NoArgs,
149+
Short: "Manage Organizations",
150+
SubDefs: []CmdDef{
151+
{
152+
Name: "create",
153+
154+
Use: "create [flags]",
155+
Args: cobra.NoArgs,
156+
Short: "Create New Organization",
157+
},
158+
},
159+
},
144160
{
145161
Name: "service",
146162

cmd/anchor/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/anchordotdev/cli"
99
_ "github.com/anchordotdev/cli/auth"
1010
_ "github.com/anchordotdev/cli/lcl"
11+
_ "github.com/anchordotdev/cli/org"
1112
_ "github.com/anchordotdev/cli/service"
1213
_ "github.com/anchordotdev/cli/trust"
1314
versionpkg "github.com/anchordotdev/cli/version"

component/selector.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,12 @@ func (s *Selector[T]) Choice(ctx context.Context, drv *ui.Driver) (*T, error) {
5454
var choices []ui.ListItem[T]
5555
for _, item := range s.Choices {
5656
choice := ui.ListItem[T]{
57-
Key: item.Key(),
58-
String: fmt.Sprintf("%s (%s)", item.String(), item.Key()),
59-
Value: item,
57+
Key: item.Key(),
58+
String: fmt.Sprintf("%s %s",
59+
item.String(),
60+
ui.Whisper(fmt.Sprintf("(%s)", item.Key())),
61+
),
62+
Value: item,
6063
}
6164
choices = append(choices, choice)
6265
}

lcl/bootstrap_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,11 @@ func TestBootstrap(t *testing.T) {
105105
"? What lcl.host domain would you like to use for diagnostics?",
106106
)
107107

108-
tm.Type("hello-world")
109108
tm.Send(tea.KeyMsg{
110-
Type: tea.KeyEnter,
109+
Runes: []rune("hello-world"),
110+
Type: tea.KeyRunes,
111111
})
112+
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})
112113

113114
if !srv.IsProxy() {
114115
t.Skip("diagnostic unsupported in mock mode")

lcl/lcl.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ var CmdLcl = cli.NewCmd[Command](cli.CmdRoot, "lcl", func(cmd *cobra.Command) {
3434
// setup
3535
cmd.Flags().StringVar(&cfg.Service.Category, "category", cli.Defaults.Service.Category, "Language or software type of the service.")
3636
cmd.Flags().StringVar(&cfg.Service.CertStyle, "cert-style", cli.Defaults.Service.CertStyle, "Provisioning method for lcl.host certificates.")
37+
cmd.Flags().StringVar(&cfg.Org.Name, "org-name", "", "Name for created org.")
3738

3839
// alias
3940
cmd.Flags().StringVar(&cfg.Service.Category, "language", cli.Defaults.Service.Category, "Language to integrate with Anchor.")

lcl/lcl_test.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,15 @@ func TestCmdLcl(t *testing.T) {
8989
})
9090

9191
t.Run("--cert-style acme", func(t *testing.T) {
92-
cfg := cmdtest.TestCfg(t, CmdLcl, "--method", "acme")
92+
cfg := cmdtest.TestCfg(t, CmdLcl, "--cert-style", "acme")
9393
require.Equal(t, "acme", cfg.Service.CertStyle)
9494
})
9595

96+
t.Run("--org-name org", func(t *testing.T) {
97+
cfg := cmdtest.TestCfg(t, CmdLcl, "--org-name", "org")
98+
require.Equal(t, "org", cfg.Org.Name)
99+
})
100+
96101
// alias
97102

98103
t.Run("--language python", func(t *testing.T) {
@@ -174,7 +179,10 @@ func TestLcl(t *testing.T) {
174179
"? What lcl.host domain would you like to use for diagnostics?",
175180
)
176181

177-
tm.Type("hello-world")
182+
tm.Send(tea.KeyMsg{
183+
Runes: []rune("hello-world"),
184+
Type: tea.KeyRunes,
185+
})
178186
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})
179187

180188
uitest.WaitForGoldenContains(t, drv, errc,
@@ -231,7 +239,10 @@ func TestLcl(t *testing.T) {
231239
uitest.WaitForGoldenContains(t, drv, errc,
232240
"? What is the application name?",
233241
)
234-
tm.Type("test-app")
242+
tm.Send(tea.KeyMsg{
243+
Runes: []rune("test-app"),
244+
Type: tea.KeyRunes,
245+
})
235246
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})
236247

237248
uitest.WaitForGoldenContains(t, drv, errc,

lcl/setup.go

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"github.com/anchordotdev/cli/detection"
2323
"github.com/anchordotdev/cli/lcl/models"
2424
climodels "github.com/anchordotdev/cli/models"
25+
"github.com/anchordotdev/cli/org"
26+
orgmodels "github.com/anchordotdev/cli/org/models"
2527
"github.com/anchordotdev/cli/service"
2628
servicemodels "github.com/anchordotdev/cli/service/models"
2729
"github.com/anchordotdev/cli/ui"
@@ -33,6 +35,7 @@ var CmdLclSetup = cli.NewCmd[Setup](CmdLcl, "setup", func(cmd *cobra.Command) {
3335
cmd.Flags().StringVar(&cfg.Service.Category, "category", cli.Defaults.Service.Category, "Language or software type of the service.")
3436
cmd.Flags().StringVar(&cfg.Service.CertStyle, "cert-style", cli.Defaults.Service.CertStyle, "Provisioning method for lcl.host certificates.")
3537
cmd.Flags().StringVarP(&cfg.Org.APID, "org", "o", cli.Defaults.Org.APID, "Organization for lcl.host application setup.")
38+
cmd.Flags().StringVar(&cfg.Org.Name, "org-name", "", "Name for created org.")
3639
cmd.Flags().StringVarP(&cfg.Lcl.RealmAPID, "realm", "r", cli.Defaults.Lcl.RealmAPID, "Realm for lcl.host application setup.")
3740
cmd.Flags().StringVarP(&cfg.Service.APID, "service", "s", cli.Defaults.Service.APID, "Service for lcl.host application setup.")
3841

@@ -227,42 +230,30 @@ func (c *Setup) orgAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver) (s
227230
},
228231
}
229232

230-
org, err := selector.Choice(ctx, drv)
233+
selectedOrg, err := selector.Choice(ctx, drv)
231234
if err != nil {
232235
return "", err
233236
}
234-
if org == nil || (*org == api.Organization{}) {
235-
orgName, err := c.orgName(ctx, cfg, drv)
236-
if err != nil {
237-
return "", err
237+
if selectedOrg == nil || (*selectedOrg == api.Organization{}) {
238+
drv.Activate(ctx, &orgmodels.OrgCreateHeader{})
239+
drv.Activate(ctx, &orgmodels.OrgCreateHint{})
240+
defer drv.Send(ui.HideModelsMsg{
241+
Models: []string{"OrgCreateHeader", "OrgCreateHint"},
242+
})
243+
244+
cmdOrgCreate := &org.Create{
245+
Anc: c.anc,
238246
}
239247

240-
if org, err = c.anc.CreateOrg(ctx, orgName); err != nil {
248+
org, err := cmdOrgCreate.Perform(ctx, drv)
249+
if err != nil {
241250
return "", err
242251
}
243-
// FIXME: provide nicer output about using newly created value, and hint flag?
244-
return org.Apid, nil
245-
}
246-
return org.Apid, nil
247-
248-
}
249252

250-
func (c *Setup) orgName(ctx context.Context, cfg *cli.Config, drv *ui.Driver) (string, error) {
251-
if cfg.Org.Name != "" {
252-
return cfg.Org.Name, nil
253+
return org.Apid, nil
253254
}
255+
return selectedOrg.Apid, nil
254256

255-
inputc := make(chan string)
256-
drv.Activate(ctx, &models.SetupOrgName{
257-
InputCh: inputc,
258-
})
259-
260-
select {
261-
case orgName := <-inputc:
262-
return orgName, nil
263-
case <-ctx.Done():
264-
return "", ctx.Err()
265-
}
266257
}
267258

268259
func (c *Setup) realmAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver, orgAPID string) (string, error) {

lcl/setup_test.go

Lines changed: 100 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,15 @@ func TestCmdLclSetup(t *testing.T) {
2929
})
3030

3131
t.Run("--cert-style acme", func(t *testing.T) {
32-
cfg := cmdtest.TestCfg(t, CmdLclSetup, "--method", "acme")
32+
cfg := cmdtest.TestCfg(t, CmdLclSetup, "--cert-style", "acme")
3333
require.Equal(t, "acme", cfg.Service.CertStyle)
3434
})
3535

36+
t.Run("--org-name org", func(t *testing.T) {
37+
cfg := cmdtest.TestCfg(t, CmdLclSetup, "--org-name", "org")
38+
require.Equal(t, "org", cfg.Org.Name)
39+
})
40+
3641
// alias
3742

3843
t.Run("--language python", func(t *testing.T) {
@@ -59,7 +64,9 @@ func TestSetup(t *testing.T) {
5964

6065
cfg := cmdtest.Config(ctx)
6166
cfg.API.URL = srv.URL
62-
cfg.Test.ACME.URL = "http://anchor.lcl.host:" + srv.RailsPort
67+
if srv.IsProxy() {
68+
cfg.Test.ACME.URL = "http://anchor.lcl.host:" + srv.RailsPort
69+
}
6370
cfg.Trust.MockMode = true
6471
cfg.Trust.NoSudo = true
6572
cfg.Trust.Stores = []string{"mock"}
@@ -73,6 +80,67 @@ func TestSetup(t *testing.T) {
7380

7481
setupGuideURL := cfg.SetupGuideURL("lcl_setup", "test-app")
7582

83+
t.Run("create-org-existing-service-basics", func(t *testing.T) {
84+
if srv.IsProxy() {
85+
t.Skip("lcl setup existing service unsupported in proxy mode")
86+
}
87+
88+
ctx, cancel := context.WithCancel(ctx)
89+
defer cancel()
90+
91+
drv, tm := uitest.TestTUI(ctx, t)
92+
93+
cmd := Setup{
94+
clipboard: new(clipboard.Mock),
95+
}
96+
97+
errc := make(chan error, 1)
98+
go func() {
99+
errc <- cmd.UI().RunTUI(ctx, drv)
100+
errc <- tm.Quit()
101+
}()
102+
103+
uitest.WaitForGoldenContains(t, drv, errc,
104+
"? Which organization's lcl.host local development environment do you want to setup?",
105+
)
106+
tm.Send(tea.KeyMsg{Type: tea.KeyDown})
107+
tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) // select second option, "Create New Org"
108+
109+
uitest.WaitForGoldenContains(t, drv, errc,
110+
"? What is the new organization's name?",
111+
)
112+
tm.Send(tea.KeyMsg{
113+
Runes: []rune("Org Name"),
114+
Type: tea.KeyRunes,
115+
})
116+
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})
117+
118+
uitest.WaitForGoldenContains(t, drv, errc,
119+
"? Which org-slug/realm-slug service's lcl.host local development environment do you want to setup?",
120+
)
121+
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})
122+
123+
uitest.WaitForGoldenContains(t, drv, errc,
124+
"? How would you like to manage your environment variables?",
125+
)
126+
127+
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})
128+
129+
tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second*3))
130+
131+
env, err := cmd.clipboard.ReadAll()
132+
if err != nil {
133+
t.Fatal(err)
134+
}
135+
136+
want := "export ACME_CONTACT=\"[email protected]\"\nexport ACME_DIRECTORY_URL=\"https://anchor.dev/org-slug/realm-slug/x509/ca/acme\"\nexport ACME_HMAC_KEY=\"abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\nexport ACME_KID=\"aae_abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEF\"\nexport HTTPS_PORT=\"4433\"\nexport SERVER_NAMES=\"service.lcl.host\"\n"
137+
if got := env; want != got {
138+
t.Errorf("Want env clipboard:\n\n%q,\n\nGot:\n\n%q\n\n", want, got)
139+
}
140+
141+
uitest.TestGolden(t, drv.Golden())
142+
})
143+
76144
t.Run("create-service-automated-basics", func(t *testing.T) {
77145
if srv.IsMock() {
78146
t.Skip("lcl setup create service unsupported in mock mode")
@@ -108,7 +176,10 @@ func TestSetup(t *testing.T) {
108176
"? What is the application name?",
109177
)
110178

111-
tm.Type("test-app")
179+
tm.Send(tea.KeyMsg{
180+
Runes: []rune("test-app"),
181+
Type: tea.KeyRunes,
182+
})
112183
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})
113184

114185
uitest.WaitForGoldenContains(t, drv, errc,
@@ -181,7 +252,6 @@ func TestSetup(t *testing.T) {
181252
uitest.WaitForGoldenContains(t, drv, errc,
182253
"? Which lcl_setup/localhost service's lcl.host local development environment do you want to setup?",
183254
)
184-
185255
tm.Send(tea.KeyMsg{Type: tea.KeyDown})
186256
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})
187257

@@ -195,7 +265,10 @@ func TestSetup(t *testing.T) {
195265
"? What is the application name?",
196266
)
197267

198-
tm.Type("test-app")
268+
tm.Send(tea.KeyMsg{
269+
Runes: []rune("test-app"),
270+
Type: tea.KeyRunes,
271+
})
199272
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})
200273

201274
uitest.WaitForGoldenContains(t, drv, errc,
@@ -219,7 +292,7 @@ func TestSetup(t *testing.T) {
219292
}
220293
})
221294

222-
t.Run(fmt.Sprintf("existing-service-basics-%s", uitest.TestTagOS()), func(t *testing.T) {
295+
t.Run("existing-service-basics", func(t *testing.T) {
223296
if srv.IsProxy() {
224297
t.Skip("lcl setup existing service unsupported in proxy mode")
225298
}
@@ -258,7 +331,15 @@ func TestSetup(t *testing.T) {
258331

259332
tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second*3))
260333

261-
// FIXME: check clipboard values for accuracy (can't easily access values)
334+
env, err := cmd.clipboard.ReadAll()
335+
if err != nil {
336+
t.Fatal(err)
337+
}
338+
339+
want := "export ACME_CONTACT=\"[email protected]\"\nexport ACME_DIRECTORY_URL=\"https://anchor.dev/org-slug/realm-slug/x509/ca/acme\"\nexport ACME_HMAC_KEY=\"abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\nexport ACME_KID=\"aae_abcdefghijklmnopqrstuvwxyz0123456789-_ABCDEF\"\nexport HTTPS_PORT=\"4433\"\nexport SERVER_NAMES=\"service.lcl.host\"\n"
340+
if got := env; want != got {
341+
t.Errorf("Want env clipboard:\n\n%q,\n\nGot:\n\n%q\n\n", want, got)
342+
}
262343

263344
uitest.TestGolden(t, drv.Golden())
264345
})
@@ -305,7 +386,10 @@ func TestSetup(t *testing.T) {
305386
"? What is the application name?",
306387
)
307388

308-
tm.Type("Test App")
389+
tm.Send(tea.KeyMsg{
390+
Runes: []rune("Test App"),
391+
Type: tea.KeyRunes,
392+
})
309393
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})
310394

311395
uitest.WaitForGoldenContains(t, drv, errc,
@@ -370,15 +454,19 @@ func TestSetup(t *testing.T) {
370454
uitest.WaitForGoldenContains(t, drv, errc,
371455
"? What is the application name?",
372456
)
373-
374-
tm.Type("test-explicit-subdomain-app")
457+
tm.Send(tea.KeyMsg{
458+
Runes: []rune("test-explicit-subdomain-app"),
459+
Type: tea.KeyRunes,
460+
})
375461
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})
376462

377463
uitest.WaitForGoldenContains(t, drv, errc,
378464
"? What lcl.host domain would you like to use for local application development?",
379465
)
380-
381-
tm.Type("this-is-my-weird-subdomain")
466+
tm.Send(tea.KeyMsg{
467+
Runes: []rune("this-is-my-weird-subdomain"),
468+
Type: tea.KeyRunes,
469+
})
382470
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})
383471

384472
uitest.WaitForGoldenContains(t, drv, errc,

0 commit comments

Comments
 (0)