github.com/ablease/cli@v6.37.1-0.20180613014814-3adbb7d7fb19+incompatible/actor/pushaction/application.go (about) 1 package pushaction 2 3 import ( 4 "fmt" 5 6 "code.cloudfoundry.org/cli/actor/actionerror" 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/types" 11 log "github.com/sirupsen/logrus" 12 ) 13 14 type Application struct { 15 v2action.Application 16 Buildpacks []string 17 Stack v2action.Stack 18 } 19 20 func (app Application) String() string { 21 return fmt.Sprintf("%s, Stack Name: '%s', Buildpacks: %s", app.Application, app.Stack.Name, app.Buildpacks) 22 } 23 24 func (app *Application) SetStack(stack v2action.Stack) { 25 app.Stack = stack 26 app.StackGUID = stack.GUID 27 } 28 29 func (actor Actor) CreateApplication(config ApplicationConfig) (ApplicationConfig, Event, Warnings, error) { 30 var warnings Warnings 31 log.Debugf("creating application") 32 v2App := config.DesiredApplication.Application 33 v2App.Buildpack = actor.setBuildpack(config) 34 35 newApp, v2warnings, err := actor.V2Actor.CreateApplication(v2App) 36 warnings = append(warnings, v2warnings...) 37 if err != nil { 38 log.Errorln("creating application:", err) 39 return ApplicationConfig{}, "", Warnings(warnings), err 40 } 41 42 if config.HasV3Buildpacks() { 43 v3Warnings, v3Err := actor.updateBuildpacks(config, newApp) 44 warnings = append(warnings, v3Warnings...) 45 if v3Err != nil { 46 return ApplicationConfig{}, "", warnings, v3Err 47 } 48 } 49 50 config.DesiredApplication.Application = newApp 51 config.CurrentApplication = config.DesiredApplication 52 53 return config, CreatedApplication, Warnings(warnings), nil 54 } 55 56 func (actor Actor) UpdateApplication(config ApplicationConfig) (ApplicationConfig, Event, Warnings, error) { 57 var warnings Warnings 58 log.Debugf("updating application") 59 v2App := config.DesiredApplication.Application 60 v2App.Buildpack = actor.setBuildpack(config) 61 62 v2App = actor.ignoreSameState(config, v2App) 63 v2App = actor.ignoreSameStackGUID(config, v2App) 64 65 updatedApp, v2Warnings, err := actor.V2Actor.UpdateApplication(v2App) 66 warnings = append(warnings, v2Warnings...) 67 if err != nil { 68 log.Errorln("updating application:", err) 69 return ApplicationConfig{}, "", Warnings(warnings), err 70 } 71 72 if config.HasV3Buildpacks() { 73 v3Warnings, v3Err := actor.updateBuildpacks(config, updatedApp) 74 warnings = append(warnings, v3Warnings...) 75 if v3Err != nil { 76 return ApplicationConfig{}, "", warnings, v3Err 77 } 78 } 79 80 config.DesiredApplication.Application = updatedApp 81 config.CurrentApplication = config.DesiredApplication 82 83 return config, UpdatedApplication, Warnings(warnings), err 84 } 85 86 func (actor Actor) FindOrReturnPartialApp(appName string, spaceGUID string) (bool, Application, v2action.Warnings, error) { 87 foundApp, appWarnings, err := actor.V2Actor.GetApplicationByNameAndSpace(appName, spaceGUID) 88 if _, ok := err.(actionerror.ApplicationNotFoundError); ok { 89 log.Warnf("unable to find app %s in current space (GUID: %s)", appName, spaceGUID) 90 return false, Application{ 91 Application: v2action.Application{ 92 Name: appName, 93 SpaceGUID: spaceGUID, 94 }, 95 }, appWarnings, nil 96 } else if err != nil { 97 log.WithField("appName", appName).Error("error retrieving app") 98 return false, Application{}, appWarnings, err 99 } 100 101 stack, stackWarnings, err := actor.V2Actor.GetStack(foundApp.StackGUID) 102 warnings := append(appWarnings, stackWarnings...) 103 if err != nil { 104 log.Warnf("unable to find app's stack (GUID: %s)", foundApp.StackGUID) 105 return false, Application{}, warnings, err 106 } 107 108 app := Application{ 109 Application: foundApp, 110 Stack: stack, 111 } 112 return true, app, warnings, err 113 } 114 115 // For some versions of CC, sending state will always result in CC 116 // attempting to do perform that request (i.e. started -> start/restart). 117 // In order to prevent repeated unintended restarts in the middle of a 118 // push, don't send state. This will be fixed in capi-release 1.48.0. 119 func (actor Actor) ignoreSameState(config ApplicationConfig, v2App v2action.Application) v2action.Application { 120 if config.CurrentApplication.State == config.DesiredApplication.State { 121 v2App.State = "" 122 } 123 124 return v2App 125 } 126 127 // Apps updates with both docker image and stack guids fail. So do not send 128 // StackGUID unless it is necessary. 129 func (actor Actor) ignoreSameStackGUID(config ApplicationConfig, v2App v2action.Application) v2action.Application { 130 if config.CurrentApplication.StackGUID == config.DesiredApplication.StackGUID { 131 v2App.StackGUID = "" 132 } 133 134 return v2App 135 } 136 137 // If 'buildpacks' is set with only one buildpack, set `buildpack` (singular) 138 // on the application. 139 func (Actor) setBuildpack(config ApplicationConfig) types.FilteredString { 140 buildpacks := config.DesiredApplication.Buildpacks 141 142 if len(buildpacks) == 1 { 143 filtered := new(types.FilteredString) 144 filtered.ParseValue(buildpacks[0]) 145 return *filtered 146 } 147 148 if buildpacks != nil && len(buildpacks) == 0 { 149 filtered := types.FilteredString{IsSet: true} 150 return filtered 151 } 152 153 return config.DesiredApplication.Buildpack 154 } 155 156 func (actor Actor) updateBuildpacks(config ApplicationConfig, v2App v2action.Application) (Warnings, error) { 157 var buildpacks []string 158 for _, buildpack := range config.DesiredApplication.Buildpacks { 159 buildpacks = append(buildpacks, buildpack) 160 } 161 162 v3App := v3action.Application{ 163 Name: v2App.Name, 164 GUID: v2App.GUID, 165 LifecycleBuildpacks: buildpacks, 166 LifecycleType: constant.AppLifecycleTypeBuildpack, 167 } 168 169 _, warnings, err := actor.V3Actor.UpdateApplication(v3App) 170 return Warnings(warnings), err 171 }