github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/cf/commands/buildpack/create_buildpack.go (about) 1 package buildpack 2 3 import ( 4 "fmt" 5 "strconv" 6 7 "code.cloudfoundry.org/cli/cf/flags" 8 . "code.cloudfoundry.org/cli/cf/i18n" 9 10 "code.cloudfoundry.org/cli/cf" 11 "code.cloudfoundry.org/cli/cf/api" 12 "code.cloudfoundry.org/cli/cf/commandregistry" 13 "code.cloudfoundry.org/cli/cf/errors" 14 "code.cloudfoundry.org/cli/cf/models" 15 "code.cloudfoundry.org/cli/cf/requirements" 16 "code.cloudfoundry.org/cli/cf/terminal" 17 ) 18 19 type CreateBuildpack struct { 20 ui terminal.UI 21 buildpackRepo api.BuildpackRepository 22 buildpackBitsRepo api.BuildpackBitsRepository 23 } 24 25 func init() { 26 commandregistry.Register(&CreateBuildpack{}) 27 } 28 29 func (cmd *CreateBuildpack) MetaData() commandregistry.CommandMetadata { 30 fs := make(map[string]flags.FlagSet) 31 fs["enable"] = &flags.BoolFlag{Name: "enable", Usage: T("Enable the buildpack to be used for staging")} 32 fs["disable"] = &flags.BoolFlag{Name: "disable", Usage: T("Disable the buildpack from being used for staging")} 33 34 return commandregistry.CommandMetadata{ 35 Name: "create-buildpack", 36 Description: T("Create a buildpack"), 37 Usage: []string{ 38 T("CF_NAME create-buildpack BUILDPACK PATH POSITION [--enable|--disable]"), 39 T("\n\nTIP:\n"), 40 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."), 41 }, 42 Flags: fs, 43 TotalArgs: 3, 44 } 45 } 46 47 func (cmd *CreateBuildpack) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) ([]requirements.Requirement, error) { 48 if len(fc.Args()) != 3 { 49 cmd.ui.Failed(T("Incorrect Usage. Requires buildpack_name, path and position as arguments\n\n") + commandregistry.Commands.CommandUsage("create-buildpack")) 50 return nil, fmt.Errorf("Incorrect usage: %d arguments of %d required", len(fc.Args()), 3) 51 } 52 53 reqs := []requirements.Requirement{ 54 requirementsFactory.NewLoginRequirement(), 55 } 56 57 return reqs, nil 58 } 59 60 func (cmd *CreateBuildpack) SetDependency(deps commandregistry.Dependency, pluginCall bool) commandregistry.Command { 61 cmd.ui = deps.UI 62 cmd.buildpackRepo = deps.RepoLocator.GetBuildpackRepository() 63 cmd.buildpackBitsRepo = deps.RepoLocator.GetBuildpackBitsRepository() 64 return cmd 65 } 66 67 func (cmd *CreateBuildpack) Execute(c flags.FlagContext) error { 68 buildpackName := c.Args()[0] 69 70 buildpackFile, buildpackFileName, err := cmd.buildpackBitsRepo.CreateBuildpackZipFile(c.Args()[1]) 71 if err != nil { 72 cmd.ui.Warn(T("Failed to create a local temporary zip file for the buildpack")) 73 return err 74 } 75 76 cmd.ui.Say(T("Creating buildpack {{.BuildpackName}}...", map[string]interface{}{"BuildpackName": terminal.EntityNameColor(buildpackName)})) 77 78 buildpack, err := cmd.createBuildpack(buildpackName, c) 79 80 if err != nil { 81 if httpErr, ok := err.(errors.HTTPError); ok && httpErr.ErrorCode() == errors.BuildpackNameTaken { 82 cmd.ui.Ok() 83 cmd.ui.Warn(T("Buildpack {{.BuildpackName}} already exists", map[string]interface{}{"BuildpackName": buildpackName})) 84 cmd.ui.Say(T("TIP: use '{{.CfUpdateBuildpackCommand}}' to update this buildpack", map[string]interface{}{"CfUpdateBuildpackCommand": terminal.CommandColor(cf.Name + " " + "update-buildpack")})) 85 } else if httpErr, ok := err.(errors.HTTPError); ok && httpErr.ErrorCode() == errors.StackUnique { 86 cmd.ui.Ok() 87 cmd.ui.Warn(T("Buildpack {{.BuildpackName}} already exists without a stack", map[string]interface{}{"BuildpackName": buildpackName})) 88 cmd.ui.Say(T("TIP: use '{{.CfDeleteBuildpackCommand}}' to delete buildpack {{.BuildpackName}} without a stack", map[string]interface{}{"CfDeleteBuildpackCommand": terminal.CommandColor(cf.Name + " " + "delete-buildpack"), "BuildpackName": buildpackName})) 89 } else { 90 return err 91 } 92 return nil 93 } 94 cmd.ui.Ok() 95 cmd.ui.Say("") 96 97 cmd.ui.Say(T("Uploading buildpack {{.BuildpackName}}...", map[string]interface{}{"BuildpackName": terminal.EntityNameColor(buildpackName)})) 98 99 err = cmd.buildpackBitsRepo.UploadBuildpack(buildpack, buildpackFile, buildpackFileName) 100 if err != nil { 101 if httpErr, ok := err.(errors.HTTPError); ok && httpErr.ErrorCode() == errors.BuildpackNameStackTaken { 102 cmd.ui.Ok() 103 cmd.ui.Warn(httpErr.Error()) 104 cmd.ui.Say(T("TIP: use '{{.CfUpdateBuildpackCommand}}' to update this buildpack", map[string]interface{}{"CfUpdateBuildpackCommand": terminal.CommandColor(cf.Name + " " + "update-buildpack")})) 105 } else { 106 return err 107 } 108 return nil 109 } 110 111 cmd.ui.Ok() 112 return nil 113 } 114 115 func (cmd CreateBuildpack) createBuildpack(buildpackName string, c flags.FlagContext) (buildpack models.Buildpack, apiErr error) { 116 position, err := strconv.Atoi(c.Args()[2]) 117 if err != nil { 118 apiErr = fmt.Errorf(T("Error {{.ErrorDescription}} is being passed in as the argument for 'Position' but 'Position' requires an integer. For more syntax help, see `cf create-buildpack -h`.", map[string]interface{}{"ErrorDescription": c.Args()[2]})) 119 return 120 } 121 122 enabled := c.Bool("enable") 123 disabled := c.Bool("disable") 124 if enabled && disabled { 125 apiErr = errors.New(T("Cannot specify both {{.Enabled}} and {{.Disabled}}.", map[string]interface{}{ 126 "Enabled": "enabled", 127 "Disabled": "disabled", 128 })) 129 return 130 } 131 132 var enableOption *bool 133 if enabled { 134 enableOption = &enabled 135 } 136 if disabled { 137 disabled = false 138 enableOption = &disabled 139 } 140 141 buildpack, apiErr = cmd.buildpackRepo.Create(buildpackName, &position, enableOption, nil) 142 143 return 144 }