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 }