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

feat(resource-link): Add Service Resource commands #800

Merged
merged 13 commits into from
Feb 22, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkg/api/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,10 @@ type Interface interface {
GetSigningKey() (ed25519.PublicKey, error)

CreateResource(i *fastly.CreateResourceInput) (*fastly.Resource, error)
DeleteResource(i *fastly.DeleteResourceInput) error
GetResource(i *fastly.GetResourceInput) (*fastly.Resource, error)
ListResources(i *fastly.ListResourcesInput) ([]*fastly.Resource, error)
UpdateResource(i *fastly.UpdateResourceInput) (*fastly.Resource, error)
}

// RealtimeStatsInterface is the subset of go-fastly's realtime stats API used here.
Expand Down
13 changes: 13 additions & 0 deletions pkg/app/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"github.com/fastly/cli/pkg/commands/pop"
"github.com/fastly/cli/pkg/commands/profile"
"github.com/fastly/cli/pkg/commands/purge"
"github.com/fastly/cli/pkg/commands/resourcelink"
"github.com/fastly/cli/pkg/commands/secretstore"
"github.com/fastly/cli/pkg/commands/secretstoreentry"
"github.com/fastly/cli/pkg/commands/service"
Expand Down Expand Up @@ -311,6 +312,12 @@ func defineCommands(
profileToken := profile.NewTokenCommand(profileCmdRoot.CmdClause, g)
profileUpdate := profile.NewUpdateCommand(profileCmdRoot.CmdClause, profile.APIClientFactory(opts.APIClient), g)
purgeCmdRoot := purge.NewRootCommand(app, g, m)
resourcelinkCmdRoot := resourcelink.NewRootCommand(app, g)
resourcelinkCreate := resourcelink.NewCreateCommand(resourcelinkCmdRoot.CmdClause, g, m)
resourcelinkDelete := resourcelink.NewDeleteCommand(resourcelinkCmdRoot.CmdClause, g, m)
resourcelinkDescribe := resourcelink.NewDescribeCommand(resourcelinkCmdRoot.CmdClause, g, m)
resourcelinkList := resourcelink.NewListCommand(resourcelinkCmdRoot.CmdClause, g, m)
resourcelinkUpdate := resourcelink.NewUpdateCommand(resourcelinkCmdRoot.CmdClause, g, m)
secretstoreCmdRoot := secretstore.NewRootCommand(app, g)
secretstoreCreate := secretstore.NewCreateCommand(secretstoreCmdRoot.CmdClause, g, m)
secretstoreDescribe := secretstore.NewDescribeCommand(secretstoreCmdRoot.CmdClause, g, m)
Expand Down Expand Up @@ -635,6 +642,12 @@ func defineCommands(
profileToken,
profileUpdate,
purgeCmdRoot,
resourcelinkCmdRoot,
resourcelinkCreate,
resourcelinkDelete,
resourcelinkDescribe,
resourcelinkList,
resourcelinkUpdate,
secretstoreCreate,
secretstoreDescribe,
secretstoreDelete,
Expand Down
1 change: 1 addition & 0 deletions pkg/app/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ object-store-entry
pops
profile
purge
resource-link
secret-store
secret-store-entry
service
Expand Down
128 changes: 128 additions & 0 deletions pkg/commands/resourcelink/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package resourcelink

import (
"io"

"github.com/fastly/cli/pkg/cmd"
fsterr "github.com/fastly/cli/pkg/errors"
"github.com/fastly/cli/pkg/global"
"github.com/fastly/cli/pkg/manifest"
"github.com/fastly/cli/pkg/text"
"github.com/fastly/go-fastly/v7/fastly"
)

// CreateCommand calls the Fastly API to create a resource link.
type CreateCommand struct {
cmd.Base
cmd.JSONOutput

autoClone cmd.OptionalAutoClone
input fastly.CreateResourceInput
manifest manifest.Data
serviceName cmd.OptionalServiceNameID
serviceVersion cmd.OptionalServiceVersion
}

// NewCreateCommand returns a usable command registered under the parent.
func NewCreateCommand(parent cmd.Registerer, g *global.Data, m manifest.Data) *CreateCommand {
c := CreateCommand{
Base: cmd.Base{
Globals: g,
},
manifest: m,
input: fastly.CreateResourceInput{
// Kingpin requires the following to be initialized.
ResourceID: new(string),
Name: new(string),
},
}
c.CmdClause = parent.Command("create", "Create a Fastly service resource link").Alias("link")

// Required.
c.RegisterFlag(cmd.StringFlagOpts{
Name: "resource-id",
Short: 'r',
Description: flagResourceIDDescription,
Dst: c.input.ResourceID,
Required: true,
})
c.RegisterFlag(cmd.StringFlagOpts{
Name: cmd.FlagVersionName,
Description: cmd.FlagVersionDesc,
Dst: &c.serviceVersion.Value,
Required: true,
})

// At least one of the following is required.
c.RegisterFlag(cmd.StringFlagOpts{
Name: cmd.FlagServiceIDName,
Short: 's',
Description: cmd.FlagServiceIDDesc,
Dst: &c.manifest.Flag.ServiceID,
})
c.RegisterFlag(cmd.StringFlagOpts{
Name: cmd.FlagServiceName,
Action: c.serviceName.Set,
Description: cmd.FlagServiceDesc,
Dst: &c.serviceName.Value,
})

// Optional.
c.RegisterAutoCloneFlag(cmd.AutoCloneFlagOpts{
Action: c.autoClone.Set,
Dst: &c.autoClone.Value,
})
c.RegisterFlagBool(c.JSONFlag()) // --json
c.RegisterFlag(cmd.StringFlagOpts{
Name: "name",
Short: 'n',
Description: flagNameDescription,
Dst: c.input.Name,
})

return &c
}

// Exec invokes the application logic for the command.
func (c *CreateCommand) Exec(_ io.Reader, out io.Writer) error {
if c.Globals.Verbose() && c.JSONOutput.Enabled {
return fsterr.ErrInvalidVerboseJSONCombo
}

serviceID, serviceVersion, err := cmd.ServiceDetails(cmd.ServiceDetailsOpts{
AutoCloneFlag: c.autoClone,
APIClient: c.Globals.APIClient,
Manifest: c.manifest,
Out: out,
ServiceNameFlag: c.serviceName,
ServiceVersionFlag: c.serviceVersion,
VerboseMode: c.Globals.Flags.Verbose,
})
if err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"Service ID": c.manifest.Flag.ServiceID,
"Service Version": fsterr.ServiceVersion(serviceVersion),
})
return err
}

