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 b877efb
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 17 deletions.
8 changes: 4 additions & 4 deletions cmd/runner/instance.go
@@ -1,7 +1,7 @@
package runner

import (
"os"
"io"
"time"

"github.com/olekukonko/tablewriter"
Expand Down Expand Up @@ -30,7 +30,7 @@ func newRunnerInstanceCommand(o *runnerOpts, preRunE validator) *cobra.Command {
return err
}

table := newRunnerInstanceTable()
table := newRunnerInstanceTable(cmd.OutOrStdout())
defer table.Render()
for _, r := range runners {
appendRunnerInstance(table, r)
Expand All @@ -43,8 +43,8 @@ func newRunnerInstanceCommand(o *runnerOpts, preRunE validator) *cobra.Command {
return cmd
}

func newRunnerInstanceTable() *tablewriter.Table {
table := tablewriter.NewWriter(os.Stdout)
func newRunnerInstanceTable(writer io.Writer) *tablewriter.Table {
table := tablewriter.NewWriter(writer)
table.SetHeader([]string{
"Name",
"Resource Class",
Expand Down
29 changes: 21 additions & 8 deletions cmd/runner/resource_class.go
@@ -1,7 +1,7 @@
package runner

import (
"os"
"io"

"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
Expand All @@ -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 @@ -25,12 +26,24 @@ func newResourceClassCommand(o *runnerOpts, preRunE validator) *cobra.Command {
if err != nil {
return err
}
table := newResourceClassTable()
table := newResourceClassTable(cmd.OutOrStdout())
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, cmd.OutOrStdout())
},
})
}
createCmd.PersistentFlags().BoolVar(&genToken, "generate-token", false,
"Generate a default token")
cmd.AddCommand(createCmd)

cmd.AddCommand(&cobra.Command{
Use: "delete <resource-class>",
Expand Down Expand Up @@ -59,7 +72,7 @@ func newResourceClassCommand(o *runnerOpts, preRunE validator) *cobra.Command {
return err
}

table := newResourceClassTable()
table := newResourceClassTable(cmd.OutOrStdout())
defer table.Render()
for _, rc := range rcs {
appendResourceClass(table, rc)
Expand All @@ -72,8 +85,8 @@ func newResourceClassCommand(o *runnerOpts, preRunE validator) *cobra.Command {
return cmd
}

func newResourceClassTable() *tablewriter.Table {
table := tablewriter.NewWriter(os.Stdout)
func newResourceClassTable(writer io.Writer) *tablewriter.Table {
table := tablewriter.NewWriter(writer)
table.SetHeader([]string{"Resource Class", "Description"})
return table
}
Expand Down
155 changes: 155 additions & 0 deletions cmd/runner/resource_class_test.go
@@ -0,0 +1,155 @@
package runner

import (
"bytes"
"strings"
"testing"
"time"

"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)
b := new(bytes.Buffer)
cmd.SetOut(b)

t.Run("create", func(t *testing.T) {
t.Run("without default token", func(t *testing.T) {
defer runner.reset()
defer b.Reset()

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.Contains(b.String(), "my-namespace/my-resource-class"))

assert.Check(t, cmp.Equal(len(runner.tokens), 0))
})

t.Run("with default token", func(t *testing.T) {
defer runner.reset()
defer b.Reset()

cmd.SetArgs([]string{
"create",
"my-namespace/my-other-resource-class",
"my-description",
"--generate-token",
})

err := cmd.Execute()
out := b.String()
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.Contains(out, "my-namespace/my-other-resource-class"))

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"))
assert.Check(t, cmp.Contains(out, "fake-token"))
})
})
}

type runnerMock struct {
resourceClasses []runner.ResourceClass
tokens []runner.Token
}

func (r *runnerMock) CreateResourceClass(resourceClass, desc string) (*runner.ResourceClass, error) {
rc := runner.ResourceClass{
ID: "d8bc155b-5e91-4765-b327-0fa256f0229e",
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: "987905d7-6780-4fed-a637-37277c373629",
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) reset() {
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
5 changes: 2 additions & 3 deletions cmd/runner/token.go
@@ -1,7 +1,6 @@
package runner

import (
"os"
"time"

"github.com/olekukonko/tablewriter"
Expand All @@ -24,7 +23,7 @@ func newTokenCommand(o *runnerOpts, preRunE validator) *cobra.Command {
if err != nil {
return err
}
return generateConfig(*token, os.Stdout)
return generateConfig(*token, cmd.OutOrStdout())
},
})

Expand All @@ -51,7 +50,7 @@ func newTokenCommand(o *runnerOpts, preRunE validator) *cobra.Command {
return err
}

table := tablewriter.NewWriter(os.Stdout)
table := tablewriter.NewWriter(cmd.OutOrStdout())
defer table.Render()
table.SetHeader([]string{"ID", "Nickname", "Created At"})
for _, token := range tokens {
Expand Down

0 comments on commit b877efb

Please sign in to comment.