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  }