github.com/jenspinney/cli@v6.42.1-0.20190207184520-7450c600020e+incompatible/command/v6/update_buildpack_command.go (about)

     1  package v6
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"time"
     7  
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccversion"
     9  
    10  	"code.cloudfoundry.org/cli/actor/sharedaction"
    11  	"code.cloudfoundry.org/cli/actor/v2action"
    12  	"code.cloudfoundry.org/cli/command"
    13  	"code.cloudfoundry.org/cli/command/flag"
    14  	"code.cloudfoundry.org/cli/command/translatableerror"
    15  	"code.cloudfoundry.org/cli/command/v6/shared"
    16  	"code.cloudfoundry.org/cli/types"
    17  	"code.cloudfoundry.org/cli/util/download"
    18  )
    19  
    20  //go:generate counterfeiter . UpdateBuildpackActor
    21  
    22  type UpdateBuildpackActor interface {
    23  	CloudControllerAPIVersion() string
    24  	UpdateBuildpackByNameAndStack(name, currentStack string, position types.NullInt, locked types.NullBool, enabled types.NullBool, newStack string) (string, v2action.Warnings, error)
    25  	PrepareBuildpackBits(inputPath string, tmpDirPath string, downloader v2action.Downloader) (string, error)
    26  	UploadBuildpack(GUID string, path string, progBar v2action.SimpleProgressBar) (v2action.Warnings, error)
    27  }
    28  
    29  type UpdateBuildpackCommand struct {
    30  	RequiredArgs flag.BuildpackName               `positional-args:"yes"`
    31  	NewStack     string                           `long:"assign-stack" description:"Assign a stack to a buildpack that does not have a stack association"`
    32  	Disable      bool                             `long:"disable" description:"Disable the buildpack from being used for staging"`
    33  	Enable       bool                             `long:"enable" description:"Enable the buildpack to be used for staging"`
    34  	Order        types.NullInt                    `short:"i" description:"The order in which the buildpacks are checked during buildpack auto-detection"`
    35  	Lock         bool                             `long:"lock" description:"Lock the buildpack to prevent updates"`
    36  	Path         flag.PathWithExistenceCheckOrURL `short:"p" description:"Path to directory or zip file"`
    37  	Unlock       bool                             `long:"unlock" description:"Unlock the buildpack to enable updates"`
    38  	CurrentStack string                           `short:"s" description:"Specify stack to disambiguate buildpacks with the same name"`
    39  	usage        interface{}                      `usage:"CF_NAME update-buildpack BUILDPACK [-p PATH | -s STACK | --assign-stack NEW_STACK] [-i POSITION] [--enable|--disable] [--lock|--unlock]\n\nTIP:\nPath should be a zip file, a url to a zip file, or a local directory. Position is a positive integer, sets priority, and is sorted from lowest to highest.\n\nUse '--assign-stack' with caution. Associating a buildpack with a stack that it does not support may result in undefined behavior. Additionally, changing this association once made may require a local copy of the buildpack.\n\n"`
    40  
    41  	relatedCommands interface{} `related_commands:"buildpacks, rename-buildpack, create-buildpack, delete-buildpack"`
    42  
    43  	UI          command.UI
    44  	SharedActor command.SharedActor
    45  	Actor       UpdateBuildpackActor
    46  	Config      command.Config
    47  	ProgressBar v2action.SimpleProgressBar
    48  }
    49  
    50  func (cmd *UpdateBuildpackCommand) Setup(config command.Config, ui command.UI) error {
    51  	cmd.UI = ui
    52  	cmd.Config = config
    53  
    54  	cmd.SharedActor = sharedaction.NewActor(config)
    55  	ccClient, uaaClient, err := shared.NewClients(config, ui, true)
    56  	if err != nil {
    57  		return err
    58  	}
    59  	cmd.Actor = v2action.NewActor(ccClient, uaaClient, config)
    60  	cmd.ProgressBar = v2action.NewProgressBar()
    61  
    62  	return nil
    63  }
    64  
    65  func (cmd UpdateBuildpackCommand) Execute(args []string) error {
    66  	err := cmd.validateFlagCombinations()
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	err = cmd.SharedActor.CheckTarget(false, false)
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	err = cmd.minAPIVersionCheck()
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	user, err := cmd.Config.CurrentUser()
    82  	if err != nil {
    83  		return err
    84  	}
    85  
    86  	cmd.printInitialText(user.Name)
    87  
    88  	var buildpackBitsPath string
    89  
    90  	if cmd.Path != "" {
    91  		var (
    92  			tmpDirPath string
    93  		)
    94  		downloader := download.NewDownloader(time.Second * 30)
    95  		tmpDirPath, err = ioutil.TempDir("", "buildpack-dir-")
    96  		if err != nil {
    97  			return err
    98  		}
    99  		defer os.RemoveAll(tmpDirPath)
   100  
   101  		buildpackBitsPath, err = cmd.Actor.PrepareBuildpackBits(string(cmd.Path), tmpDirPath, downloader)
   102  		if err != nil {
   103  			return err
   104  		}
   105  	}
   106  
   107  	enabled := types.NullBool{
   108  		IsSet: cmd.Enable || cmd.Disable,
   109  		Value: cmd.Enable,
   110  	}
   111  
   112  	locked := types.NullBool{
   113  		IsSet: cmd.Lock || cmd.Unlock,
   114  		Value: cmd.Lock,
   115  	}
   116  
   117  	buildpackGUID, warnings, err := cmd.Actor.UpdateBuildpackByNameAndStack(cmd.RequiredArgs.Buildpack, cmd.CurrentStack, cmd.Order, locked, enabled, cmd.NewStack)
   118  
   119  	cmd.UI.DisplayWarnings(warnings)
   120  	if err != nil {
   121  		return err
   122  	}
   123  
   124  	cmd.UI.DisplayOK()
   125  
   126  	if buildpackBitsPath != "" {
   127  		cmd.UI.DisplayTextWithFlavor("Uploading buildpack {{.Buildpack}} as {{.Username}}...", map[string]interface{}{
   128  			"Buildpack": cmd.RequiredArgs.Buildpack,
   129  			"Username":  user.Name,
   130  		})
   131  
   132  		warnings, err = cmd.Actor.UploadBuildpack(buildpackGUID, buildpackBitsPath, cmd.ProgressBar)
   133  		cmd.UI.DisplayWarnings(warnings)
   134  		if err != nil {
   135  			return err
   136  		}
   137  
   138  		cmd.UI.DisplayOK()
   139  
   140  	}
   141  	return err
   142  }
   143  
   144  func (cmd UpdateBuildpackCommand) minAPIVersionCheck() error {
   145  	if cmd.CurrentStack != "" {
   146  		return command.MinimumCCAPIVersionCheck(
   147  			cmd.Actor.CloudControllerAPIVersion(),
   148  			ccversion.MinVersionBuildpackStackAssociationV2,
   149  			"Option '-s'",
   150  		)
   151  	}
   152  
   153  	if cmd.NewStack != "" {
   154  		return command.MinimumCCAPIVersionCheck(
   155  			cmd.Actor.CloudControllerAPIVersion(),
   156  			ccversion.MinVersionBuildpackStackAssociationV2,
   157  			"Option '--assign-stack'",
   158  		)
   159  	}
   160  	return nil
   161  }
   162  
   163  func (cmd UpdateBuildpackCommand) printInitialText(userName string) {
   164  	if cmd.NewStack != "" {
   165  		cmd.UI.DisplayTextWithFlavor("Assigning stack {{.Stack}} to {{.Buildpack}} as {{.CurrentUser}}...", map[string]interface{}{
   166  			"Buildpack":   cmd.RequiredArgs.Buildpack,
   167  			"CurrentUser": userName,
   168  			"Stack":       cmd.NewStack,
   169  		})
   170  		if cmd.Order.IsSet || cmd.Lock || cmd.Unlock || cmd.Enable || cmd.Disable {
   171  			cmd.UI.DisplayTextWithFlavor("Updating buildpack {{.Buildpack}} with stack {{.Stack}} as {{.CurrentUser}}...", map[string]interface{}{
   172  				"Buildpack":   cmd.RequiredArgs.Buildpack,
   173  				"CurrentUser": userName,
   174  				"Stack":       cmd.NewStack,
   175  			})
   176  		}
   177  	} else if cmd.CurrentStack == "" {
   178  		cmd.UI.DisplayTextWithFlavor("Updating buildpack {{.Buildpack}} as {{.CurrentUser}}...", map[string]interface{}{
   179  			"Buildpack":   cmd.RequiredArgs.Buildpack,
   180  			"CurrentUser": userName,
   181  		})
   182  	} else {
   183  		cmd.UI.DisplayTextWithFlavor("Updating buildpack {{.Buildpack}} with stack {{.Stack}} as {{.CurrentUser}}...", map[string]interface{}{
   184  			"Buildpack":   cmd.RequiredArgs.Buildpack,
   185  			"CurrentUser": userName,
   186  			"Stack":       cmd.CurrentStack,
   187  		})
   188  	}
   189  }
   190  
   191  func (cmd UpdateBuildpackCommand) validateFlagCombinations() error {
   192  	if cmd.Lock && cmd.Unlock {
   193  		return translatableerror.ArgumentCombinationError{
   194  			Args: []string{"--lock", "--unlock"},
   195  		}
   196  	}
   197  
   198  	if cmd.Lock && len(cmd.Path) > 0 {
   199  		return translatableerror.ArgumentCombinationError{
   200  			Args: []string{"-p", "--lock"},
   201  		}
   202  	}
   203  
   204  	if len(cmd.Path) > 0 && cmd.Unlock {
   205  		return translatableerror.ArgumentCombinationError{
   206  			Args: []string{"-p", "--unlock"},
   207  		}
   208  	}
   209  
   210  	if len(cmd.Path) > 0 && len(cmd.NewStack) > 0 {
   211  		return translatableerror.ArgumentCombinationError{
   212  			Args: []string{"-p", "--assign-stack"},
   213  		}
   214  	}
   215  
   216  	if len(cmd.CurrentStack) > 0 && len(cmd.NewStack) > 0 {
   217  		return translatableerror.ArgumentCombinationError{
   218  			Args: []string{"-s", "--assign-stack"},
   219  		}
   220  	}
   221  
   222  	if cmd.Enable && cmd.Disable {
   223  		return translatableerror.ArgumentCombinationError{
   224  			Args: []string{"--enable", "--disable"},
   225  		}
   226  	}
   227  
   228  	return nil
   229  }