github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+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) HasMultipleBuildpacks() 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 config := ApplicationConfig{ 60 NoRoute: app.NoRoute, 61 } 62 63 if app.DropletPath != "" { 64 absPath, err := filepath.EvalSymlinks(app.DropletPath) 65 if err != nil { 66 return nil, nil, err 67 } 68 config.DropletPath = absPath 69 } else { 70 absPath, err := filepath.EvalSymlinks(app.Path) 71 if err != nil { 72 return nil, nil, err 73 } 74 config.Path = absPath 75 } 76 77 log.Infoln("searching for app", app.Name) 78 found, constructedApp, v2Warnings, err := actor.FindOrReturnPartialApp(app.Name, spaceGUID) 79 warnings = append(warnings, v2Warnings...) 80 if err != nil { 81 log.Errorln("app lookup:", err) 82 return nil, warnings, err 83 } 84 85 if found { 86 var configWarnings v2action.Warnings 87 config, configWarnings, err = actor.configureExistingApp(config, app, constructedApp) 88 warnings = append(warnings, configWarnings...) 89 if err != nil { 90 log.Errorln("configuring existing app:", err) 91 return nil, warnings, err 92 } 93 } else { 94 log.Debug("using empty app as base") 95 config.DesiredApplication = constructedApp 96 } 97 config.DesiredApplication = actor.overrideApplicationProperties(config.DesiredApplication, app, noStart) 98 99 var stackWarnings Warnings 100 config.DesiredApplication, stackWarnings, err = actor.overrideStack(config.DesiredApplication, app) 101 warnings = append(warnings, stackWarnings...) 102 if err != nil { 103 return nil, warnings, err 104 } 105 log.Debugln("post overriding config:", config.DesiredApplication) 106 107 var serviceWarnings Warnings 108 config.DesiredServices, serviceWarnings, err = actor.getDesiredServices(config.CurrentServices, app.Services, spaceGUID) 109 warnings = append(warnings, serviceWarnings...) 110 if err != nil { 111 log.Errorln("getting services:", err) 112 return nil, warnings, err 113 } 114 115 if !config.NoRoute { 116 var routeWarnings Warnings 117 config, routeWarnings, err = actor.configureRoutes(app, orgGUID, spaceGUID, config) 118 warnings = append(warnings, routeWarnings...) 119 if err != nil { 120 log.Errorln("determining routes:", err) 121 return nil, warnings, err 122 } 123 } 124 125 if app.DockerImage == "" && app.DropletPath == "" { 126 config, err = actor.configureResources(config) 127 if err != nil { 128 log.Errorln("configuring resources", err) 129 return nil, warnings, err 130 } 131 } 132 133 configs = append(configs, config) 134 } 135 136 return configs, warnings, nil 137 } 138 139 func (actor Actor) configureRoutes(manifestApp manifest.Application, orgGUID string, spaceGUID string, config ApplicationConfig) (ApplicationConfig, Warnings, error) { 140 switch { 141 case len(manifestApp.Routes) > 0: // Routes in manifest mutually exclusive with all other route related fields 142 routes, warnings, err := actor.CalculateRoutes(manifestApp.Routes, orgGUID, spaceGUID, config.CurrentRoutes) 143 config.DesiredRoutes = routes 144 return config, warnings, err 145 case len(config.CurrentRoutes) > 0 && (manifestApp.RandomRoute || manifestApp.Domain == ""): 146 config.DesiredRoutes = config.CurrentRoutes 147 return config, nil, nil 148 case manifestApp.RandomRoute: 149 // append random route to current route (becomes desired route) 150 randomRoute, warnings, err := actor.GenerateRandomRoute(manifestApp, spaceGUID, orgGUID) 151 config.DesiredRoutes = append(config.CurrentRoutes, randomRoute) 152 return config, warnings, err 153 default: 154 desiredRoute, warnings, err := actor.GetGeneratedRoute(manifestApp, orgGUID, spaceGUID, config.CurrentRoutes) 155 if err != nil { 156 log.Errorln("getting default route:", err) 157 return config, warnings, err 158 } 159 config.DesiredRoutes = append(config.CurrentRoutes, desiredRoute) 160 return config, warnings, nil 161 } 162 } 163 164 func (actor Actor) getDesiredServices(currentServices map[string]v2action.ServiceInstance, requestedServices []string, spaceGUID string) (map[string]v2action.ServiceInstance, Warnings, error) { 165 var warnings Warnings 166 167 desiredServices := map[string]v2action.ServiceInstance{} 168 for name, serviceInstance := range currentServices { 169 log.Debugln("adding bound service:", name) 170 desiredServices[name] = serviceInstance 171 } 172 173 for _, serviceName := range requestedServices { 174 if _, ok := desiredServices[serviceName]; !ok { 175 log.Debugln("adding requested service:", serviceName) 176 serviceInstance, serviceWarnings, err := actor.V2Actor.GetServiceInstanceByNameAndSpace(serviceName, spaceGUID) 177 warnings = append(warnings, serviceWarnings...) 178 if err != nil { 179 return nil, warnings, err 180 } 181 182 desiredServices[serviceName] = serviceInstance 183 } 184 } 185 return desiredServices, warnings, nil 186 } 187 188 func (actor Actor) configureExistingApp(config ApplicationConfig, app manifest.Application, foundApp Application) (ApplicationConfig, v2action.Warnings, error) { 189 log.Debugln("found app:", foundApp) 190 config.CurrentApplication = foundApp 191 config.DesiredApplication = foundApp 192 193 log.Info("looking up application routes") 194 routes, warnings, err := actor.V2Actor.GetApplicationRoutes(foundApp.GUID) 195 if err != nil { 196 log.Errorln("existing routes lookup:", err) 197 return config, warnings, err 198 } 199 200 serviceInstances, serviceWarnings, err := actor.V2Actor.GetServiceInstancesByApplication(foundApp.GUID) 201 warnings = append(warnings, serviceWarnings...) 202 if err != nil { 203 log.Errorln("existing services lookup:", err) 204 return config, warnings, err 205 } 206 207 nameToService := map[string]v2action.ServiceInstance{} 208 for _, serviceInstance := range serviceInstances { 209 nameToService[serviceInstance.Name] = serviceInstance 210 } 211 212 config.CurrentRoutes = routes 213 config.CurrentServices = nameToService 214 return config, warnings, nil 215 } 216 217 func (actor Actor) configureResources(config ApplicationConfig) (ApplicationConfig, error) { 218 info, err := os.Stat(config.Path) 219 if err != nil { 220 return config, err 221 } 222 223 var resources []sharedaction.Resource 224 if info.IsDir() { 225 log.WithField("path_to_resources", config.Path).Info("determine directory resources to zip") 226 resources, err = actor.SharedActor.GatherDirectoryResources(config.Path) 227 } else { 228 config.Archive = true 229 log.WithField("path_to_resources", config.Path).Info("determine archive resources to zip") 230 resources, err = actor.SharedActor.GatherArchiveResources(config.Path) 231 } 232 if err != nil { 233 return config, err 234 } 235 config.AllResources = actor.ConvertSharedResourcesToV2Resources(resources) 236 237 log.WithField("number_of_files", len(resources)).Debug("completed file scan") 238 239 return config, nil 240 } 241 242 func (Actor) overrideApplicationProperties(application Application, manifest manifest.Application, noStart bool) Application { 243 if manifest.Buildpack.IsSet { 244 application.Buildpacks = []string{} 245 if len(manifest.Buildpack.Value) > 0 { 246 application.Buildpacks = append(application.Buildpacks, manifest.Buildpack.Value) 247 } 248 } 249 250 if manifest.Buildpacks != nil { 251 application.Buildpacks = append([]string{}, manifest.Buildpacks...) 252 } 253 254 if manifest.Command.IsSet { 255 application.Command = manifest.Command 256 } 257 258 if manifest.DockerImage != "" { 259 application.DockerImage = manifest.DockerImage 260 if manifest.DockerUsername != "" { 261 application.DockerCredentials.Username = manifest.DockerUsername 262 application.DockerCredentials.Password = manifest.DockerPassword 263 } 264 } 265 266 if manifest.DiskQuota.IsSet { 267 application.DiskQuota = manifest.DiskQuota 268 } 269 270 if manifest.Memory.IsSet { 271 application.Memory = manifest.Memory 272 } 273 274 if manifest.HealthCheckTimeout != 0 { 275 application.HealthCheckTimeout = manifest.HealthCheckTimeout 276 } 277 278 if manifest.HealthCheckType != "" { 279 application.HealthCheckType = constant.ApplicationHealthCheckType(manifest.HealthCheckType) 280 application.HealthCheckHTTPEndpoint = manifest.HealthCheckHTTPEndpoint 281 282 if application.HealthCheckType == constant.ApplicationHealthCheckHTTP && application.HealthCheckHTTPEndpoint == "" { 283 application.HealthCheckHTTPEndpoint = "/" 284 } 285 } 286 287 if manifest.Instances.IsSet { 288 application.Instances = manifest.Instances 289 } 290 291 if noStart { 292 application.State = constant.ApplicationStopped 293 } 294 295 if len(manifest.EnvironmentVariables) > 0 { 296 if application.EnvironmentVariables == nil { 297 application.EnvironmentVariables = manifest.EnvironmentVariables 298 } else { 299 env := map[string]string{} 300 for key, value := range application.EnvironmentVariables { 301 env[key] = value 302 } 303 for key, value := range manifest.EnvironmentVariables { 304 env[key] = value 305 } 306 application.EnvironmentVariables = env 307 } 308 } 309 310 log.Debugln("post application override:", application) 311 312 return application 313 } 314 315 func (actor Actor) overrideStack(application Application, manifest manifest.Application) (Application, Warnings, error) { 316 if manifest.StackName == "" { 317 return application, nil, nil 318 } 319 stack, warnings, err := actor.V2Actor.GetStackByName(manifest.StackName) 320 application.SetStack(stack) 321 return application, Warnings(warnings), err 322 }