Skip to content

Commit

Permalink
Build and BuildRun "create" subcommands.
Browse files Browse the repository at this point in the history
Additionally making sure "build run" also uses the same machinery.

Co-authored-by: Adam Kaplan <adam.kaplan@redhat.com>
  • Loading branch information
otaviof and adambkaplan committed Jun 8, 2021
1 parent d7e9771 commit 0548273
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 135 deletions.
118 changes: 50 additions & 68 deletions pkg/shp/cmd/build/create.go
Original file line number Diff line number Diff line change
@@ -1,106 +1,88 @@
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/flags"
"github.com/shipwright-io/cli/pkg/shp/params"
"github.com/shipwright-io/cli/pkg/shp/resource"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
)

// CreateCommand contains data input from user
type CreateCommand struct {
url string
strategy string
name string

image string

build *buildv1alpha1.Build
cmd *cobra.Command // cobra command instance

cmd *cobra.Command
name string // build resource's name
buildSpec *buildv1alpha1.BuildSpec // stores command-line flags
}

func createCmd() runner.SubCommand {
createCommand := &CreateCommand{
cmd: &cobra.Command{
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")
const buildCreateLongDesc = `
Creates a new Build instance using the first argument as its name. For example:
return createCommand
}
$ shp build create my-app --source-url="..." --output-image="..."
`

// Cmd returns cobra Command object of the create subcommand
// Cmd returns cobra.Command object of the create subcommand.
func (c *CreateCommand) Cmd() *cobra.Command {
return c.cmd
}

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

switch len(args) {
case 1:
c.name = args[0]
default:
return fmt.Errorf("one argument is expected")
}
return nil
}

func (c *CreateCommand) initializeBuild() {
strategyKind := buildv1alpha1.ClusterBuildStrategyKind

c.build = &buildv1alpha1.Build{
ObjectMeta: metav1.ObjectMeta{
Name: c.name,
},
Spec: buildv1alpha1.BuildSpec{
Strategy: &buildv1alpha1.Strategy{
Name: c.strategy,
Kind: &strategyKind,
},
Source: buildv1alpha1.Source{
URL: c.url,
},
},
}

if c.image != "" {
c.build.Spec.Output = buildv1alpha1.Image{
Image: c.image,
}
// Validate is used for user input validation of flags and other data.
func (c *CreateCommand) Validate() error {
if c.name == "" {
return fmt.Errorf("name must be provided")
}
return nil
}

// Validate is used for user input validation of flags and other data
func (c *CreateCommand) Validate() error {
if c.strategy != "buildah" {
return errors.New("incorrect strategy, must be 'buildah'")
}
// Run executes the creation of a new Build instance using flags to fill up the details.
func (c *CreateCommand) Run(params *params.Params, io *genericclioptions.IOStreams) error {
b := &buildv1alpha1.Build{Spec: *c.buildSpec}
flags.SanitizeBuildSpec(&b.Spec)

buildResource := resource.GetBuildResource(params)
if err := buildResource.Create(c.cmd.Context(), c.name, b); err != nil {
return err
}
fmt.Fprintf(io.Out, "Created build %q\n", c.name)
return nil
}

// Run contains main logic of the create subcommand
func (sc *CreateCommand) Run(params *params.Params, io *genericclioptions.IOStreams) error {
sc.initializeBuild()
buildResource := resource.GetBuildResource(params)
// createCmd instantiate the "build create" subcommand.
func createCmd() runner.SubCommand {
cmd := &cobra.Command{
Use: "create <name> [flags]",
Short: "Create Build",
Long: buildCreateLongDesc,
}

if err := buildResource.Create(sc.cmd.Context(), sc.name, sc.build); err != nil {
return err
// instantiating command-line flags and the build-spec structure which receives the informed flag
// values, also marking certain flags as mandatory
buildSpecFlags := flags.BuildSpecFromFlags(cmd.Flags())
if err := cmd.MarkFlagRequired(flags.SourceURLFlag); err != nil {
panic(err)
}
if err := cmd.MarkFlagRequired(flags.OutputImageFlag); err != nil {
panic(err)
}

fmt.Fprintf(io.Out, "Build created %q\n", sc.name)
return nil
return &CreateCommand{
cmd: cmd,
buildSpec: buildSpecFlags,
}
}
100 changes: 56 additions & 44 deletions pkg/shp/cmd/build/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,72 +5,84 @@ import (
"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/flags"
"github.com/shipwright-io/cli/pkg/shp/params"
"github.com/shipwright-io/cli/pkg/shp/resource"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
)

// RunCommand contains data input from user for run sub-command
// RunCommand represents the `build run` sub-command, which creates a unique BuildRun instance to run
// the build process, informed via arguments.
type RunCommand struct {
cmd *cobra.Command
cmd *cobra.Command // cobra command instance

buildName string
buildName string // build name
buildRunSpec *buildv1alpha1.BuildRunSpec // stores command-line flags
}

// Cmd returns cobra command object
func (c *RunCommand) Cmd() *cobra.Command {
return c.cmd
}
const buildRunLongDesc = `
Creates a unique BuildRun instance for the given Build, which starts the build
process orchestrated by the Shipwright build controller. For example:
func runCmd() runner.SubCommand {
runCommand := &RunCommand{
cmd: &cobra.Command{
Use: "run <name>",
Short: "Start a build specified by 'name'",
Args: cobra.ExactArgs(1),
},
}
$ shp build run my-app
`

return runCommand
// Cmd returns cobra.Command object of the create sub-command.
func (r *RunCommand) Cmd() *cobra.Command {
return r.cmd
}

// 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")
// Complete picks the build resource name from arguments, or error when not informed.
func (r *RunCommand) Complete(params *params.Params, args []string) error {
switch len(args) {
case 1:
r.buildName = args[0]
default:
return errors.New("Build name is not informed")
}

c.buildName = args[0]

return nil
// overwriting build-ref name to use what's on arguments
return r.Cmd().Flags().Set(flags.BuildrefNameFlag, r.buildName)
}

// Validate validates data input by user
func (c *RunCommand) Validate() error {
// Validate the user must inform the build resource name.
func (r *RunCommand) Validate() error {
if r.buildName == "" {
return fmt.Errorf("name is not informed")
}
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
// Run creates a BuildRun resource based on Build's name informed on arguments.
func (r *RunCommand) Run(params *params.Params, ioStreams *genericclioptions.IOStreams) error {
// resource using GenerateName, which will provice a unique instance
br := &buildv1alpha1.BuildRun{
ObjectMeta: metav1.ObjectMeta{
GenerateName: fmt.Sprintf("%s-", r.buildName),
},
Spec: *r.buildRunSpec,
}
flags.SanitizeBuildRunSpec(&br.Spec)

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

if err := brr.Create(c.cmd.Context(), "", buildRun); err != nil {
buildRunResource := resource.GetBuildRunResource(params)
if err := buildRunResource.Create(r.cmd.Context(), "", br); err != nil {
return err
}

fmt.Fprintf(ioStreams.Out, "BuildRun created %q\n", buildRun.Name)
fmt.Fprintf(ioStreams.Out, "BuildRun created %q for build %q\n", br.GetName(), r.buildName)
return nil
}

// runCmd instantiate the "build run" sub-command using common BuildRun flags.
func runCmd() runner.SubCommand {
cmd := &cobra.Command{
Use: "run <name>",
Short: "Start a build specified by 'name'",
Long: buildRunLongDesc,
}
return &RunCommand{
cmd: cmd,
buildRunSpec: flags.BuildRunSpecFromFlags(cmd.Flags()),
}
}
3 changes: 2 additions & 1 deletion pkg/shp/cmd/buildrun/buildrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ func Command(p *params.Params, ioStreams *genericclioptions.IOStreams) *cobra.Co
command.AddCommand(
runner.NewRunner(p, ioStreams, listCmd()).Cmd(),
runner.NewRunner(p, ioStreams, logsCmd()).Cmd(),
runner.NewRunner(p, ioStreams, deleteCmd()).Cmd(),
runner.NewRunner(p, ioStreams, logsCmd()).Cmd(),
runner.NewRunner(p, ioStreams, createCmd()).Cmd(),
)
return command
}
22 changes: 0 additions & 22 deletions pkg/shp/cmd/buildrun/common.go

This file was deleted.

Loading

0 comments on commit 0548273

Please sign in to comment.