Skip to content

Commit

Permalink
PodLogsFollower and Params Refactoring
Browse files Browse the repository at this point in the history
- Refactoring the former `PodFollower` to become `PodLogsFollower`,
  focused on the pod lifecycle, also able to both stream live logs or
  read all logs from a existing pod
- Refactoring `BuildRun` inspections into a single component
- Introducing `FakeParams` to simplify unit-testing and refactoring
  `Params` to avoid cycle dependencies
  • Loading branch information
otaviof committed Mar 31, 2022
1 parent 537e493 commit 74293a1
Show file tree
Hide file tree
Showing 28 changed files with 1,016 additions and 1,060 deletions.
8 changes: 4 additions & 4 deletions pkg/shp/cmd/build/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,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, io *genericclioptions.IOStreams, args []string) error {
func (c *CreateCommand) Complete(p params.Interface, io *genericclioptions.IOStreams, args []string) error {
switch len(args) {
case 1:
c.name = args[0]
Expand All @@ -53,7 +53,7 @@ func (c *CreateCommand) Validate() error {
}

// 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 {
func (c *CreateCommand) Run(p params.Interface, io *genericclioptions.IOStreams) error {
b := &buildv1alpha1.Build{
ObjectMeta: metav1.ObjectMeta{
Name: c.name,
Expand All @@ -63,11 +63,11 @@ func (c *CreateCommand) Run(params *params.Params, io *genericclioptions.IOStrea

flags.SanitizeBuildSpec(&b.Spec)

clientset, err := params.ShipwrightClientSet()
clientset, err := p.ShipwrightClientSet()
if err != nil {
return err
}
if _, err := clientset.ShipwrightV1alpha1().Builds(params.Namespace()).Create(c.cmd.Context(), b, metav1.CreateOptions{}); err != nil {
if _, err := clientset.ShipwrightV1alpha1().Builds(p.Namespace()).Create(c.cmd.Context(), b, metav1.CreateOptions{}); err != nil {
return err
}
fmt.Fprintf(io.Out, "Created build %q\n", c.name)
Expand Down
18 changes: 11 additions & 7 deletions pkg/shp/cmd/build/delete.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
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"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"

"github.com/shipwright-io/cli/pkg/shp/cmd/runner"
Expand Down Expand Up @@ -41,7 +42,10 @@ func (c *DeleteCommand) Cmd() *cobra.Command {
}

// Complete fills DeleteSubCommand structure with data obtained from cobra command
func (c *DeleteCommand) Complete(params *params.Params, io *genericclioptions.IOStreams, args []string) error {
func (c *DeleteCommand) Complete(p params.Interface, io *genericclioptions.IOStreams, args []string) error {
if len(args) != 1 {
return errors.New("build name is not informed")
}
c.name = args[0]

return nil
Expand All @@ -53,25 +57,25 @@ func (c *DeleteCommand) Validate() error {
}

// Run contains main logic of delete subcommand
func (c *DeleteCommand) Run(params *params.Params, io *genericclioptions.IOStreams) error {
clientset, err := params.ShipwrightClientSet()
func (c *DeleteCommand) Run(p params.Interface, io *genericclioptions.IOStreams) error {
clientset, err := p.ShipwrightClientSet()
if err != nil {
return err
}
if err := clientset.ShipwrightV1alpha1().Builds(params.Namespace()).Delete(c.Cmd().Context(), c.name, v1.DeleteOptions{}); err != nil {
if err := clientset.ShipwrightV1alpha1().Builds(p.Namespace()).Delete(c.Cmd().Context(), c.name, metav1.DeleteOptions{}); err != nil {
return err
}

if c.deleteRuns {
var brList *buildv1alpha1.BuildRunList
if brList, err = clientset.ShipwrightV1alpha1().BuildRuns(params.Namespace()).List(c.cmd.Context(), v1.ListOptions{
if brList, err = clientset.ShipwrightV1alpha1().BuildRuns(p.Namespace()).List(c.cmd.Context(), metav1.ListOptions{
LabelSelector: fmt.Sprintf("%v/name=%v", buildv1alpha1.BuildDomain, c.name),
}); err != nil {
return err
}

for _, buildrun := range brList.Items {
if err := clientset.ShipwrightV1alpha1().BuildRuns(params.Namespace()).Delete(c.cmd.Context(), buildrun.Name, v1.DeleteOptions{}); err != nil {
if err := clientset.ShipwrightV1alpha1().BuildRuns(p.Namespace()).Delete(c.cmd.Context(), buildrun.Name, metav1.DeleteOptions{}); err != nil {
fmt.Fprintf(io.ErrOut, "Error deleting BuildRun %q: %v\n", buildrun.Name, err)
}
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/shp/cmd/build/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (c *ListCommand) Cmd() *cobra.Command {
}

// Complete fills object with user input data
func (c *ListCommand) Complete(params *params.Params, io *genericclioptions.IOStreams, args []string) error {
func (c *ListCommand) Complete(_ params.Interface, _ *genericclioptions.IOStreams, _ []string) error {
return nil
}

Expand All @@ -49,7 +49,7 @@ func (c *ListCommand) Validate() error {
}

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

Expand All @@ -59,11 +59,11 @@ func (c *ListCommand) Run(params *params.Params, io *genericclioptions.IOStreams
columnTemplate := "%s\t%s\t%s\n"

var buildList *buildv1alpha1.BuildList
clientset, err := params.ShipwrightClientSet()
clientset, err := p.ShipwrightClientSet()
if err != nil {
return err
}
if buildList, err = clientset.ShipwrightV1alpha1().Builds(params.Namespace()).List(c.cmd.Context(), metav1.ListOptions{}); err != nil {
if buildList, err = clientset.ShipwrightV1alpha1().Builds(p.Namespace()).List(c.cmd.Context(), metav1.ListOptions{}); err != nil {
return err
}

Expand Down
58 changes: 35 additions & 23 deletions pkg/shp/cmd/build/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (
"fmt"

buildv1alpha1 "github.com/shipwright-io/build/pkg/apis/build/v1alpha1"
"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/follower"
"github.com/shipwright-io/cli/pkg/shp/params"
"github.com/shipwright-io/cli/pkg/shp/reactor"

"github.com/spf13/cobra"

Expand All @@ -22,11 +24,12 @@ import (
type RunCommand struct {
cmd *cobra.Command // cobra command instance

buildName string
namespace string
buildName string // build name, collected during complete

buildRunSpec *buildv1alpha1.BuildRunSpec // stores command-line flags
follow bool // flag to tail pod logs
follower *follower.Follower

podLogsFollower *follower.PodLogsFollower
}

const buildRunLongDesc = `
Expand All @@ -42,15 +45,15 @@ func (r *RunCommand) Cmd() *cobra.Command {
}

// Complete picks the build resource name from arguments, and instantiate additional components.
func (r *RunCommand) Complete(params *params.Params, ioStreams *genericclioptions.IOStreams, args []string) error {
switch len(args) {
case 1:
r.buildName = args[0]
default:
func (r *RunCommand) Complete(
p params.Interface,
ioStreams *genericclioptions.IOStreams,
args []string,
) error {
if len(args) != 1 {
return errors.New("build name is not informed")
}

r.namespace = params.Namespace()
r.buildName = args[0]

// overwriting build-ref name to use what's on arguments
return r.Cmd().Flags().Set(flags.BuildrefNameFlag, r.buildName)
Expand All @@ -65,7 +68,7 @@ func (r *RunCommand) Validate() error {
}

// Run creates a BuildRun resource based on Build's name informed on arguments.
func (r *RunCommand) Run(params *params.Params, ioStreams *genericclioptions.IOStreams) error {
func (r *RunCommand) Run(p params.Interface, ioStreams *genericclioptions.IOStreams) error {
// resource using GenerateName, which will provide a unique instance
br := &buildv1alpha1.BuildRun{
ObjectMeta: metav1.ObjectMeta{
Expand All @@ -76,25 +79,30 @@ func (r *RunCommand) Run(params *params.Params, ioStreams *genericclioptions.IOS
flags.SanitizeBuildRunSpec(&br.Spec)

ctx := r.cmd.Context()
clientset, err := params.ShipwrightClientSet()
clientset, err := p.ShipwrightClientSet()
if err != nil {
return err
}
br, err = clientset.ShipwrightV1alpha1().BuildRuns(r.namespace).Create(ctx, br, metav1.CreateOptions{})
br, err = clientset.ShipwrightV1alpha1().
BuildRuns(p.Namespace()).
Create(ctx, br, metav1.CreateOptions{})
if err != nil {
return err
}

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

// during unit-testing the follower instance will be injected directly, which makes possible to
// simulate the pod events without creating a race condition
if r.follower == nil {
buildRun := types.NamespacedName{Namespace: r.namespace, Name: br.GetName()}
r.follower, err = params.NewFollower(ctx, buildRun, ioStreams)
if r.podLogsFollower == nil {
pw, err := reactor.NewPodWatcherFromParams(r.cmd.Context(), p)
if err != nil {
return err
}
r.podLogsFollower, err = follower.NewPodLogsFollowerFromParams(ctx, p, pw, ioStreams)
if err != nil {
return err
}
Expand All @@ -103,12 +111,16 @@ func (r *RunCommand) Run(params *params.Params, ioStreams *genericclioptions.IOS
// instantiating a pod watcher with a specific label-selector to find the indented pod where the
// actual build started by this subcommand is being executed, including the randomized buildrun
// name
listOpts := metav1.ListOptions{LabelSelector: fmt.Sprintf(
"build.shipwright.io/name=%s,buildrun.shipwright.io/name=%s",
r.buildName,
br.GetName(),
)}
_, err = r.follower.Start(listOpts)
buildNameLabel := fmt.Sprintf("%s=%s", buildv1alpha1.LabelBuild, r.buildName)
buildRunNameLabel := fmt.Sprintf("%s=%s", buildv1alpha1.LabelBuildRun, br.GetName())
listOpts := metav1.ListOptions{
LabelSelector: fmt.Sprintf("%s,%s", buildNameLabel, buildRunNameLabel),
}

if _, err = r.podLogsFollower.Start(listOpts); err != nil {
buildRunName := types.NamespacedName{Namespace: br.GetNamespace(), Name: br.GetName()}
_ = buildrun.InspectBuildRun(ctx, clientset, buildRunName, ioStreams)
}
return err
}

Expand Down
Loading

0 comments on commit 74293a1

Please sign in to comment.