github.com/nimakaviani/cli@v6.37.1-0.20180619223813-e734901a73fa+incompatible/actor/pushaction/application_config.go (about) 1 package pushaction 2 3 import ( 4 "os" 5 "path/filepath" 6 7 "code.cloudfoundry.org/cli/actor/sharedaction" 8 "code.cloudfoundry.org/cli/actor/v2action" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant" 10 "code.cloudfoundry.org/cli/util/manifest" 11 log "github.com/sirupsen/logrus" 12 ) 13 14 type ApplicationConfig struct { 15 CurrentApplication Application 16 DesiredApplication Application 17 18 CurrentRoutes []v2action.Route 19 DesiredRoutes []v2action.Route 20 NoRoute bool 21 22 CurrentServices map[string]v2action.ServiceInstance 23 DesiredServices map[string]v2action.ServiceInstance 24 25 AllResources []v2action.Resource 26 MatchedResources []v2action.Resource 27 UnmatchedResources []v2action.Resource 28 Archive bool 29 Path string 30 DropletPath string 31 } 32 33 func (config ApplicationConfig) CreatingApplication() bool { 34 return config.CurrentApplication.GUID == "" 35 } 36 37 func (config ApplicationConfig) UpdatingApplication() bool { 38 return !config.CreatingApplication() 39 } 40 41 func (config ApplicationConfig) HasV3Buildpacks() bool { 42 return len(config.DesiredApplication.Buildpacks) > 1 43 } 44 45 // ConvertToApplicationConfigs converts a set of application manifests into an 46 // application configs. These configs reflect the current and desired states of 47 // the application - providing details required by the Apply function to 48 // proceed. 49 // 50 // The V2 Actor is primarily used to determine all but multiple buildpack 51 // information. Only then is the V3 Actor used to gather the multiple 52 // buildpacks. 53 func (actor Actor) ConvertToApplicationConfigs(orgGUID string, spaceGUID string, noStart bool, apps []manifest.Application) ([]ApplicationConfig, Warnings, error) { 54 var configs []ApplicationConfig 55 var warnings Warnings 56 57 log.Infof("iterating through %d app configuration(s)", len(apps)) 58 for _, app := range apps { 59 60 var ( 61 config ApplicationConfig 62 absPath string 63 err error 64 ) 65 if app.DropletPath != "" { 66 absPath, err = filepath.EvalSymlinks(app.DropletPath) 67 if err != nil { 68 return nil, nil, err 69 } 70 config = ApplicationConfig{ 71 DropletPath: absPath, 72 NoRoute: app.NoRoute, 73 } 74 } else { 75 absPath, err = filepath.EvalSymlinks(app.Path) 76 if err != nil { 77 return nil, nil, err 78 } 79 config = ApplicationConfig{ 80 Path: absPath, 81 NoRoute: app.NoRoute, 82 } 83 } 84 85 log.Infoln("searching for app", app.Name) 86 found, constructedApp, v2Warnings, err := actor.FindOrReturnPartialApp(app.Name, spaceGUID) 87 warnings = append(warnings, v2Warnings...) 88 if err != nil { 89 log.Errorln("app lookup:", err) 90 return nil, warnings, err 91 } 92 93 if found { 94 var configWarnings v2action.Warnings 95 config, configWarnings, err = actor.configureExistingApp(config, app, constructedApp) 96 warnings = append(warnings, configWarnings...) 97 if err != nil { 98 log.Errorln("configuring existing app:", err) 99 return nil, warnings, err 100 } 101 } else { 102 log.Debug("using empty app as base") 103 config.DesiredApplication = constructedApp 104 } 105 config.DesiredApplication = actor.overrideApplicationProperties(config.DesiredApplication, app, noStart) 106 107 var stackWarnings Warnings 108 config.DesiredApplication, stackWarnings, err = actor.overrideStack(config.DesiredApplication, app) 109 warnings = append(warnings, stackWarnings...) 110 if err != nil { 111 return nil, warnings, err 112 } 113 log.Debugln("post overriding config:", config.DesiredApplication) 114 115 var serviceWarnings Warnings 116 config.DesiredServices, serviceWarnings, err = actor.getDesiredServices(config.CurrentServices, app.Services, spaceGUID) 117 warnings = append(warnings, serviceWarnings...) 118 if err != nil { 119 log.Errorln("getting services:", err) 120 return nil, warnings, err 121 } 122 123 if !config.NoRoute { 124 var routeWarnings Warnings 125 config, routeWarnings, err = actor.configureRoutes(app, orgGUID, spaceGUID, config) 126 warnings = append(warnings, routeWarnings...) 127 if err != nil { 128 log.Errorln("determining routes:", err) 129 return nil, warnings, err 130 } 131 } 132 133 if app.DockerImage == "" && app.DropletPath == "" { 134 config, err = actor.configureResources(config) 135 if err != nil { 136 log.Errorln("configuring resources", err) 137 return nil, warnings, err 138 } 139 } 140 141 configs = append(configs, config) 142 } 143 144 return configs, warnings, nil 145 } 146 147 func (actor Actor) configureRoutes(manifestApp manifest.Application, orgGUID string, spaceGUID string, config ApplicationConfig) (ApplicationConfig, Warnings, error) { 148 switch { 149 case len(manifestApp.Routes) > 0: // Routes in manifest mutually exclusive with all other route related fields 150 routes, warnings, err := actor.CalculateRoutes(manifestApp.Routes, orgGUID, spaceGUID, config.CurrentRoutes) 151 config.DesiredRoutes = routes 152 return config, warnings, err 153 case len(config.CurrentRoutes) > 0 && (manifestApp.RandomRoute || manifestApp.Domain == ""): 154 config.DesiredRoutes = config.CurrentRoutes 155 return config, nil, nil 156 case manifestApp.RandomRoute: 157 // append random route to current route (becomes desired route) 158 randomRoute, warnings, err := actor.GenerateRandomRoute(manifestApp, spaceGUID, orgGUID) 159 config.DesiredRoutes = append(config.CurrentRoutes, randomRoute) 160 return config, warnings, err 161 default: 162 desiredRoute, warnings, err := actor.GetGeneratedRoute(manifestApp, orgGUID, spaceGUID, config.CurrentRoutes) 163 if err != nil { 164 log.Errorln("getting default route:", err) 165 return config, warnings, err 166 } 167 config.DesiredRoutes = append(config.CurrentRoutes, desiredRoute) 168 return config, warnings, nil 169 } 170 } 171 172 func (actor Actor) getDesiredServices(currentServices map[string]v2action.ServiceInstance, requestedServices []string, spaceGUID string) (map[string]v2action.ServiceInstance, Warnings, error) { 173 var warnings Warnings 174 175 desiredServices := map[string]v2action.ServiceInstance{} 176 for name, serviceInstance := range currentServices { 177 log.Debugln("adding bound service:", name) 178 desiredServices[name] = serviceInstance 179 } 180 181 for _, serviceName := range requestedServices { 182 if _, ok := desiredServices[serviceName]; !ok { 183 log.Debugln("adding requested service:", serviceName) 184 serviceInstance, serviceWarnings, err := actor.V2Actor.GetServiceInstanceByNameAndSpace(serviceName, spaceGUID) 185 warnings = append(warnings, serviceWarnings...) 186 if err != nil { 187 return nil, warnings, err 188 } 189 190 desiredServices[serviceName] = serviceInstance 191 } 192 } 193 return desiredServices, warnings, nil 194 } 195 196 func (actor Actor) configureExistingApp(config ApplicationConfig, app manifest.Application, foundApp Application) (ApplicationConfig, v2action.Warnings, error) { 197 log.Debugln("found app:", foundApp) 198 config.CurrentApplication = foundApp 199 config.DesiredApplication = foundApp 200 201 log.Info("looking up application routes") 202 routes, warnings, err := actor.V2Actor.GetApplicationRoutes(foundApp.GUID) 203 if err != nil { 204 log.Errorln("existing routes lookup:", err) 205 return config, warnings, err 206 } 207 208 serviceInstances, serviceWarnings, err := actor.V2Actor.GetServiceInstancesByApplication(foundApp.GUID) 209 warnings = append(warnings, serviceWarnings...) 210 if err != nil { 211 log.Errorln("existing services lookup:", err) 212 return config, warnings, err 213 } 214 215 nameToService := map[string]v2action.ServiceInstance{} 216 for _, serviceInstance := range serviceInstances { 217 nameToService[serviceInstance.Name] = serviceInstance 218 } 219 220 config.CurrentRoutes = routes 221 config.CurrentServices = nameToService 222 return config, warnings, nil 223 } 224 225 func (actor Actor) configureResources(config ApplicationConfig) (ApplicationConfig, error) { 226 info, err := os.Stat(config.Path) 227 if err != nil { 228 return config, err 229 } 230 231 var resources []sharedaction.Resource 232 if info.IsDir() { 233 log.WithField("path_to_resources", config.Path).Info("determine directory resources to zip") 234 resources, err = actor.SharedActor.GatherDirectoryResources(config.Path) 235 } else { 236 config.Archive = true 237 log.WithField("path_to_resources", config.Path).Info("determine archive resources to zip") 238 resources, err = actor.SharedActor.GatherArchiveResources(config.Path) 239 } 240 if err != nil { 241 return config, err 242 } 243 config.AllResources = actor.ConvertSharedResourcesToV2Resources(resources) 244 245 log.WithField("number_of_files", len(resources)).Debug("completed file scan") 246 247 return config, nil 248 } 249 250 func (Actor) overrideApplicationProperties(application Application, manifest manifest.Application, noStart bool) Application { 251 252 if manifest.Buildpack.IsSet { 253 application.Buildpack = manifest.Buildpack 254 } 255 256 if manifest.Buildpacks != nil { 257 application.Buildpacks = []string{} 258 } 259 260 for _, buildpack := range manifest.Buildpacks { 261 application.Buildpacks = append(application.Buildpacks, buildpack) 262 } 263 264 if manifest.Command.IsSet { 265 application.Command = manifest.Command 266 } 267 if manifest.DockerImage != "" { 268 application.DockerImage = manifest.DockerImage 269 if manifest.DockerUsername != "" { 270 application.DockerCredentials.Username = manifest.DockerUsername 271 application.DockerCredentials.Password = manifest.DockerPassword 272 } 273 } 274 275 if manifest.DiskQuota.IsSet { 276 application.DiskQuota = manifest.DiskQuota 277 } 278 279 if manifest.Memory.IsSet { 280 application.Memory = manifest.Memory 281 } 282 283 if manifest.HealthCheckTimeout != 0 { 284 application.HealthCheckTimeout = manifest.HealthCheckTimeout 285 } 286 287 if manifest.HealthCheckType != "" { 288 application.HealthCheckType = constant.ApplicationHealthCheckType(manifest.HealthCheckType) 289 application.HealthCheckHTTPEndpoint = manifest.HealthCheckHTTPEndpoint 290 291 if application.HealthCheckType == constant.ApplicationHealthCheckHTTP && application.HealthCheckHTTPEndpoint == "" { 292 application.HealthCheckHTTPEndpoint = "/" 293 } 294 } 295 296 if manifest.Instances.IsSet { 297 application.Instances = manifest.Instances 298 } 299 300 if noStart { 301 application.State = constant.ApplicationStopped 302 } 303 304 if len(manifest.EnvironmentVariables) > 0 { 305 if application.EnvironmentVariables == nil { 306 application.EnvironmentVariables = manifest.EnvironmentVariables 307 } else { 308 env := map[string]string{} 309 for key, value := range application.EnvironmentVariables { 310 env[key] = value 311 } 312 for key, value := range manifest.EnvironmentVariables { 313 env[key] = value 314 } 315 application.EnvironmentVariables = env 316 } 317 } 318 319 log.Debugln("post application override:", application) 320 321 return application 322 } 323 324 func (actor Actor) overrideStack(application Application, manifest manifest.Application) (Application, Warnings, error) { 325 if manifest.StackName == "" { 326 return application, nil, nil 327 } 328 stack, warnings, err := actor.V2Actor.GetStackByName(manifest.StackName) 329 application.SetStack(stack) 330 return application, Warnings(warnings), err 331 }