Skip to content

Commit

Permalink
Add option to generate a default token on runner resource class creation
Browse files Browse the repository at this point in the history
  • Loading branch information
christian-stephen committed Oct 5, 2021
1 parent ce8624c commit da5942d
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 5 deletions.
19 changes: 16 additions & 3 deletions cmd/runner/resource_class.go
Expand Up @@ -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 <resource-class> <description>",
Short: "Create a resource-class",
Args: cobra.ExactArgs(2),
Expand All @@ -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 <resource-class>",
Expand Down
147 changes: 147 additions & 0 deletions 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
}
13 changes: 12 additions & 1 deletion cmd/runner/runner.go
Expand Up @@ -9,7 +9,7 @@ import (
)

type runnerOpts struct {
r *runner.Runner
r running
}

func NewCommand(config *settings.Config, preRunE validator) *cobra.Command {
Expand All @@ -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
@@ -1,2 +1,5 @@
Usage:
runner resource-class create <resource-class> <description>
runner resource-class create <resource-class> <description> [flags]

Flags:
--generate-token Generate a default token
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Expand Up @@ -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=
Expand Down

0 comments on commit da5942d

Please sign in to comment.