diff --git a/cmd/runner/resource_class.go b/cmd/runner/resource_class.go index 278c42ba2..c18dee826 100644 --- a/cmd/runner/resource_class.go +++ b/cmd/runner/resource_class.go @@ -15,7 +15,8 @@ func newResourceClassCommand(o *runnerOpts, preRunE validator) *cobra.Command { Short: "Operate on runner resource-classes", } - cmd.AddCommand(&cobra.Command{ + genToken := false + createCmd := &cobra.Command{ Use: "create ", Short: "Create a resource-class", Args: cobra.ExactArgs(2), @@ -28,9 +29,21 @@ func newResourceClassCommand(o *runnerOpts, preRunE validator) *cobra.Command { table := newResourceClassTable() defer table.Render() appendResourceClass(table, *rc) - return nil + + if !genToken { + return nil + } + + token, err := o.r.CreateToken(args[0], "default") + if err != nil { + return err + } + return generateConfig(*token, os.Stdout) }, - }) + } + createCmd.PersistentFlags().BoolVar(&genToken, "generate-token", false, + "Generate a default token") + cmd.AddCommand(createCmd) cmd.AddCommand(&cobra.Command{ Use: "delete ", diff --git a/cmd/runner/resource_class_test.go b/cmd/runner/resource_class_test.go new file mode 100644 index 000000000..fbcbabda0 --- /dev/null +++ b/cmd/runner/resource_class_test.go @@ -0,0 +1,147 @@ +package runner + +import ( + "strings" + "testing" + "time" + + "github.com/google/uuid" + "github.com/pkg/errors" + "gotest.tools/v3/assert" + "gotest.tools/v3/assert/cmp" + + "github.com/CircleCI-Public/circleci-cli/api/runner" +) + +func Test_ResourceClass(t *testing.T) { + runner := runnerMock{} + cmd := newResourceClassCommand(&runnerOpts{r: &runner}, nil) + + t.Run("create", func(t *testing.T) { + t.Run("without default token", func(t *testing.T) { + defer runner.cleanup() + + cmd.SetArgs([]string{ + "create", + "my-namespace/my-resource-class", + "my-description", + }) + + err := cmd.Execute() + assert.NilError(t, err) + + assert.Check(t, cmp.Equal(len(runner.resourceClasses), 1)) + assert.Check(t, cmp.Equal(runner.resourceClasses[0].ResourceClass, "my-namespace/my-resource-class")) + assert.Check(t, cmp.Equal(runner.resourceClasses[0].Description, "my-description")) + + assert.Check(t, cmp.Equal(len(runner.tokens), 0)) + }) + + t.Run("with default token", func(t *testing.T) { + defer runner.cleanup() + + cmd.SetArgs([]string{ + "create", + "my-namespace/my-other-resource-class", + "my-description", + "--generate-token", + }) + + err := cmd.Execute() + assert.NilError(t, err) + + assert.Check(t, cmp.Equal(len(runner.resourceClasses), 1)) + assert.Check(t, cmp.Equal(runner.resourceClasses[0].ResourceClass, "my-namespace/my-other-resource-class")) + assert.Check(t, cmp.Equal(runner.resourceClasses[0].Description, "my-description")) + + assert.Check(t, cmp.Equal(len(runner.tokens), 1)) + assert.Check(t, cmp.Equal(runner.tokens[0].ResourceClass, "my-namespace/my-other-resource-class")) + assert.Check(t, cmp.Equal(runner.tokens[0].Nickname, "default")) + }) + }) +} + +type runnerMock struct { + resourceClasses []runner.ResourceClass + tokens []runner.Token +} + +func (r *runnerMock) CreateResourceClass(resourceClass, desc string) (*runner.ResourceClass, error) { + rc := runner.ResourceClass{ + ID: uuid.New().String(), + ResourceClass: resourceClass, + Description: desc, + } + r.resourceClasses = append(r.resourceClasses, rc) + return &rc, nil +} + +func (r *runnerMock) GetResourceClassByName(resourceClass string) (*runner.ResourceClass, error) { + for _, rc := range r.resourceClasses { + if rc.ResourceClass == resourceClass { + return &rc, nil + } + } + return nil, errors.New("not found") +} + +func (r *runnerMock) GetResourceClassesByNamespace(namespace string) ([]runner.ResourceClass, error) { + var rcs []runner.ResourceClass + for _, rc := range r.resourceClasses { + if strings.Split(rc.ResourceClass, "/")[0] == namespace { + rcs = append(rcs, rc) + } + } + return rcs, nil +} + +func (r *runnerMock) DeleteResourceClass(id string) error { + for i, rc := range r.resourceClasses { + if rc.ID == id { + r.resourceClasses = append(r.resourceClasses[:i], r.resourceClasses[i+1:]...) + return nil + } + } + return errors.New("not found") +} + +func (r *runnerMock) CreateToken(resourceClass, nickname string) (*runner.Token, error) { + token := runner.Token{ + ID: uuid.New().String(), + Token: "fake-token", + ResourceClass: resourceClass, + Nickname: nickname, + CreatedAt: time.Now(), + } + r.tokens = append(r.tokens, token) + return &token, nil +} + +func (r *runnerMock) GetRunnerTokensByResourceClass(resourceClass string) ([]runner.Token, error) { + var tokens []runner.Token + for _, token := range r.tokens { + if token.ResourceClass == resourceClass { + tokens = append(tokens, token) + } + } + return tokens, nil +} + +func (r *runnerMock) DeleteToken(id string) error { + for i, token := range r.tokens { + if token.ID == id { + r.tokens = append(r.tokens[:i], r.tokens[i+1:]...) + return nil + } + } + return errors.New("not found") +} + +func (r *runnerMock) GetRunnerInstances(_ string) ([]runner.RunnerInstance, error) { + return nil, nil +} + +func (r *runnerMock) cleanup() { + r.resourceClasses = nil + r.tokens = nil +} diff --git a/cmd/runner/runner.go b/cmd/runner/runner.go index b43941b9c..616e9f267 100644 --- a/cmd/runner/runner.go +++ b/cmd/runner/runner.go @@ -9,7 +9,7 @@ import ( ) type runnerOpts struct { - r *runner.Runner + r running } func NewCommand(config *settings.Config, preRunE validator) *cobra.Command { @@ -27,4 +27,15 @@ func NewCommand(config *settings.Config, preRunE validator) *cobra.Command { return cmd } +type running interface { + CreateResourceClass(resourceClass, desc string) (rc *runner.ResourceClass, err error) + GetResourceClassByName(resourceClass string) (rc *runner.ResourceClass, err error) + GetResourceClassesByNamespace(namespace string) ([]runner.ResourceClass, error) + DeleteResourceClass(id string) error + CreateToken(resourceClass, nickname string) (token *runner.Token, err error) + GetRunnerTokensByResourceClass(resourceClass string) ([]runner.Token, error) + DeleteToken(id string) error + GetRunnerInstances(query string) ([]runner.RunnerInstance, error) +} + type validator func(cmd *cobra.Command, args []string) error diff --git a/cmd/runner/testdata/runner/resource-class/create-expected-usage.txt b/cmd/runner/testdata/runner/resource-class/create-expected-usage.txt index 43cfc530f..c23ce9526 100644 --- a/cmd/runner/testdata/runner/resource-class/create-expected-usage.txt +++ b/cmd/runner/testdata/runner/resource-class/create-expected-usage.txt @@ -1,2 +1,5 @@ Usage: - runner resource-class create + runner resource-class create [flags] + +Flags: + --generate-token Generate a default token diff --git a/go.mod b/go.mod index f7be1eefd..169057525 100644 --- a/go.mod +++ b/go.mod @@ -47,6 +47,7 @@ require ( github.com/gobuffalo/syncx v0.0.0-20181120194010-558ac7de985f // indirect github.com/golang/protobuf v1.4.2 // indirect github.com/google/go-cmp v0.4.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/imdario/mergo v0.3.9 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect diff --git a/go.sum b/go.sum index 7af4f8541..b3a22e19f 100644 --- a/go.sum +++ b/go.sum @@ -237,6 +237,8 @@ github.com/google/go-github v15.0.0+incompatible h1:jlPg2Cpsxb/FyEV/MFiIE9tW/2RA github.com/google/go-github v15.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY=