Skip to content

Commit

Permalink
BUILD-206: added BuildRun, resource accepts context
Browse files Browse the repository at this point in the history
New Subcommands for working with BuildRun
Created via 'build run'
Can be deleted, listed and view logs
Resource objects now support context passed from cobra commands
SubCommand Run method now accepts IoStreams for information output
Other minor changes, including README
  • Loading branch information
Alice Rum committed Apr 7, 2021
1 parent 47e2250 commit 863e038
Show file tree
Hide file tree
Showing 29 changed files with 607 additions and 98 deletions.
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)
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 {
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'",
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

0 comments on commit 863e038

Please sign in to comment.