Skip to content
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
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
</a>
</p>

`shp` (PoC)
`shp`
-----------

This is a proof-of-concept implementation of a command-line client for
[Shipwright's Build](shipwrightbuild) operator, which uses the same pattern than `kubectl`/`oc` and
can be used as a staandalone binary and as a `kubectl` plugin.
This is an implementation of a command-line client for
[Shipwright's Build](shipwrightbuild) operator, which uses the same pattern as `kubectl`/`oc` and
can be used as a standalone binary and as a `kubectl` plugin.

You can expect to read developer's documentation below, the focus on final users with extend
usage documentation will come in the near future.
Expand All @@ -25,7 +25,7 @@ usage documentation will come in the near future.
To install it run:

```sh
go get -u github.com/otaviof/shp/cmd/shp
go get -u github.com/shipwright-io/cli/cmd/shp
```

Or clone the repository, and run `make` to build the binary at `_output` directory:
Expand Down
4 changes: 2 additions & 2 deletions cmd/shp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ func main() {
pflag.CommandLine = flags

streams := genericclioptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
rootCmd := cmd.NewCmdSHP(streams)
rootCmd := cmd.NewCmdSHP(&streams)
if err := rootCmd.Execute(); err != nil {
fmt.Printf("[ERROR] %#v\n", err)
fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we switch to using klog v2 here (and throughout ShipWright)?
That would give us logging levels and InfoF, WarnF, ErrorF, etc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest making a small issue for that. I think it must be done, but not as part of this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. Feel free to create issues and reference them here, please. :-)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#7 was created for this issue.

os.Exit(1)
}
}
2 changes: 1 addition & 1 deletion hack/install-kind.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ kind --version
KIND_CLUSTER_NAME="${KIND_CLUSTER_NAME:-kind}"

# kind cluster version
KIND_CLUSTER_VERSION="${KIND_CLUSTER_VERSION:-v1.17.0}"
KIND_CLUSTER_VERSION="${KIND_CLUSTER_VERSION:-v1.20.2}"

echo "# Creating a new Kubernetes cluster..."
kind create cluster --quiet --name="${KIND_CLUSTER_NAME}" --image="kindest/node:${KIND_CLUSTER_VERSION}" --wait=120s
Expand Down
30 changes: 5 additions & 25 deletions pkg/shp/cmd/build/build.go
Original file line number Diff line number Diff line change
@@ -1,32 +1,17 @@
package build

import (
"os"

buildv1alpha1 "github.com/shipwright-io/build/pkg/apis/build/v1alpha1"
"github.com/spf13/cobra"

"k8s.io/cli-runtime/pkg/genericclioptions"

"github.com/shipwright-io/cli/pkg/shp/cmd/runner"
"github.com/shipwright-io/cli/pkg/shp/params"
"github.com/shipwright-io/cli/pkg/shp/resource"
)

var (
buildResource *resource.Resource
)

// Command returns Build subcommand of Shipwright CLI
// for interaction with shipwright builds
func Command(p *params.Params) *cobra.Command {
buildResource = resource.NewShpResource(
p,
buildv1alpha1.SchemeGroupVersion,
"Build",
"builds",
)

func Command(p *params.Params, ioStreams *genericclioptions.IOStreams) *cobra.Command {
command := &cobra.Command{
Use: "build",
Aliases: []string{"bd"},
Expand All @@ -36,17 +21,12 @@ func Command(p *params.Params) *cobra.Command {
},
}

streams := genericclioptions.IOStreams{
In: os.Stdin,
Out: os.Stdout,
ErrOut: os.Stderr,
}

// TODO: add support for `update` and `get` commands
command.AddCommand(
runner.NewRunner(p, streams, createCmd()).Cmd(),
runner.NewRunner(p, streams, listCmd()).Cmd(),
runner.NewRunner(p, streams, deleteCmd()).Cmd(),
runner.NewRunner(p, ioStreams, createCmd()).Cmd(),
runner.NewRunner(p, ioStreams, listCmd()).Cmd(),
runner.NewRunner(p, ioStreams, deleteCmd()).Cmd(),
runner.NewRunner(p, ioStreams, runCmd()).Cmd(),
)
return command
}
29 changes: 18 additions & 11 deletions pkg/shp/cmd/build/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ package build

import (
"errors"
"fmt"

buildv1alpha1 "github.com/shipwright-io/build/pkg/apis/build/v1alpha1"
"github.com/spf13/cobra"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"

"github.com/shipwright-io/cli/pkg/shp/cmd/runner"
"github.com/shipwright-io/cli/pkg/shp/params"
"github.com/shipwright-io/cli/pkg/shp/resource"
)

// CreateCommand contains data input from user
Expand All @@ -28,12 +31,17 @@ type CreateCommand struct {
func createCmd() runner.SubCommand {
createCommand := &CreateCommand{
cmd: &cobra.Command{
Use: "create [flags] name strategy url",
Use: "create <name> [flags]",
Short: "Create Build",
Args: cobra.ExactArgs(1),
},
}

createCommand.cmd.Flags().StringVarP(&createCommand.image, "output-image", "i", "", "Output image created by build")
createCommand.cmd.Flags().StringVarP(&createCommand.strategy, "strategy", "", "buildah", "Build strategy")
createCommand.cmd.Flags().StringVarP(&createCommand.image, "source-url", "u", "", "Source URL to run the build from")

createCommand.cmd.MarkFlagRequired("source-url")

return createCommand
}
Expand All @@ -45,14 +53,7 @@ func (c *CreateCommand) Cmd() *cobra.Command {

// Complete fills internal subcommand structure for future work with user input
func (c *CreateCommand) Complete(params *params.Params, args []string) error {

if len(args) < 3 {
return errors.New("not enough arguments for Build create")
}

c.name = args[0]
c.strategy = args[1]
c.url = args[2]

return nil
}
Expand Down Expand Up @@ -92,8 +93,14 @@ func (c *CreateCommand) Validate() error {
}

// Run contains main logic of the create subcommand
func (c *CreateCommand) Run(params *params.Params) error {
c.initializeBuild()
func (sc *CreateCommand) Run(params *params.Params, io *genericclioptions.IOStreams) error {
sc.initializeBuild()
buildResource := resource.GetBuildResource(params)

return buildResource.Create(c.name, c.build)
if err := buildResource.Create(sc.cmd.Context(), sc.name, sc.build); err != nil {
return err
}

fmt.Fprintf(io.Out, "Build created %q\n", sc.name)
return nil
}
45 changes: 34 additions & 11 deletions pkg/shp/cmd/build/delete.go
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
package build

import (
"errors"
"fmt"

buildv1alpha1 "github.com/shipwright-io/build/pkg/apis/build/v1alpha1"
"github.com/spf13/cobra"

v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"

"github.com/shipwright-io/cli/pkg/shp/cmd/runner"
"github.com/shipwright-io/cli/pkg/shp/params"
"github.com/shipwright-io/cli/pkg/shp/resource"
)

// DeleteCommand contains data provided by user to the delete subcommand
type DeleteCommand struct {
name string

cmd *cobra.Command
cmd *cobra.Command
deleteRuns bool
}

func deleteCmd() runner.SubCommand {
deleteCommand := &DeleteCommand{
cmd: &cobra.Command{
Use: "delete [flags] name",
Use: "delete <name> [flags]",
Short: "Delete Build",
Args: cobra.ExactArgs(1),
},
}

deleteCommand.cmd.Flags().BoolVarP(&deleteCommand.deleteRuns, "delete-runs", "r", false, "Also delete all of the buildruns")

return deleteCommand
}

Expand All @@ -35,10 +43,6 @@ func (c *DeleteCommand) Cmd() *cobra.Command {

// Complete fills DeleteSubCommand structure with data obtained from cobra command
func (c *DeleteCommand) Complete(params *params.Params, args []string) error {
if len(args) == 0 {
return errors.New("missing 'name' argument")
}

c.name = args[0]

return nil
Expand All @@ -50,12 +54,31 @@ func (c *DeleteCommand) Validate() error {
}

// Run contains main logic of delete subcommand
func (c *DeleteCommand) Run(params *params.Params) error {
var b buildv1alpha1.Build
func (c *DeleteCommand) Run(params *params.Params, io *genericclioptions.IOStreams) error {
br := resource.GetBuildResource(params)

if err := buildResource.Get(c.name, &b); err != nil {
if err := br.Delete(c.cmd.Context(), c.name); err != nil {
return err
}

return buildResource.Delete(c.name)
if c.deleteRuns {
brr := resource.GetBuildRunResource(params)

var brList buildv1alpha1.BuildRunList
if err := brr.ListWithOptions(c.cmd.Context(), &brList, v1.ListOptions{
LabelSelector: fmt.Sprintf("%v/name=%v", buildv1alpha1.BuildDomain, c.name),
}); err != nil {
return err
}

for _, buildrun := range brList.Items {
if err := brr.Delete(c.cmd.Context(), buildrun.Name); err != nil {
fmt.Fprintf(io.ErrOut, "Error deleting BuildRun %q: %v\n", buildrun.Name, err)
}
}
}

fmt.Fprintf(io.Out, "Build deleted %q\n", c.name)

return nil
}
2 changes: 2 additions & 0 deletions pkg/shp/cmd/build/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// build contains types and functions for build cobra sub-command
package build
12 changes: 8 additions & 4 deletions pkg/shp/cmd/build/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ package build

import (
"fmt"
"os"
"text/tabwriter"

buildv1alpha1 "github.com/shipwright-io/build/pkg/apis/build/v1alpha1"
"github.com/spf13/cobra"

"k8s.io/cli-runtime/pkg/genericclioptions"

"github.com/shipwright-io/cli/pkg/shp/cmd/runner"
"github.com/shipwright-io/cli/pkg/shp/params"
"github.com/shipwright-io/cli/pkg/shp/resource"
)

// ListCommand struct contains user input to the List subcommand of Build
Expand Down Expand Up @@ -48,17 +50,19 @@ func (c *ListCommand) Validate() error {
}

// Run contains main logic of List subcommand of Build
func (c *ListCommand) Run(params *params.Params) error {
func (c *ListCommand) Run(params *params.Params, io *genericclioptions.IOStreams) error {
// TODO: Support multiple output formats here, not only tabwriter
// find out more in kubectl libraries and use them

// Initialize tabwriter for command output
writer := tabwriter.NewWriter(os.Stdout, 0, 8, 2, '\t', 0)
writer := tabwriter.NewWriter(io.Out, 0, 8, 2, '\t', 0)
columnNames := "NAME\tOUTPUT\tSTATUS"
columnTemplate := "%s\t%s\t%s\n"

var buildList buildv1alpha1.BuildList
if err := buildResource.List(&buildList); err != nil {
br := resource.GetBuildResource(params)

if err := br.List(c.cmd.Context(), &buildList); err != nil {
return err
}

Expand Down
76 changes: 76 additions & 0 deletions pkg/shp/cmd/build/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package build

import (
"errors"
"fmt"

buildv1alpha1 "github.com/shipwright-io/build/pkg/apis/build/v1alpha1"
"github.com/spf13/cobra"

"k8s.io/cli-runtime/pkg/genericclioptions"

"github.com/shipwright-io/cli/pkg/shp/cmd/buildrun"
"github.com/shipwright-io/cli/pkg/shp/cmd/runner"
"github.com/shipwright-io/cli/pkg/shp/params"
"github.com/shipwright-io/cli/pkg/shp/resource"
)

// RunCommand contains data input from user for run sub-command
type RunCommand struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great do have doc-comments, and perhaps a initial doc.go 🙏🏼

cmd *cobra.Command

buildName string
}

// Cmd returns cobra command object
func (c *RunCommand) Cmd() *cobra.Command {
return c.cmd
}

func runCmd() runner.SubCommand {
runCommand := &RunCommand{
cmd: &cobra.Command{
Use: "run <name>",
Short: "Start a build specified by 'name'",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can add Args: cobra.MinimumNArgs(1), instead of having to check len(args) < 1 later on.

Args: cobra.ExactArgs(1),
},
}

return runCommand
}

// Complete fills in data provided by user
func (c *RunCommand) Complete(params *params.Params, args []string) error {
if len(args) < 1 {
return errors.New("'name' argument is empty")
}

c.buildName = args[0]

return nil
}

// Validate validates data input by user
func (c *RunCommand) Validate() error {
return nil
}

// Run executes run sub-command logic
func (c *RunCommand) Run(params *params.Params, ioStreams *genericclioptions.IOStreams) error {
br := resource.GetBuildResource(params)
brr := resource.GetBuildRunResource(params)

var build buildv1alpha1.Build
if err := br.Get(c.cmd.Context(), c.buildName, &build); err != nil {
return err
}

buildRun := buildrun.NewBuildRun(&build, build.Name)

if err := brr.Create(c.cmd.Context(), "", buildRun); err != nil {
return err
}

fmt.Fprintf(ioStreams.Out, "BuildRun created %q\n", buildRun.Name)
return nil
}
Loading