Skip to content

Commit

Permalink
v0.1.8 org create standalone and refinement
Browse files Browse the repository at this point in the history
  • Loading branch information
geemus committed Dec 3, 2024
1 parent e75e108 commit 3b95788
Show file tree
Hide file tree
Showing 32 changed files with 746 additions and 1,392 deletions.
2 changes: 1 addition & 1 deletion api/openapi.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,22 @@ var rootDef = CmdDef{
},
},
},
{
Name: "org",

Use: "org [flags]",
Args: cobra.NoArgs,
Short: "Manage Organizations",
SubDefs: []CmdDef{
{
Name: "create",

Use: "create [flags]",
Args: cobra.NoArgs,
Short: "Create New Organization",
},
},
},
{
Name: "service",

Expand Down
1 change: 1 addition & 0 deletions cmd/anchor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/anchordotdev/cli"
_ "github.com/anchordotdev/cli/auth"
_ "github.com/anchordotdev/cli/lcl"
_ "github.com/anchordotdev/cli/org"
_ "github.com/anchordotdev/cli/service"
_ "github.com/anchordotdev/cli/trust"
versionpkg "github.com/anchordotdev/cli/version"
Expand Down
9 changes: 6 additions & 3 deletions component/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,12 @@ func (s *Selector[T]) Choice(ctx context.Context, drv *ui.Driver) (*T, error) {
var choices []ui.ListItem[T]
for _, item := range s.Choices {
choice := ui.ListItem[T]{
Key: item.Key(),
String: fmt.Sprintf("%s (%s)", item.String(), item.Key()),
Value: item,
Key: item.Key(),
String: fmt.Sprintf("%s %s",
item.String(),
ui.Whisper(fmt.Sprintf("(%s)", item.Key())),
),
Value: item,
}
choices = append(choices, choice)
}
Expand Down
5 changes: 3 additions & 2 deletions lcl/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,11 @@ func TestBootstrap(t *testing.T) {
"? What lcl.host domain would you like to use for diagnostics?",
)

tm.Type("hello-world")
tm.Send(tea.KeyMsg{
Type: tea.KeyEnter,
Runes: []rune("hello-world"),
Type: tea.KeyRunes,
})
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

if !srv.IsProxy() {
t.Skip("diagnostic unsupported in mock mode")
Expand Down
1 change: 1 addition & 0 deletions lcl/lcl.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var CmdLcl = cli.NewCmd[Command](cli.CmdRoot, "lcl", func(cmd *cobra.Command) {
// setup
cmd.Flags().StringVar(&cfg.Service.Category, "category", cli.Defaults.Service.Category, "Language or software type of the service.")
cmd.Flags().StringVar(&cfg.Service.CertStyle, "cert-style", cli.Defaults.Service.CertStyle, "Provisioning method for lcl.host certificates.")
cmd.Flags().StringVar(&cfg.Org.Name, "org-name", "", "Name for created org.")

// alias
cmd.Flags().StringVar(&cfg.Service.Category, "language", cli.Defaults.Service.Category, "Language to integrate with Anchor.")
Expand Down
17 changes: 14 additions & 3 deletions lcl/lcl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,15 @@ func TestCmdLcl(t *testing.T) {
})

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

t.Run("--org-name org", func(t *testing.T) {
cfg := cmdtest.TestCfg(t, CmdLcl, "--org-name", "org")
require.Equal(t, "org", cfg.Org.Name)
})

// alias

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

tm.Type("hello-world")
tm.Send(tea.KeyMsg{
Runes: []rune("hello-world"),
Type: tea.KeyRunes,
})
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

uitest.WaitForGoldenContains(t, drv, errc,
Expand Down Expand Up @@ -231,7 +239,10 @@ func TestLcl(t *testing.T) {
uitest.WaitForGoldenContains(t, drv, errc,
"? What is the application name?",
)
tm.Type("test-app")
tm.Send(tea.KeyMsg{
Runes: []rune("test-app"),
Type: tea.KeyRunes,
})
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

uitest.WaitForGoldenContains(t, drv, errc,
Expand Down
43 changes: 17 additions & 26 deletions lcl/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
"github.com/anchordotdev/cli/detection"
"github.com/anchordotdev/cli/lcl/models"
climodels "github.com/anchordotdev/cli/models"
"github.com/anchordotdev/cli/org"
orgmodels "github.com/anchordotdev/cli/org/models"
"github.com/anchordotdev/cli/service"
servicemodels "github.com/anchordotdev/cli/service/models"
"github.com/anchordotdev/cli/ui"
Expand All @@ -33,6 +35,7 @@ var CmdLclSetup = cli.NewCmd[Setup](CmdLcl, "setup", func(cmd *cobra.Command) {
cmd.Flags().StringVar(&cfg.Service.Category, "category", cli.Defaults.Service.Category, "Language or software type of the service.")
cmd.Flags().StringVar(&cfg.Service.CertStyle, "cert-style", cli.Defaults.Service.CertStyle, "Provisioning method for lcl.host certificates.")
cmd.Flags().StringVarP(&cfg.Org.APID, "org", "o", cli.Defaults.Org.APID, "Organization for lcl.host application setup.")
cmd.Flags().StringVar(&cfg.Org.Name, "org-name", "", "Name for created org.")
cmd.Flags().StringVarP(&cfg.Lcl.RealmAPID, "realm", "r", cli.Defaults.Lcl.RealmAPID, "Realm for lcl.host application setup.")
cmd.Flags().StringVarP(&cfg.Service.APID, "service", "s", cli.Defaults.Service.APID, "Service for lcl.host application setup.")

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

org, err := selector.Choice(ctx, drv)
selectedOrg, err := selector.Choice(ctx, drv)
if err != nil {
return "", err
}
if org == nil || (*org == api.Organization{}) {
orgName, err := c.orgName(ctx, cfg, drv)
if err != nil {
return "", err
if selectedOrg == nil || (*selectedOrg == api.Organization{}) {
drv.Activate(ctx, &orgmodels.OrgCreateHeader{})
drv.Activate(ctx, &orgmodels.OrgCreateHint{})
defer drv.Send(ui.HideModelsMsg{
Models: []string{"OrgCreateHeader", "OrgCreateHint"},
})

cmdOrgCreate := &org.Create{
Anc: c.anc,
}

if org, err = c.anc.CreateOrg(ctx, orgName); err != nil {
org, err := cmdOrgCreate.Perform(ctx, drv)
if err != nil {
return "", err
}
// FIXME: provide nicer output about using newly created value, and hint flag?
return org.Apid, nil
}
return org.Apid, nil

}

func (c *Setup) orgName(ctx context.Context, cfg *cli.Config, drv *ui.Driver) (string, error) {
if cfg.Org.Name != "" {
return cfg.Org.Name, nil
return org.Apid, nil
}
return selectedOrg.Apid, nil

inputc := make(chan string)
drv.Activate(ctx, &models.SetupOrgName{
InputCh: inputc,
})

select {
case orgName := <-inputc:
return orgName, nil
case <-ctx.Done():
return "", ctx.Err()
}
}

func (c *Setup) realmAPID(ctx context.Context, cfg *cli.Config, drv *ui.Driver, orgAPID string) (string, error) {
Expand Down
112 changes: 100 additions & 12 deletions lcl/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@ func TestCmdLclSetup(t *testing.T) {
})

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

t.Run("--org-name org", func(t *testing.T) {
cfg := cmdtest.TestCfg(t, CmdLclSetup, "--org-name", "org")
require.Equal(t, "org", cfg.Org.Name)
})

// alias

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

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

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

t.Run("create-org-existing-service-basics", func(t *testing.T) {
if srv.IsProxy() {
t.Skip("lcl setup existing service unsupported in proxy mode")
}

ctx, cancel := context.WithCancel(ctx)
defer cancel()

drv, tm := uitest.TestTUI(ctx, t)

cmd := Setup{
clipboard: new(clipboard.Mock),
}

errc := make(chan error, 1)
go func() {
errc <- cmd.UI().RunTUI(ctx, drv)
errc <- tm.Quit()
}()

uitest.WaitForGoldenContains(t, drv, errc,
"? Which organization's lcl.host local development environment do you want to setup?",
)
tm.Send(tea.KeyMsg{Type: tea.KeyDown})
tm.Send(tea.KeyMsg{Type: tea.KeyEnter}) // select second option, "Create New Org"

uitest.WaitForGoldenContains(t, drv, errc,
"? What is the new organization's name?",
)
tm.Send(tea.KeyMsg{
Runes: []rune("Org Name"),
Type: tea.KeyRunes,
})
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

uitest.WaitForGoldenContains(t, drv, errc,
"? Which org-slug/realm-slug service's lcl.host local development environment do you want to setup?",
)
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

uitest.WaitForGoldenContains(t, drv, errc,
"? How would you like to manage your environment variables?",
)

tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

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

env, err := cmd.clipboard.ReadAll()
if err != nil {
t.Fatal(err)
}

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"
if got := env; want != got {
t.Errorf("Want env clipboard:\n\n%q,\n\nGot:\n\n%q\n\n", want, got)
}

uitest.TestGolden(t, drv.Golden())
})

t.Run("create-service-automated-basics", func(t *testing.T) {
if srv.IsMock() {
t.Skip("lcl setup create service unsupported in mock mode")
Expand Down Expand Up @@ -108,7 +176,10 @@ func TestSetup(t *testing.T) {
"? What is the application name?",
)

tm.Type("test-app")
tm.Send(tea.KeyMsg{
Runes: []rune("test-app"),
Type: tea.KeyRunes,
})
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

uitest.WaitForGoldenContains(t, drv, errc,
Expand Down Expand Up @@ -181,7 +252,6 @@ func TestSetup(t *testing.T) {
uitest.WaitForGoldenContains(t, drv, errc,
"? Which lcl_setup/localhost service's lcl.host local development environment do you want to setup?",
)

tm.Send(tea.KeyMsg{Type: tea.KeyDown})
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

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

tm.Type("test-app")
tm.Send(tea.KeyMsg{
Runes: []rune("test-app"),
Type: tea.KeyRunes,
})
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

uitest.WaitForGoldenContains(t, drv, errc,
Expand All @@ -219,7 +292,7 @@ func TestSetup(t *testing.T) {
}
})

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

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

// FIXME: check clipboard values for accuracy (can't easily access values)
env, err := cmd.clipboard.ReadAll()
if err != nil {
t.Fatal(err)
}

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"
if got := env; want != got {
t.Errorf("Want env clipboard:\n\n%q,\n\nGot:\n\n%q\n\n", want, got)
}

uitest.TestGolden(t, drv.Golden())
})
Expand Down Expand Up @@ -305,7 +386,10 @@ func TestSetup(t *testing.T) {
"? What is the application name?",
)

tm.Type("Test App")
tm.Send(tea.KeyMsg{
Runes: []rune("Test App"),
Type: tea.KeyRunes,
})
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

uitest.WaitForGoldenContains(t, drv, errc,
Expand Down Expand Up @@ -370,15 +454,19 @@ func TestSetup(t *testing.T) {
uitest.WaitForGoldenContains(t, drv, errc,
"? What is the application name?",
)

tm.Type("test-explicit-subdomain-app")
tm.Send(tea.KeyMsg{
Runes: []rune("test-explicit-subdomain-app"),
Type: tea.KeyRunes,
})
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

uitest.WaitForGoldenContains(t, drv, errc,
"? What lcl.host domain would you like to use for local application development?",
)

tm.Type("this-is-my-weird-subdomain")
tm.Send(tea.KeyMsg{
Runes: []rune("this-is-my-weird-subdomain"),
Type: tea.KeyRunes,
})
tm.Send(tea.KeyMsg{Type: tea.KeyEnter})

uitest.WaitForGoldenContains(t, drv, errc,
Expand Down
Loading

0 comments on commit 3b95788

Please sign in to comment.