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