c.input.ServiceID = serviceID
c.input.ServiceVersion = serviceVersion.Number

resource, err := c.Globals.APIClient.CreateResource(&c.input)
if err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"ID": c.input.ResourceID,
"Service ID": c.input.ServiceID,
"Service Version": c.input.ServiceVersion,
})
return err
}

if ok, err := c.WriteJSON(out, resource); ok {
return err
}

text.Success(out, "Created service resource link %q (%s) on service %s version %s", resource.Name, resource.ID, resource.ServiceID, resource.ServiceVersion)
return nil
}
128 changes: 128 additions & 0 deletions pkg/commands/resourcelink/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package resourcelink

import (
"io"

"github.com/fastly/cli/pkg/cmd"
fsterr "github.com/fastly/cli/pkg/errors"
"github.com/fastly/cli/pkg/global"
"github.com/fastly/cli/pkg/manifest"
"github.com/fastly/cli/pkg/text"
"github.com/fastly/go-fastly/v7/fastly"
)

// DeleteCommand calls the Fastly API to delete service resource links.
type DeleteCommand struct {
cmd.Base
cmd.JSONOutput

autoClone cmd.OptionalAutoClone
input fastly.DeleteResourceInput
manifest manifest.Data
serviceName cmd.OptionalServiceNameID
serviceVersion cmd.OptionalServiceVersion
}

// NewDeleteCommand returns a usable command registered under the parent.
func NewDeleteCommand(parent cmd.Registerer, g *global.Data, m manifest.Data) *DeleteCommand {
c := DeleteCommand{
Base: cmd.Base{
Globals: g,
},
manifest: m,
}
c.CmdClause = parent.Command("delete", "Delete a resource link for a Fastly service version").Alias("remove")

// Required.
c.RegisterFlag(cmd.StringFlagOpts{
Name: "id",
Description: flagIDDescription,
Dst: &c.input.ID,
Required: true,
})
c.RegisterFlag(cmd.StringFlagOpts{
Name: cmd.FlagVersionName,
Description: cmd.FlagVersionDesc,
Dst: &c.serviceVersion.Value,
Required: true,
})

// At least one of the following is required.
c.RegisterFlag(cmd.StringFlagOpts{
Name: cmd.FlagServiceIDName,
Short: 's',
Description: cmd.FlagServiceIDDesc,
Dst: &c.manifest.Flag.ServiceID,
})
c.RegisterFlag(cmd.StringFlagOpts{
Name: cmd.FlagServiceName,
Action: c.serviceName.Set,
Description: cmd.FlagServiceDesc,
Dst: &c.serviceName.Value,
})

// Optional.
c.RegisterAutoCloneFlag(cmd.AutoCloneFlagOpts{
Action: c.autoClone.Set,
Dst: &c.autoClone.Value,
})
c.RegisterFlagBool(c.JSONFlag()) // --json

return &c
}

// Exec invokes the application logic for the command.
func (c *DeleteCommand) Exec(_ io.Reader, out io.Writer) error {
if c.Globals.Verbose() && c.JSONOutput.Enabled {
return fsterr.ErrInvalidVerboseJSONCombo
}

serviceID, serviceVersion, err := cmd.ServiceDetails(cmd.ServiceDetailsOpts{
AutoCloneFlag: c.autoClone,
APIClient: c.Globals.APIClient,
Manifest: c.manifest,
Out: out,
ServiceNameFlag: c.serviceName,
ServiceVersionFlag: c.serviceVersion,
VerboseMode: c.Globals.Flags.Verbose,
})
if err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"Service ID": c.manifest.Flag.ServiceID,
"Service Version": fsterr.ServiceVersion(serviceVersion),
})
return err
}

c.input.ServiceID = serviceID
c.input.ServiceVersion = serviceVersion.Number

err = c.Globals.APIClient.DeleteResource(&c.input)
if err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"ID": c.input.ID,
"Service ID": c.input.ServiceID,
"Service Version": c.input.ServiceVersion,
})
return err
}

if c.JSONOutput.Enabled {
o := struct {
ID string `json:"id"`
ServiceID string `json:"service_id"`
ServiceVersion int `json:"service_version"`
Deleted bool `json:"deleted"`
}{
c.input.ID,
c.input.ServiceID,
c.input.ServiceVersion,
true,
}
_, err := c.WriteJSON(out, o)
return err
}

text.Success(out, "Deleted service resource link %s from service %s version %d", c.input.ID, c.input.ServiceID, c.input.ServiceVersion)
return nil
}
Loading