Skip to content

Commit

Permalink
Merge pull request #52 from hashicorp/WAYP-2339-add-ons
Browse files Browse the repository at this point in the history
`hcp waypoint add-ons` CLI
  • Loading branch information
paladin-devops authored Apr 4, 2024
2 parents aab8602 + 104a0b5 commit abb1895
Show file tree
Hide file tree
Showing 24 changed files with 741 additions and 45 deletions.
3 changes: 3 additions & 0 deletions .changelog/52.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:feature
waypoint: Add `hcp waypoint add-ons` CLI for managing HCP Waypoint add-ons.
```
20 changes: 20 additions & 0 deletions internal/commands/waypoint/add-ons/add_on.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,21 @@ package addons

import (
"github.com/hashicorp/hcp/internal/commands/waypoint/add-ons/definitions"
"github.com/hashicorp/hcp/internal/commands/waypoint/opts"
"github.com/hashicorp/hcp/internal/pkg/cmd"
"github.com/hashicorp/hcp/internal/pkg/heredoc"
)

type AddOnOpts struct {
opts.WaypointOpts

Name string
AddOnDefinitionName string
ApplicationName string

testFunc func(c *cmd.Command, args []string) error
}

func NewCmdAddOn(ctx *cmd.Context) *cmd.Command {
cmd := &cmd.Command{
Name: "add-ons",
Expand All @@ -18,5 +29,14 @@ manage HCP Waypoint add-ons and add-on definitions.

cmd.AddChild(definitions.NewCmdAddOnDefinition(ctx))

opts := &AddOnOpts{
WaypointOpts: opts.New(ctx),
}

cmd.AddChild(NewCmdCreate(ctx, opts))
cmd.AddChild(NewCmdDestroy(ctx, opts))
cmd.AddChild(NewCmdRead(ctx, opts))
cmd.AddChild(NewCmdList(ctx, opts))

return cmd
}
100 changes: 100 additions & 0 deletions internal/commands/waypoint/add-ons/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package addons

import (
"fmt"

"github.com/hashicorp/hcp-sdk-go/clients/cloud-waypoint-service/preview/2023-08-18/client/waypoint_service"
"github.com/hashicorp/hcp-sdk-go/clients/cloud-waypoint-service/preview/2023-08-18/models"
"github.com/hashicorp/hcp/internal/pkg/cmd"
"github.com/hashicorp/hcp/internal/pkg/flagvalue"
"github.com/hashicorp/hcp/internal/pkg/heredoc"
"github.com/pkg/errors"
)

func NewCmdCreate(ctx *cmd.Context, opts *AddOnOpts) *cmd.Command {
cmd := &cmd.Command{
Name: "create",
ShortHelp: "Create a new HCP Waypoint add-on.",
LongHelp: heredoc.New(ctx.IO).Must(`
The {{ template "mdCodeOrBold" "hcp waypoint add-ons create" }} command creates a new HCP Waypoint add-on.
`),
Examples: []cmd.Example{
{
Preamble: "Create a new HCP Waypoint add-on:",
Command: heredoc.New(ctx.IO, heredoc.WithPreserveNewlines()).Must(`
$ hcp waypoint add-ons create -n=my-addon -a=my-application -d=my-addon-definition
`),
},
},
AdditionalDocs: nil,
PersistentPreRun: func(c *cmd.Command, args []string) error {
return cmd.RequireOrgAndProject(ctx)
},
RunF: func(c *cmd.Command, args []string) error {
if opts.testFunc != nil {
return opts.testFunc(c, args)
}
return addOnCreate(opts)
},
Flags: cmd.Flags{
Local: []*cmd.Flag{
{
Name: "name",
Shorthand: "n",
DisplayValue: "NAME",
Description: "The name of the add-on. If no name is provided," +
" a name will be generated.",
Value: flagvalue.Simple("", &opts.Name),
Required: false,
},
{
Name: "add-on-definition-name",
DisplayValue: "NAME",
Description: "The name of the add-on definition to use.",
Value: flagvalue.Simple("", &opts.AddOnDefinitionName),
Required: true,
},
{
Name: "application-name",
DisplayValue: "NAME",
Description: "The name of the application to which the add-on will be added.",
Value: flagvalue.Simple("", &opts.ApplicationName),
Required: true,
},
},
},
}

return cmd
}

func addOnCreate(opts *AddOnOpts) error {
ns, err := opts.Namespace()
if err != nil {
return err
}

_, err = opts.WS.WaypointServiceCreateAddOn(
&waypoint_service.WaypointServiceCreateAddOnParams{
NamespaceID: ns.ID,
Context: opts.Ctx,
Body: &models.HashicorpCloudWaypointWaypointServiceCreateAddOnBody{
Application: &models.HashicorpCloudWaypointRefApplication{
Name: opts.ApplicationName,
},
Definition: &models.HashicorpCloudWaypointRefAddOnDefinition{
Name: opts.AddOnDefinitionName,
},
Name: opts.Name,
},
}, nil)
if err != nil {
return errors.Wrapf(err, "%s failed to create add-on %q",
opts.IO.ColorScheme().FailureIcon(),
opts.Name)
}

fmt.Fprintf(opts.IO.Err(), "%s Add-on %q created!\n", opts.IO.ColorScheme().SuccessIcon(), opts.Name)

return nil
}
89 changes: 89 additions & 0 deletions internal/commands/waypoint/add-ons/create_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package addons

import (
"context"
"testing"

"github.com/go-openapi/runtime/client"
"github.com/hashicorp/hcp/internal/pkg/cmd"
"github.com/hashicorp/hcp/internal/pkg/format"
"github.com/hashicorp/hcp/internal/pkg/iostreams"
"github.com/hashicorp/hcp/internal/pkg/profile"
"github.com/stretchr/testify/require"
)

func TestNewCmdCreate(t *testing.T) {
t.Parallel()

cases := []struct {
Name string
Args []string
Profile func(t *testing.T) *profile.Profile
Error string
Expect *AddOnOpts
}{
{
Name: "No Org",
Profile: profile.TestProfile,
Args: []string{},
Error: "Organization ID must be configured",
},
{
Name: "no args",
Profile: func(t *testing.T) *profile.Profile {
return profile.TestProfile(t).SetOrgID("123")
},
Args: []string{},
Error: "accepts 1 arg(s), received 0",
},
{
Name: "happy",
Profile: func(t *testing.T) *profile.Profile {
return profile.TestProfile(t).SetOrgID("123")
},
Args: []string{
"-n=cli-test",
"--application-name=testApp",
"--add-on-definition-name=testAddOnDefinition",
},
Expect: &AddOnOpts{
Name: "cli-test",
ApplicationName: "testApp",
AddOnDefinitionName: "testAddOnDefinition",
},
},
}

for _, c := range cases {
c := c
t.Run(c.Name, func(t *testing.T) {
t.Parallel()

r := require.New(t)

io := iostreams.Test()
ctx := &cmd.Context{
IO: io,
Profile: c.Profile(t),
ShutdownCtx: context.Background(),
HCP: &client.Runtime{},
Output: format.New(io),
}

var addOnOpts AddOnOpts
addOnOpts.testFunc = func(c *cmd.Command, args []string) error {
return nil
}
cmd := NewCmdCreate(ctx, &addOnOpts)
cmd.SetIO(io)

cmd.Run(c.Args)

if c.Expect != nil {
r.Equal(c.Expect.Name, addOnOpts.Name)
r.Equal(c.Expect.ApplicationName, addOnOpts.ApplicationName)
r.Equal(c.Expect.AddOnDefinitionName, addOnOpts.AddOnDefinitionName)
}
})
}
}
20 changes: 10 additions & 10 deletions internal/commands/waypoint/add-ons/definitions/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ command lets you create HCP Waypoint add-on definitions.
{
Preamble: "Create a new HCP Waypoint add-on definition:",
Command: heredoc.New(ctx.IO, heredoc.WithPreserveNewlines()).Must(`
$ hcp waypoint add-ons definitions create -n my-add-on-definition \
-s "My Add-on Definition summary." \
-d "My Add-on Definition description." \
--readme-markdown-template-file "README.tpl" \
--tfc-no-code-module-source "app.terraform.io/hashicorp/dir/template" \
--tfc-no-code-module-version "1.0.2" \
--tfc-project-name "my-tfc-project" \
--tfc-project-id "prj-123456" \
-l label1 \
-l label2
$ hcp waypoint add-ons definitions create -n=my-add-on-definition \
-s="My Add-on Definition summary." \
-d="My Add-on Definition description." \
--readme-markdown-template-file="README.tpl" \
--tfc-no-code-module-source="app.terraform.io/hashicorp/dir/template" \
--tfc-no-code-module-version="1.0.2" \
--tfc-project-name="my-tfc-project" \
--tfc-project-id="prj-123456" \
-l=label1 \
-l=label2
`),
},
},
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/waypoint/add-ons/definitions/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ command lets you delete an existing HCP Waypoint add-on definition.
{
Preamble: "Delete an HCP Waypoint add-on definition:",
Command: heredoc.New(ctx.IO, heredoc.WithPreserveNewlines()).Must(`
$ hcp waypoint add-ons definitions delete -n my-addon-definition
$ hcp waypoint add-ons definitions delete -n=my-addon-definition
`),
},
},
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/waypoint/add-ons/definitions/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ command lets you read an existing HCP Waypoint add-on definition.
{
Preamble: "Read an HCP Waypoint add-on definition:",
Command: heredoc.New(ctx.IO, heredoc.WithPreserveNewlines()).Must(`
$ hcp waypoint add-ons definitions read -n my-addon-definition
$ hcp waypoint add-ons definitions read -n=my-addon-definition
`),
},
},
Expand Down
16 changes: 8 additions & 8 deletions internal/commands/waypoint/add-ons/definitions/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ command lets you update an existing HCP Waypoint add-on definition.
Preamble: "Update a HCP Waypoint add-on definition:",
Command: heredoc.New(ctx.IO, heredoc.WithPreserveNewlines()).Must(`
$ hcp waypoint add-ons definitions update -n=my-add-on-definition \
-s "My updated Add-on Definition summary." \
-d "My updated Add-on Definition description." \
-s="My updated Add-on Definition summary." \
-d="My updated Add-on Definition description." \
--readme-markdown-template-file "README.tpl" \
--tfc-no-code-module-source "app.terraform.io/hashicorp/dir/template" \
--tfc-no-code-module-version "1.0.2" \
--tfc-project-name "my-tfc-project" \
--tfc-project-id "prj-123456" \
-l label1 \
-l label2
--tfc-no-code-module-source="app.terraform.io/hashicorp/dir/template" \
--tfc-no-code-module-version="1.0.2" \
--tfc-project-name="my-tfc-project" \
--tfc-project-id="prj-123456" \
-l=label1 \
-l=label2
`),
},
},
Expand Down
76 changes: 76 additions & 0 deletions internal/commands/waypoint/add-ons/destroy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package addons

import (
"fmt"

"github.com/hashicorp/hcp-sdk-go/clients/cloud-waypoint-service/preview/2023-08-18/client/waypoint_service"
"github.com/hashicorp/hcp/internal/pkg/cmd"
"github.com/hashicorp/hcp/internal/pkg/flagvalue"
"github.com/hashicorp/hcp/internal/pkg/heredoc"
"github.com/pkg/errors"
)

func NewCmdDestroy(ctx *cmd.Context, opts *AddOnOpts) *cmd.Command {
cmd := &cmd.Command{
Name: "destroy",
ShortHelp: "Destroy an HCP Waypoint add-ons.",
LongHelp: heredoc.New(ctx.IO).Must(`
The {{ template "mdCodeOrBold" "hcp waypoint add-ons destroy" }} command lets you
destroy an existing HCP Waypoint add-on.
`),
Examples: []cmd.Example{
{
Preamble: "Destroy an HCP Waypoint add-on:",
Command: heredoc.New(ctx.IO, heredoc.WithPreserveNewlines()).Must(`
$ hcp waypoint add-ons destroy -n=my-addon
`),
},
},
RunF: func(c *cmd.Command, args []string) error {
if opts.testFunc != nil {
return opts.testFunc(c, args)
}
return addOnDestroy(opts)
},
PersistentPreRun: func(c *cmd.Command, args []string) error {
return cmd.RequireOrgAndProject(ctx)
},
Flags: cmd.Flags{
Local: []*cmd.Flag{
{
Name: "name",
Shorthand: "n",
DisplayValue: "NAME",
Description: "The name of the add-on to destroy.",
Value: flagvalue.Simple("", &opts.Name),
Required: true,
},
},
},
}
return cmd
}

func addOnDestroy(opts *AddOnOpts) error {
ns, err := opts.Namespace()
if err != nil {
return err
}

_, err = opts.WS.WaypointServiceDestroyAddOn2(
&waypoint_service.WaypointServiceDestroyAddOn2Params{
NamespaceID: ns.ID,
Context: opts.Ctx,
AddOnName: opts.Name,
}, nil,
)
if err != nil {
return errors.Wrapf(err, "%s failed to destroy add-on %q",
opts.IO.ColorScheme().FailureIcon(),
opts.Name)
}

fmt.Fprintf(opts.IO.Out(), "Add-on %s destroyed\n", opts.Name)

return nil
}
Loading

0 comments on commit abb1895

Please sign in to comment.