github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/command/v6/v3_push_original_command.go (about) 1 package v6 2 3 import ( 4 "code.cloudfoundry.org/cli/actor/actionerror" 5 "code.cloudfoundry.org/cli/actor/pushaction" 6 "code.cloudfoundry.org/cli/actor/sharedaction" 7 "code.cloudfoundry.org/cli/actor/v2action" 8 "code.cloudfoundry.org/cli/actor/v3action" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" 11 "code.cloudfoundry.org/cli/command" 12 "code.cloudfoundry.org/cli/command/translatableerror" 13 "code.cloudfoundry.org/cli/command/v6/shared" 14 ) 15 16 //go:generate counterfeiter . OriginalV2PushActor 17 18 type OriginalV2PushActor interface { 19 CreateAndMapDefaultApplicationRoute(orgGUID string, spaceGUID string, app v2action.Application) (pushaction.Warnings, error) 20 } 21 22 //go:generate counterfeiter . OriginalV3PushActor 23 24 type OriginalV3PushActor interface { 25 CloudControllerAPIVersion() string 26 CreateAndUploadBitsPackageByApplicationNameAndSpace(appName string, spaceGUID string, bitsPath string) (v3action.Package, v3action.Warnings, error) 27 CreateDockerPackageByApplicationNameAndSpace(appName string, spaceGUID string, dockerImageCredentials v3action.DockerImageCredentials) (v3action.Package, v3action.Warnings, error) 28 CreateApplicationInSpace(app v3action.Application, spaceGUID string) (v3action.Application, v3action.Warnings, error) 29 GetApplicationByNameAndSpace(appName string, spaceGUID string) (v3action.Application, v3action.Warnings, error) 30 GetApplicationSummaryByNameAndSpace(appName string, spaceGUID string, withObfuscatedValues bool) (v3action.ApplicationSummary, v3action.Warnings, error) 31 GetStreamingLogsForApplicationByNameAndSpace(appName string, spaceGUID string, client v3action.NOAAClient) (<-chan *v3action.LogMessage, <-chan error, v3action.Warnings, error) 32 PollStart(appGUID string, warnings chan<- v3action.Warnings) error 33 SetApplicationDropletByApplicationNameAndSpace(appName string, spaceGUID string, dropletGUID string) (v3action.Warnings, error) 34 StagePackage(packageGUID string, appName string) (<-chan v3action.Droplet, <-chan v3action.Warnings, <-chan error) 35 StartApplication(appGUID string) (v3action.Application, v3action.Warnings, error) 36 StopApplication(appGUID string) (v3action.Warnings, error) 37 UpdateApplication(app v3action.Application) (v3action.Application, v3action.Warnings, error) 38 } 39 40 func (cmd *V3PushCommand) OriginalSetup(config command.Config, ui command.UI) error { 41 cmd.UI = ui 42 cmd.Config = config 43 sharedActor := sharedaction.NewActor(config) 44 45 ccClient, uaaClient, err := shared.NewV3BasedClients(config, ui, true, "") 46 if err != nil { 47 return err 48 } 49 v3actor := v3action.NewActor(ccClient, config, sharedActor, nil) 50 cmd.OriginalActor = v3actor 51 52 ccClientV2, uaaClientV2, err := shared.NewClients(config, ui, true) 53 if err != nil { 54 return err 55 } 56 57 v2Actor := v2action.NewActor(ccClientV2, uaaClientV2, config) 58 59 cmd.SharedActor = sharedActor 60 cmd.OriginalV2PushActor = pushaction.NewActor(v2Actor, v3actor, sharedActor) 61 62 v2AppActor := v2action.NewActor(ccClientV2, uaaClientV2, config) 63 cmd.NOAAClient = shared.NewNOAAClient(ccClient.Info.Logging(), config, uaaClient, ui) 64 65 cmd.AppSummaryDisplayer = shared.AppSummaryDisplayer{ 66 UI: cmd.UI, 67 Config: cmd.Config, 68 Actor: cmd.OriginalActor, 69 V2AppActor: v2AppActor, 70 AppName: cmd.RequiredArgs.AppName, 71 } 72 cmd.PackageDisplayer = shared.NewPackageDisplayer(cmd.UI, cmd.Config) 73 74 return nil 75 } 76 77 func (cmd V3PushCommand) OriginalExecute(args []string) error { 78 cmd.UI.DisplayWarning(command.ExperimentalWarning) 79 80 err := cmd.validateArgs() 81 if err != nil { 82 return err 83 } 84 85 err = command.MinimumCCAPIVersionCheck(cmd.OriginalActor.CloudControllerAPIVersion(), ccversion.MinVersionApplicationFlowV3) 86 if err != nil { 87 return err 88 } 89 90 err = cmd.SharedActor.CheckTarget(true, true) 91 if err != nil { 92 return err 93 } 94 95 user, err := cmd.Config.CurrentUser() 96 if err != nil { 97 return err 98 } 99 100 if !verifyBuildpacks(cmd.Buildpacks) { 101 return translatableerror.ConflictingBuildpacksError{} 102 } 103 104 var app v3action.Application 105 app, err = cmd.getApplication() 106 if _, ok := err.(actionerror.ApplicationNotFoundError); ok { 107 app, err = cmd.createApplication(user.Name) 108 if err != nil { 109 return err 110 } 111 } else if err != nil { 112 return err 113 } else { 114 app, err = cmd.updateApplication(user.Name, app.GUID) 115 if err != nil { 116 return err 117 } 118 } 119 120 pkg, err := cmd.createPackage() 121 if err != nil { 122 return err 123 } 124 125 if app.Started() { 126 err = cmd.stopApplication(app.GUID, user.Name) 127 if err != nil { 128 return err 129 } 130 } 131 132 if cmd.NoStart { 133 return nil 134 } 135 136 dropletGUID, err := cmd.stagePackage(pkg, user.Name) 137 if err != nil { 138 return err 139 } 140 141 err = cmd.setApplicationDroplet(dropletGUID, user.Name) 142 if err != nil { 143 return err 144 } 145 146 if !cmd.NoRoute { 147 err = cmd.createAndMapRoutes(app) 148 if err != nil { 149 return err 150 } 151 } 152 153 err = cmd.startApplication(app.GUID, user.Name) 154 if err != nil { 155 return err 156 } 157 158 cmd.UI.DisplayText("Waiting for app to start...") 159 160 warnings := make(chan v3action.Warnings) 161 done := make(chan bool) 162 go func() { 163 for { 164 select { 165 case message := <-warnings: 166 cmd.UI.DisplayWarnings(message) 167 case <-done: 168 return 169 } 170 } 171 }() 172 173 err = cmd.OriginalActor.PollStart(app.GUID, warnings) 174 done <- true 175 176 if err != nil { 177 if _, ok := err.(actionerror.StartupTimeoutError); ok { 178 return translatableerror.StartupTimeoutError{ 179 AppName: cmd.RequiredArgs.AppName, 180 BinaryName: cmd.Config.BinaryName(), 181 } 182 } 183 184 return err 185 } 186 187 cmd.UI.DisplayTextWithFlavor("Showing health and status for app {{.AppName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.Username}}...", map[string]interface{}{ 188 "AppName": cmd.RequiredArgs.AppName, 189 "OrgName": cmd.Config.TargetedOrganization().Name, 190 "SpaceName": cmd.Config.TargetedSpace().Name, 191 "Username": user.Name, 192 }) 193 cmd.UI.DisplayNewline() 194 195 return cmd.AppSummaryDisplayer.DisplayAppInfo() 196 } 197 198 func (cmd V3PushCommand) validateArgs() error { 199 switch { 200 case cmd.DockerImage.Path != "" && cmd.AppPath != "": 201 return translatableerror.ArgumentCombinationError{ 202 Args: []string{"--docker-image", "-o", "-p"}, 203 } 204 case cmd.DockerImage.Path != "" && len(cmd.Buildpacks) > 0: 205 return translatableerror.ArgumentCombinationError{ 206 Args: []string{"-b", "--docker-image", "-o"}, 207 } 208 case cmd.DockerUsername != "" && cmd.DockerImage.Path == "": 209 return translatableerror.RequiredFlagsError{ 210 Arg1: "--docker-image, -o", Arg2: "--docker-username", 211 } 212 case cmd.DockerUsername != "" && cmd.Config.DockerPassword() == "": 213 return translatableerror.DockerPasswordNotSetError{} 214 } 215 return nil 216 } 217 218 func (cmd V3PushCommand) createApplication(userName string) (v3action.Application, error) { 219 appToCreate := v3action.Application{ 220 Name: cmd.RequiredArgs.AppName, 221 } 222 223 if cmd.DockerImage.Path != "" { 224 appToCreate.LifecycleType = constant.AppLifecycleTypeDocker 225 } else { 226 appToCreate.LifecycleType = constant.AppLifecycleTypeBuildpack 227 appToCreate.LifecycleBuildpacks = cmd.Buildpacks 228 } 229 230 app, warnings, err := cmd.OriginalActor.CreateApplicationInSpace( 231 appToCreate, 232 cmd.Config.TargetedSpace().GUID, 233 ) 234 cmd.UI.DisplayWarnings(warnings) 235 if err != nil { 236 return v3action.Application{}, err 237 } 238 239 cmd.UI.DisplayTextWithFlavor("Creating app {{.AppName}} in org {{.CurrentOrg}} / space {{.CurrentSpace}} as {{.CurrentUser}}...", map[string]interface{}{ 240 "AppName": cmd.RequiredArgs.AppName, 241 "CurrentSpace": cmd.Config.TargetedSpace().Name, 242 "CurrentOrg": cmd.Config.TargetedOrganization().Name, 243 "CurrentUser": userName, 244 }) 245 246 cmd.UI.DisplayOK() 247 cmd.UI.DisplayNewline() 248 return app, nil 249 } 250 251 func (cmd V3PushCommand) getApplication() (v3action.Application, error) { 252 app, warnings, err := cmd.OriginalActor.GetApplicationByNameAndSpace(cmd.RequiredArgs.AppName, cmd.Config.TargetedSpace().GUID) 253 cmd.UI.DisplayWarnings(warnings) 254 if err != nil { 255 return v3action.Application{}, err 256 } 257 258 return app, nil 259 } 260 261 func (cmd V3PushCommand) updateApplication(userName string, appGUID string) (v3action.Application, error) { 262 cmd.UI.DisplayTextWithFlavor("Updating app {{.AppName}} in org {{.CurrentOrg}} / space {{.CurrentSpace}} as {{.CurrentUser}}...", map[string]interface{}{ 263 "AppName": cmd.RequiredArgs.AppName, 264 "CurrentSpace": cmd.Config.TargetedSpace().Name, 265 "CurrentOrg": cmd.Config.TargetedOrganization().Name, 266 "CurrentUser": userName, 267 }) 268 269 appToUpdate := v3action.Application{ 270 GUID: appGUID, 271 } 272 273 if cmd.DockerImage.Path != "" { 274 appToUpdate.LifecycleType = constant.AppLifecycleTypeDocker 275 276 } else { 277 appToUpdate.LifecycleType = constant.AppLifecycleTypeBuildpack 278 appToUpdate.LifecycleBuildpacks = cmd.Buildpacks 279 } 280 281 app, warnings, err := cmd.OriginalActor.UpdateApplication(appToUpdate) 282 cmd.UI.DisplayWarnings(warnings) 283 if err != nil { 284 return v3action.Application{}, err 285 } 286 287 cmd.UI.DisplayOK() 288 cmd.UI.DisplayNewline() 289 return app, nil 290 } 291 292 func (cmd V3PushCommand) createAndMapRoutes(app v3action.Application) error { 293 cmd.UI.DisplayText("Mapping routes...") 294 routeWarnings, err := cmd.OriginalV2PushActor.CreateAndMapDefaultApplicationRoute(cmd.Config.TargetedOrganization().GUID, cmd.Config.TargetedSpace().GUID, v2action.Application{Name: app.Name, GUID: app.GUID}) 295 cmd.UI.DisplayWarnings(routeWarnings) 296 if err != nil { 297 return err 298 } 299 300 cmd.UI.DisplayOK() 301 cmd.UI.DisplayNewline() 302 return nil 303 } 304 305 func (cmd V3PushCommand) createPackage() (v3action.Package, error) { 306 isDockerImage := (cmd.DockerImage.Path != "") 307 err := cmd.PackageDisplayer.DisplaySetupMessage(cmd.RequiredArgs.AppName, isDockerImage) 308 if err != nil { 309 return v3action.Package{}, err 310 } 311 312 var ( 313 pkg v3action.Package 314 warnings v3action.Warnings 315 ) 316 317 if isDockerImage { 318 pkg, warnings, err = cmd.OriginalActor.CreateDockerPackageByApplicationNameAndSpace(cmd.RequiredArgs.AppName, cmd.Config.TargetedSpace().GUID, v3action.DockerImageCredentials{Path: cmd.DockerImage.Path, Username: cmd.DockerUsername, Password: cmd.Config.DockerPassword()}) 319 } else { 320 pkg, warnings, err = cmd.OriginalActor.CreateAndUploadBitsPackageByApplicationNameAndSpace(cmd.RequiredArgs.AppName, cmd.Config.TargetedSpace().GUID, string(cmd.AppPath)) 321 } 322 323 cmd.UI.DisplayWarnings(warnings) 324 if err != nil { 325 return v3action.Package{}, err 326 } 327 328 cmd.UI.DisplayOK() 329 cmd.UI.DisplayNewline() 330 return pkg, nil 331 } 332 333 func (cmd V3PushCommand) stagePackage(pkg v3action.Package, userName string) (string, error) { 334 cmd.UI.DisplayTextWithFlavor("Staging package for app {{.AppName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.Username}}...", map[string]interface{}{ 335 "AppName": cmd.RequiredArgs.AppName, 336 "OrgName": cmd.Config.TargetedOrganization().Name, 337 "SpaceName": cmd.Config.TargetedSpace().Name, 338 "Username": userName, 339 }) 340 341 logStream, logErrStream, logWarnings, logErr := cmd.OriginalActor.GetStreamingLogsForApplicationByNameAndSpace(cmd.RequiredArgs.AppName, cmd.Config.TargetedSpace().GUID, cmd.NOAAClient) 342 cmd.UI.DisplayWarnings(logWarnings) 343 if logErr != nil { 344 return "", logErr 345 } 346 347 buildStream, warningsStream, errStream := cmd.OriginalActor.StagePackage(pkg.GUID, cmd.RequiredArgs.AppName) 348 droplet, err := shared.PollStage(buildStream, warningsStream, errStream, logStream, logErrStream, cmd.UI) 349 if err != nil { 350 return "", err 351 } 352 353 cmd.UI.DisplayOK() 354 cmd.UI.DisplayNewline() 355 return droplet.GUID, nil 356 } 357 358 func (cmd V3PushCommand) setApplicationDroplet(dropletGUID string, userName string) error { 359 cmd.UI.DisplayTextWithFlavor("Setting app {{.AppName}} to droplet {{.DropletGUID}} in org {{.OrgName}} / space {{.SpaceName}} as {{.Username}}...", map[string]interface{}{ 360 "AppName": cmd.RequiredArgs.AppName, 361 "DropletGUID": dropletGUID, 362 "OrgName": cmd.Config.TargetedOrganization().Name, 363 "SpaceName": cmd.Config.TargetedSpace().Name, 364 "Username": userName, 365 }) 366 367 warnings, err := cmd.OriginalActor.SetApplicationDropletByApplicationNameAndSpace(cmd.RequiredArgs.AppName, cmd.Config.TargetedSpace().GUID, dropletGUID) 368 cmd.UI.DisplayWarnings(warnings) 369 if err != nil { 370 return err 371 } 372 373 cmd.UI.DisplayOK() 374 cmd.UI.DisplayNewline() 375 return nil 376 } 377 378 func (cmd V3PushCommand) startApplication(appGUID string, userName string) error { 379 cmd.UI.DisplayTextWithFlavor("Starting app {{.AppName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.Username}}...", map[string]interface{}{ 380 "AppName": cmd.RequiredArgs.AppName, 381 "OrgName": cmd.Config.TargetedOrganization().Name, 382 "SpaceName": cmd.Config.TargetedSpace().Name, 383 "Username": userName, 384 }) 385 386 _, warnings, err := cmd.OriginalActor.StartApplication(appGUID) 387 cmd.UI.DisplayWarnings(warnings) 388 if err != nil { 389 return err 390 } 391 cmd.UI.DisplayOK() 392 cmd.UI.DisplayNewline() 393 return nil 394 } 395 396 func (cmd V3PushCommand) stopApplication(appGUID string, userName string) error { 397 cmd.UI.DisplayTextWithFlavor("Stopping app {{.AppName}} in org {{.CurrentOrg}} / space {{.CurrentSpace}} as {{.CurrentUser}}...", map[string]interface{}{ 398 "AppName": cmd.RequiredArgs.AppName, 399 "CurrentSpace": cmd.Config.TargetedSpace().Name, 400 "CurrentOrg": cmd.Config.TargetedOrganization().Name, 401 "CurrentUser": userName, 402 }) 403 404 warnings, err := cmd.OriginalActor.StopApplication(appGUID) 405 cmd.UI.DisplayWarnings(warnings) 406 if err != nil { 407 return err 408 } 409 cmd.UI.DisplayOK() 410 cmd.UI.DisplayNewline() 411 return nil 412 } 413 414 func verifyBuildpacks(buildpacks []string) bool { 415 if len(buildpacks) < 2 { 416 return true 417 } 418 419 for _, buildpack := range buildpacks { 420 if buildpack == "default" || buildpack == "null" { 421 return false 422 } 423 } 424 return true 425 }