Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add service search command #152

Merged
merged 2 commits into from Sep 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 16 additions & 2 deletions go.mod
Expand Up @@ -12,24 +12,38 @@ require (
github.com/fastly/go-fastly v1.16.0
github.com/fatih/color v1.7.0
github.com/frankban/quicktest v1.5.0 // indirect
github.com/go-delve/delve v1.5.0 // indirect
github.com/google/go-cmp v0.3.1
github.com/google/go-dap v0.3.0 // indirect
github.com/google/go-github/v28 v28.1.1
github.com/google/jsonapi v0.0.0-20200226002910-c8283f632fb7 // indirect
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
github.com/kennygrant/sanitize v1.2.4
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/mattn/go-isatty v0.0.10 // indirect
github.com/mattn/go-colorable v0.1.7 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mholt/archiver v3.1.1+incompatible
github.com/mholt/archiver/v3 v3.3.0
github.com/mitchellh/go-wordwrap v1.0.0
github.com/mitchellh/mapstructure v1.3.2
github.com/nicksnyder/go-i18n v1.10.1 // indirect
github.com/onsi/ginkgo v1.8.0 // indirect
github.com/onsi/gomega v1.5.0 // indirect
github.com/peterh/liner v1.2.0 // indirect
github.com/pierrec/lz4 v2.3.0+incompatible // indirect
github.com/pkg/profile v0.0.0-20170413231811-06b906832ed0 // indirect
github.com/segmentio/textio v1.2.0
github.com/spf13/cobra v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.starlark.net v0.0.0-20200901195727-6e684ef5eeee // indirect
golang.org/x/arch v0.0.0-20200826200359-b19915210f00 // indirect
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d // indirect
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
gopkg.in/src-d/go-git.v4 v4.13.1
gopkg.in/yaml.v2 v2.3.0 // indirect
)
207 changes: 207 additions & 0 deletions go.sum

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pkg/api/interface.go
Expand Up @@ -25,6 +25,7 @@ type Interface interface {
GetServiceDetails(*fastly.GetServiceInput) (*fastly.ServiceDetail, error)
UpdateService(*fastly.UpdateServiceInput) (*fastly.Service, error)
DeleteService(*fastly.DeleteServiceInput) error
SearchService(*fastly.SearchServiceInput) (*fastly.Service, error)

CloneVersion(*fastly.CloneVersionInput) (*fastly.Version, error)
ListVersions(*fastly.ListVersionsInput) ([]*fastly.Version, error)
Expand Down
4 changes: 3 additions & 1 deletion pkg/app/run.go
Expand Up @@ -90,7 +90,7 @@ func Run(args []string, env config.Environment, file config.File, configFilePath
})

// Prevent kingpin from calling os.Exit, this gives us greater control over
// error states and output contorl flow.
// error states and output control flow.
app.Terminate(nil)

