github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/command/v6/create_buildpack_command.go (about) 1 package v6 2 3 import ( 4 "io/ioutil" 5 "os" 6 "time" 7 8 "code.cloudfoundry.org/cli/actor/actionerror" 9 "code.cloudfoundry.org/cli/actor/sharedaction" 10 "code.cloudfoundry.org/cli/actor/v2action" 11 "code.cloudfoundry.org/cli/command" 12 "code.cloudfoundry.org/cli/command/flag" 13 "code.cloudfoundry.org/cli/command/translatableerror" 14 "code.cloudfoundry.org/cli/command/v6/shared" 15 "code.cloudfoundry.org/cli/util/download" 16 ) 17 18 //go:generate counterfeiter . Downloader 19 20 type Downloader interface { 21 Download(string) (string, error) 22 } 23 24 //go:generate counterfeiter . CreateBuildpackActor 25 26 type CreateBuildpackActor interface { 27 CreateBuildpack(name string, position int, enabled bool) (v2action.Buildpack, v2action.Warnings, error) 28 UploadBuildpack(GUID string, path string, progBar v2action.SimpleProgressBar) (v2action.Warnings, error) 29 PrepareBuildpackBits(inputPath string, tmpDirPath string, downloader v2action.Downloader) (string, error) 30 } 31 32 type CreateBuildpackCommand struct { 33 RequiredArgs flag.CreateBuildpackArgs `positional-args:"yes"` 34 Disable bool `long:"disable" description:"Disable the buildpack from being used for staging"` 35 Enable bool `long:"enable" description:"Enable the buildpack to be used for staging"` 36 usage interface{} `usage:"CF_NAME create-buildpack BUILDPACK PATH POSITION [--enable|--disable]\n\nTIP:\n 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."` 37 relatedCommands interface{} `related_commands:"buildpacks, push"` 38 39 UI command.UI 40 Actor CreateBuildpackActor 41 ProgressBar v2action.SimpleProgressBar 42 SharedActor command.SharedActor 43 Config command.Config 44 } 45 46 func (cmd *CreateBuildpackCommand) Setup(config command.Config, ui command.UI) error { 47 cmd.UI = ui 48 cmd.Config = config 49 cmd.SharedActor = sharedaction.NewActor(config) 50 51 ccClient, uaaClient, err := shared.NewClients(config, ui, true) 52 if err != nil { 53 return err 54 } 55 cmd.Actor = v2action.NewActor(ccClient, uaaClient, config) 56 cmd.ProgressBar = v2action.NewProgressBar() 57 58 return nil 59 } 60 61 func (cmd *CreateBuildpackCommand) Execute(args []string) error { 62 if cmd.Enable && cmd.Disable { 63 return translatableerror.ArgumentCombinationError{ 64 Args: []string{"--enable", "--disable"}, 65 } 66 } 67 68 err := cmd.SharedActor.CheckTarget(false, false) 69 if err != nil { 70 return err 71 } 72 73 user, err := cmd.Config.CurrentUser() 74 if err != nil { 75 return err 76 } 77 78 cmd.UI.DisplayTextWithFlavor("Creating buildpack {{.Buildpack}} as {{.Username}}...", map[string]interface{}{ 79 "Buildpack": cmd.RequiredArgs.Buildpack, 80 "Username": user.Name, 81 }) 82 83 downloader := download.NewDownloader(time.Second * 30) 84 tmpDirPath, err := ioutil.TempDir("", "buildpack-dir-") 85 if err != nil { 86 return err 87 } 88 defer os.RemoveAll(tmpDirPath) 89 90 pathToBuildpackBits, err := cmd.Actor.PrepareBuildpackBits(string(cmd.RequiredArgs.Path), tmpDirPath, downloader) 91 if err != nil { 92 return err 93 } 94 95 buildpack, warnings, err := cmd.Actor.CreateBuildpack(cmd.RequiredArgs.Buildpack, cmd.RequiredArgs.Position, !cmd.Disable) 96 cmd.UI.DisplayWarnings(warnings) 97 98 if err != nil { 99 return cmd.displayIfNameCollisionError(err) 100 } 101 102 cmd.UI.DisplayOK() 103 cmd.UI.DisplayNewline() 104 105 cmd.UI.DisplayTextWithFlavor("Uploading buildpack {{.Buildpack}} as {{.Username}}...", map[string]interface{}{ 106 "Buildpack": cmd.RequiredArgs.Buildpack, 107 "Username": user.Name, 108 }) 109 110 uploadWarnings, err := cmd.Actor.UploadBuildpack(buildpack.GUID, pathToBuildpackBits, cmd.ProgressBar) 111 cmd.UI.DisplayWarnings(uploadWarnings) 112 if err != nil { 113 cmd.UI.DisplayNewline() 114 cmd.UI.DisplayNewline() 115 if _, ok := err.(actionerror.BuildpackAlreadyExistsForStackError); ok { 116 cmd.displayNameAndStackCollisionError(err) 117 return nil 118 } else if httpErr, ok := err.(download.RawHTTPStatusError); ok { 119 return translatableerror.HTTPStatusError{Status: httpErr.Status} 120 } 121 return err 122 } 123 124 cmd.UI.DisplayNewline() 125 cmd.UI.DisplayText("Done uploading") 126 cmd.UI.DisplayOK() 127 128 return nil 129 } 130 131 func (cmd CreateBuildpackCommand) displayNameAndStackCollisionError(err error) { 132 cmd.UI.DisplayWarning(err.Error()) 133 cmd.UI.DisplayTextWithFlavor("TIP: use '{{.CfUpdateBuildpackCommand}}' to update this buildpack", 134 map[string]interface{}{ 135 "CfUpdateBuildpackCommand": cmd.Config.BinaryName() + " update-buildpack", 136 }) 137 } 138 139 func (cmd CreateBuildpackCommand) displayIfNameCollisionError(err error) error { 140 if _, ok := err.(actionerror.BuildpackAlreadyExistsWithoutStackError); ok { 141 cmd.displayAlreadyExistingBuildpackWithoutStack(err) 142 return nil 143 } else if _, ok := err.(actionerror.BuildpackNameTakenError); ok { 144 cmd.displayAlreadyExistingBuildpack(err) 145 return nil 146 } 147 return err 148 } 149 150 func (cmd CreateBuildpackCommand) displayAlreadyExistingBuildpackWithoutStack(err error) { 151 cmd.UI.DisplayNewline() 152 cmd.UI.DisplayWarning(err.Error()) 153 cmd.UI.DisplayTextWithFlavor("TIP: use '{{.CfBuildpacksCommand}}' and '{{.CfDeleteBuildpackCommand}}' to delete buildpack {{.BuildpackName}} without a stack", 154 map[string]interface{}{ 155 "CfBuildpacksCommand": cmd.Config.BinaryName() + " buildpacks", 156 "CfDeleteBuildpackCommand": cmd.Config.BinaryName() + " delete-buildpack", 157 "BuildpackName": cmd.RequiredArgs.Buildpack, 158 }) 159 } 160 161 func (cmd CreateBuildpackCommand) displayAlreadyExistingBuildpack(err error) { 162 cmd.UI.DisplayNewline() 163 cmd.UI.DisplayWarning(err.Error()) 164 cmd.UI.DisplayTextWithFlavor("TIP: use '{{.CfUpdateBuildpackCommand}}' to update this buildpack", 165 map[string]interface{}{ 166 "CfUpdateBuildpackCommand": cmd.Config.BinaryName() + " update-buildpack", 167 }) 168 }