github.com/swisscom/cloudfoundry-cli@v7.1.0+incompatible/cf/commands/buildpack/update_buildpack.go (about)

     1  package buildpack
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  
     8  	"code.cloudfoundry.org/cli/cf/api"
     9  	"code.cloudfoundry.org/cli/cf/commandregistry"
    10  	"code.cloudfoundry.org/cli/cf/flags"
    11  	. "code.cloudfoundry.org/cli/cf/i18n"
    12  	"code.cloudfoundry.org/cli/cf/requirements"
    13  	"code.cloudfoundry.org/cli/cf/terminal"
    14  )
    15  
    16  type UpdateBuildpack struct {
    17  	ui                terminal.UI
    18  	buildpackRepo     api.BuildpackRepository
    19  	buildpackBitsRepo api.BuildpackBitsRepository
    20  	buildpackReq      requirements.BuildpackRequirement
    21  }
    22  
    23  func init() {
    24  	commandregistry.Register(&UpdateBuildpack{})
    25  }
    26  
    27  func (cmd *UpdateBuildpack) MetaData() commandregistry.CommandMetadata {
    28  	fs := make(map[string]flags.FlagSet)
    29  	fs["i"] = &flags.IntFlag{ShortName: "i", Usage: T("The order in which the buildpacks are checked during buildpack auto-detection")}
    30  	fs["s"] = &flags.StringFlag{ShortName: "s", Usage: T("Specify stack to disambiguate buildpacks with the same name")}
    31  	fs["p"] = &flags.StringFlag{ShortName: "p", Usage: T("Path to directory or zip file")}
    32  	fs["enable"] = &flags.BoolFlag{Name: "enable", Usage: T("Enable the buildpack to be used for staging")}
    33  	fs["disable"] = &flags.BoolFlag{Name: "disable", Usage: T("Disable the buildpack from being used for staging")}
    34  	fs["lock"] = &flags.BoolFlag{Name: "lock", Usage: T("Lock the buildpack to prevent updates")}
    35  	fs["unlock"] = &flags.BoolFlag{Name: "unlock", Usage: T("Unlock the buildpack to enable updates")}
    36  
    37  	return commandregistry.CommandMetadata{
    38  		Name:        "update-buildpack",
    39  		Description: T("Update a buildpack"),
    40  		Usage: []string{
    41  			T("CF_NAME update-buildpack BUILDPACK [-p PATH] [-i POSITION] [-s STACK] [--enable|--disable] [--lock|--unlock]"),
    42  			T("\n\nTIP:\n"),
    43  			T("   Path 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."),
    44  		},
    45  		Flags: fs,
    46  	}
    47  }
    48  
    49  func (cmd *UpdateBuildpack) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) ([]requirements.Requirement, error) {
    50  	if len(fc.Args()) != 1 {
    51  		cmd.ui.Failed(T("Incorrect Usage. Requires an argument\n\n") + commandregistry.Commands.CommandUsage("update-buildpack"))
    52  		return nil, fmt.Errorf("Incorrect usage: %d arguments of %d required", len(fc.Args()), 1)
    53  	}
    54  
    55  	loginReq := requirementsFactory.NewLoginRequirement()
    56  	cmd.buildpackReq = requirementsFactory.NewBuildpackRequirement(fc.Args()[0], fc.String("s"))
    57  
    58  	reqs := []requirements.Requirement{
    59  		loginReq,
    60  		cmd.buildpackReq,
    61  	}
    62  
    63  	return reqs, nil
    64  }
    65  
    66  func (cmd *UpdateBuildpack) SetDependency(deps commandregistry.Dependency, pluginCall bool) commandregistry.Command {
    67  	cmd.ui = deps.UI
    68  	cmd.buildpackRepo = deps.RepoLocator.GetBuildpackRepository()
    69  	cmd.buildpackBitsRepo = deps.RepoLocator.GetBuildpackBitsRepository()
    70  	return cmd
    71  }
    72  
    73  func (cmd *UpdateBuildpack) Execute(c flags.FlagContext) error {
    74  	buildpack := cmd.buildpackReq.GetBuildpack()
    75  
    76  	cmd.ui.Say(T("Updating buildpack {{.BuildpackName}} with stack {{.BuildpackStack}}...", map[string]interface{}{"BuildpackName": terminal.EntityNameColor(buildpack.Name), "BuildpackStack": terminal.EntityNameColor(buildpack.Stack)}))
    77  
    78  	updateBuildpack := false
    79  
    80  	if c.IsSet("i") {
    81  		position := c.Int("i")
    82  
    83  		buildpack.Position = &position
    84  		updateBuildpack = true
    85  	}
    86  
    87  	enabled := c.Bool("enable")
    88  	disabled := c.Bool("disable")
    89  	if enabled && disabled {
    90  		return errors.New(T("Cannot specify both {{.Enabled}} and {{.Disabled}}.", map[string]interface{}{
    91  			"Enabled":  "enabled",
    92  			"Disabled": "disabled",
    93  		}))
    94  	}
    95  
    96  	if enabled {
    97  		buildpack.Enabled = &enabled
    98  		updateBuildpack = true
    99  	}
   100  	if disabled {
   101  		disabled = false
   102  		buildpack.Enabled = &disabled
   103  		updateBuildpack = true
   104  	}
   105  
   106  	lock := c.Bool("lock")
   107  	unlock := c.Bool("unlock")
   108  	if lock && unlock {
   109  		return errors.New(T("Cannot specify both lock and unlock options."))
   110  	}
   111  
   112  	path := c.String("p")
   113  
   114  	if path != "" && (lock || unlock) {
   115  		return errors.New(T("Cannot specify buildpack bits and lock/unlock."))
   116  	}
   117  
   118  	if lock {
   119  		buildpack.Locked = &lock
   120  		updateBuildpack = true
   121  	}
   122  	if unlock {
   123  		unlock = false
   124  		buildpack.Locked = &unlock
   125  		updateBuildpack = true
   126  	}
   127  	var (
   128  		buildpackFile     *os.File
   129  		buildpackFileName string
   130  		err               error
   131  	)
   132  	if path != "" {
   133  		buildpackFile, buildpackFileName, err = cmd.buildpackBitsRepo.CreateBuildpackZipFile(path)
   134  		if err != nil {
   135  			cmd.ui.Warn(T("Failed to create a local temporary zip file for the buildpack"))
   136  			return err
   137  		}
   138  	}
   139  
   140  	if updateBuildpack {
   141  		newBuildpack, err := cmd.buildpackRepo.Update(buildpack)
   142  		if err != nil {
   143  			return errors.New(T("Error updating buildpack {{.Name}}\n{{.Error}}", map[string]interface{}{
   144  				"Name":  terminal.EntityNameColor(buildpack.Name),
   145  				"Error": err.Error(),
   146  			}))
   147  		}
   148  		buildpack = newBuildpack
   149  	}
   150  
   151  	if path != "" {
   152  		err := cmd.buildpackBitsRepo.UploadBuildpack(buildpack, buildpackFile, buildpackFileName)
   153  		if err != nil {
   154  			return errors.New(T("Error uploading buildpack {{.Name}}\n{{.Error}}", map[string]interface{}{
   155  				"Name":  terminal.EntityNameColor(buildpack.Name),
   156  				"Error": err.Error(),
   157  			}))
   158  		}
   159  	}
   160  	cmd.ui.Ok()
   161  	return nil
   162  }