// As kingpin generates bash completion as a side-effect of kingpin.Parse we
Expand Down Expand Up @@ -118,6 +118,7 @@ func Run(args []string, env config.Environment, file config.File, configFilePath
serviceDescribe := service.NewDescribeCommand(serviceRoot.CmdClause, &globals)
serviceUpdate := service.NewUpdateCommand(serviceRoot.CmdClause, &globals)
serviceDelete := service.NewDeleteCommand(serviceRoot.CmdClause, &globals)
serviceSearch := service.NewSearchCommand(serviceRoot.CmdClause, &globals)

serviceVersionRoot := serviceversion.NewRootCommand(app, &globals)
serviceVersionClone := serviceversion.NewCloneCommand(serviceVersionRoot.CmdClause, &globals)
Expand Down Expand Up @@ -342,6 +343,7 @@ func Run(args []string, env config.Environment, file config.File, configFilePath
serviceDescribe,
serviceUpdate,
serviceDelete,
serviceSearch,

serviceVersionRoot,
serviceVersionClone,
Expand Down
10 changes: 10 additions & 0 deletions pkg/app/run_test.go
Expand Up @@ -156,6 +156,11 @@ SUBCOMMANDS

-s, --service-id=SERVICE-ID Service ID

service search [<flags>]
Search for a Fastly service by name

-n, --name=NAME Service name

`) + "\n\n"

var fullFatHelpDefault = strings.TrimSpace(`
Expand Down Expand Up @@ -219,6 +224,11 @@ COMMANDS

-s, --service-id=SERVICE-ID Service ID

service search [<flags>]
Search for a Fastly service by name

-n, --name=NAME Service name

service-version clone --version=VERSION [<flags>]
Clone a Fastly service version

Expand Down
6 changes: 6 additions & 0 deletions pkg/mock/api.go
Expand Up @@ -16,6 +16,7 @@ type API struct {
GetServiceDetailsFn func(*fastly.GetServiceInput) (*fastly.ServiceDetail, error)
UpdateServiceFn func(*fastly.UpdateServiceInput) (*fastly.Service, error)
DeleteServiceFn func(*fastly.DeleteServiceInput) error
SearchServiceFn func(*fastly.SearchServiceInput) (*fastly.Service, error)

CloneVersionFn func(*fastly.CloneVersionInput) (*fastly.Version, error)
ListVersionsFn func(*fastly.ListVersionsInput) ([]*fastly.Version, error)
Expand Down Expand Up @@ -221,6 +222,11 @@ func (m API) GetServiceDetails(i *fastly.GetServiceInput) (*fastly.ServiceDetail
return m.GetServiceDetailsFn(i)
}

// SearchService implements Interface.
func (m API) SearchService(i *fastly.SearchServiceInput) (*fastly.Service, error) {
return m.SearchServiceFn(i)
}

// UpdateService implements Interface.
func (m API) UpdateService(i *fastly.UpdateServiceInput) (*fastly.Service, error) {
return m.UpdateServiceFn(i)
Expand Down
39 changes: 39 additions & 0 deletions pkg/service/search.go
@@ -0,0 +1,39 @@
package service

import (
"io"

"github.com/fastly/cli/pkg/common"
"github.com/fastly/cli/pkg/compute/manifest"
"github.com/fastly/cli/pkg/config"
"github.com/fastly/cli/pkg/text"
"github.com/fastly/go-fastly/fastly"
)

// SearchCommand calls the Fastly API to describe a service.
type SearchCommand struct {
common.Base
manifest manifest.Data
Input fastly.SearchServiceInput
}

// NewSearchCommand returns a usable command registered under the parent.
func NewSearchCommand(parent common.Registerer, globals *config.Data) *SearchCommand {
var c SearchCommand
c.Globals = globals
c.manifest.File.Read(manifest.Filename)
c.CmdClause = parent.Command("search", "Search for a Fastly service by name")
c.CmdClause.Flag("name", "Service name").Short('n').StringVar(&c.Input.Name)
return &c
}

// Exec invokes the application logic for the command.
func (c *SearchCommand) Exec(in io.Reader, out io.Writer) error {
service, err := c.Globals.Client.SearchService(&c.Input)
if err != nil {
return err
}

text.PrintService(out, "", service)
return nil
}
139 changes: 139 additions & 0 deletions pkg/service/service_test.go
Expand Up @@ -197,6 +197,48 @@ func TestServiceDescribe(t *testing.T) {
}
}

func TestServiceSearch(t *testing.T) {
for _, testcase := range []struct {
args []string
api mock.API
wantError string
wantOutput string
}{
{
args: []string{"service", "search", "--name", "Foo"},
api: mock.API{SearchServiceFn: searchServiceOK},
wantOutput: searchServiceShortOutput,
},
{
args: []string{"service", "search", "--name", "Foo", "-v"},
api: mock.API{SearchServiceFn: searchServiceOK},
wantOutput: searchServiceVerboseOutput,
},
{
args: []string{"service", "search", "--name"},
api: mock.API{SearchServiceFn: searchServiceOK},
wantError: "error parsing arguments: expected argument for flag '--name'",
},
} {
t.Run(strings.Join(testcase.args, " "), func(t *testing.T) {
var (
args = testcase.args
env = config.Environment{}
file = config.File{}
appConfigFile = "/dev/null"
clientFactory = mock.APIClient(testcase.api)
httpClient = http.DefaultClient
versioner update.Versioner = nil
in io.Reader = nil
out bytes.Buffer
)
err := app.Run(args, env, file, appConfigFile, clientFactory, httpClient, versioner, in, &out)
testutil.AssertErrorContains(t, err, testcase.wantError)
testutil.AssertString(t, testcase.wantOutput, out.String())
})
}
}

func TestServiceUpdate(t *testing.T) {
for _, testcase := range []struct {
args []string
Expand Down Expand Up @@ -612,6 +654,103 @@ Versions: 2
Last edited (UTC): 2001-03-04 04:05
`) + "\n"

func searchServiceOK(i *fastly.SearchServiceInput) (*fastly.Service, error) {
return &fastly.Service{
ID: "123",
Name: "Foo",
Type: "wasm",
CustomerID: "mycustomerid",
UpdatedAt: testutil.MustParseTimeRFC3339("2010-11-15T19:01:02Z"),
Versions: []*fastly.Version{
&fastly.Version{
Number: 1,
Comment: "a",
ServiceID: "b",
CreatedAt: testutil.MustParseTimeRFC3339("2001-02-03T04:05:06Z"),
UpdatedAt: testutil.MustParseTimeRFC3339("2001-02-04T04:05:06Z"),
DeletedAt: testutil.MustParseTimeRFC3339("2001-02-05T04:05:06Z"),
},
&fastly.Version{
Number: 2,
Comment: "c",
ServiceID: "d",
Active: true,
Deployed: true,
CreatedAt: testutil.MustParseTimeRFC3339("2001-03-03T04:05:06Z"),
UpdatedAt: testutil.MustParseTimeRFC3339("2001-03-04T04:05:06Z"),
},
},
}, nil
}

var searchServiceShortOutput = strings.TrimSpace(`
ID: 123
Name: Foo
Type: wasm
Customer ID: mycustomerid
Last edited (UTC): 2010-11-15 19:01
Active version: 0
Versions: 2
Version 1/2
Number: 1
Comment: a
Service ID: b
Active: false
Locked: false
Deployed: false
Staging: false
Testing: false
Created (UTC): 2001-02-03 04:05
Last edited (UTC): 2001-02-04 04:05
Deleted (UTC): 2001-02-05 04:05
Version 2/2
Number: 2
Comment: c
Service ID: d
Active: true
Locked: false
Deployed: true
Staging: false
Testing: false
Created (UTC): 2001-03-03 04:05
Last edited (UTC): 2001-03-04 04:05
`) + "\n"

var searchServiceVerboseOutput = strings.TrimSpace(`
Fastly API token not provided
Fastly API endpoint: https://api.fastly.com
ID: 123
Name: Foo
Type: wasm
Customer ID: mycustomerid
Last edited (UTC): 2010-11-15 19:01
Active version: 0
Versions: 2
Version 1/2
Number: 1
Comment: a
Service ID: b
Active: false
Locked: false
Deployed: false
Staging: false
Testing: false
Created (UTC): 2001-02-03 04:05
Last edited (UTC): 2001-02-04 04:05
Deleted (UTC): 2001-02-05 04:05
Version 2/2
Number: 2
Comment: c
Service ID: d
Active: true
Locked: false
Deployed: true
Staging: false
Testing: false
Created (UTC): 2001-03-03 04:05
Last edited (UTC): 2001-03-04 04:05
`) + "\n"

func updateServiceOK(i *fastly.UpdateServiceInput) (*fastly.Service, error) {
return &fastly.Service{
ID: "12345",
Expand Down