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  }