github.com/elopio/cli@v6.21.2-0.20160902224010-ea909d1fdb2f+incompatible/cf/manifest/generate_manifest.go (about)

     1  package manifest
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"code.cloudfoundry.org/cli/cf/models"
     8  
     9  	"gopkg.in/yaml.v2"
    10  
    11  	"io"
    12  
    13  	. "code.cloudfoundry.org/cli/cf/i18n"
    14  )
    15  
    16  //go:generate counterfeiter . App
    17  
    18  type App interface {
    19  	BuildpackURL(string, string)
    20  	DiskQuota(string, int64)
    21  	Memory(string, int64)
    22  	Service(string, string)
    23  	StartCommand(string, string)
    24  	EnvironmentVars(string, string, string)
    25  	HealthCheckTimeout(string, int)
    26  	Instances(string, int)
    27  	Route(string, string, string, string, int)
    28  	GetContents() []models.Application
    29  	Stack(string, string)
    30  	AppPorts(string, []int)
    31  	Save(f io.Writer) error
    32  }
    33  
    34  type Application struct {
    35  	Name      string                 `yaml:"name"`
    36  	Instances int                    `yaml:"instances,omitempty"`
    37  	Memory    string                 `yaml:"memory,omitempty"`
    38  	DiskQuota string                 `yaml:"disk_quota,omitempty"`
    39  	AppPorts  []int                  `yaml:"app-ports,omitempty"`
    40  	Routes    []map[string]string    `yaml:"routes,omitempty"`
    41  	NoRoute   bool                   `yaml:"no-route,omitempty"`
    42  	Buildpack string                 `yaml:"buildpack,omitempty"`
    43  	Command   string                 `yaml:"command,omitempty"`
    44  	Env       map[string]interface{} `yaml:"env,omitempty"`
    45  	Services  []string               `yaml:"services,omitempty"`
    46  	Stack     string                 `yaml:"stack,omitempty"`
    47  	Timeout   int                    `yaml:"timeout,omitempty"`
    48  }
    49  
    50  type Applications struct {
    51  	Applications []Application `yaml:"applications"`
    52  }
    53  
    54  type appManifest struct {
    55  	contents []models.Application
    56  }
    57  
    58  func NewGenerator() App {
    59  	return &appManifest{}
    60  }
    61  
    62  func (m *appManifest) Stack(appName string, stackName string) {
    63  	i := m.findOrCreateApplication(appName)
    64  	m.contents[i].Stack = &models.Stack{
    65  		Name: stackName,
    66  	}
    67  }
    68  
    69  func (m *appManifest) Memory(appName string, memory int64) {
    70  	i := m.findOrCreateApplication(appName)
    71  	m.contents[i].Memory = memory
    72  }
    73  
    74  func (m *appManifest) DiskQuota(appName string, diskQuota int64) {
    75  	i := m.findOrCreateApplication(appName)
    76  	m.contents[i].DiskQuota = diskQuota
    77  }
    78  
    79  func (m *appManifest) StartCommand(appName string, cmd string) {
    80  	i := m.findOrCreateApplication(appName)
    81  	m.contents[i].Command = cmd
    82  }
    83  
    84  func (m *appManifest) BuildpackURL(appName string, url string) {
    85  	i := m.findOrCreateApplication(appName)
    86  	m.contents[i].BuildpackURL = url
    87  }
    88  
    89  func (m *appManifest) HealthCheckTimeout(appName string, timeout int) {
    90  	i := m.findOrCreateApplication(appName)
    91  	m.contents[i].HealthCheckTimeout = timeout
    92  }
    93  
    94  func (m *appManifest) Instances(appName string, instances int) {
    95  	i := m.findOrCreateApplication(appName)
    96  	m.contents[i].InstanceCount = instances
    97  }
    98  
    99  func (m *appManifest) Service(appName string, name string) {
   100  	i := m.findOrCreateApplication(appName)
   101  	m.contents[i].Services = append(m.contents[i].Services, models.ServicePlanSummary{
   102  		GUID: "",
   103  		Name: name,
   104  	})
   105  }
   106  
   107  func (m *appManifest) Route(appName, host, domain, path string, port int) {
   108  	i := m.findOrCreateApplication(appName)
   109  	m.contents[i].Routes = append(m.contents[i].Routes, models.RouteSummary{
   110  		Host: host,
   111  		Domain: models.DomainFields{
   112  			Name: domain,
   113  		},
   114  		Path: path,
   115  		Port: port,
   116  	})
   117  
   118  }
   119  
   120  func (m *appManifest) EnvironmentVars(appName string, key, value string) {
   121  	i := m.findOrCreateApplication(appName)
   122  	m.contents[i].EnvironmentVars[key] = value
   123  }
   124  
   125  func (m *appManifest) AppPorts(appName string, appPorts []int) {
   126  	i := m.findOrCreateApplication(appName)
   127  	m.contents[i].AppPorts = appPorts
   128  }
   129  
   130  func (m *appManifest) GetContents() []models.Application {
   131  	return m.contents
   132  }
   133  
   134  func generateAppMap(app models.Application) (Application, error) {
   135  	if app.Stack == nil {
   136  		return Application{}, errors.New(T("required attribute 'stack' missing"))
   137  	}
   138  
   139  	if app.Memory == 0 {
   140  		return Application{}, errors.New(T("required attribute 'memory' missing"))
   141  	}
   142  
   143  	if app.DiskQuota == 0 {
   144  		return Application{}, errors.New(T("required attribute 'disk_quota' missing"))
   145  	}
   146  
   147  	if app.InstanceCount == 0 {
   148  		return Application{}, errors.New(T("required attribute 'instances' missing"))
   149  	}
   150  
   151  	var services []string
   152  	for _, s := range app.Services {
   153  		services = append(services, s.Name)
   154  	}
   155  
   156  	var routes []map[string]string
   157  	for _, routeSummary := range app.Routes {
   158  		routes = append(routes, buildRoute(routeSummary))
   159  	}
   160  	m := Application{
   161  		Name:      app.Name,
   162  		Services:  services,
   163  		Buildpack: app.BuildpackURL,
   164  		Memory:    fmt.Sprintf("%dM", app.Memory),
   165  		Command:   app.Command,
   166  		Env:       app.EnvironmentVars,
   167  		Timeout:   app.HealthCheckTimeout,
   168  		Instances: app.InstanceCount,
   169  		DiskQuota: fmt.Sprintf("%dM", app.DiskQuota),
   170  		Stack:     app.Stack.Name,
   171  		AppPorts:  app.AppPorts,
   172  		Routes:    routes,
   173  	}
   174  
   175  	if len(app.Routes) == 0 {
   176  		m.NoRoute = true
   177  
   178  	}
   179  
   180  	return m, nil
   181  }
   182  
   183  func (m *appManifest) Save(f io.Writer) error {
   184  	apps := Applications{}
   185  
   186  	for _, app := range m.contents {
   187  		appMap, mapErr := generateAppMap(app)
   188  		if mapErr != nil {
   189  			return fmt.Errorf(T("Error saving manifest: {{.Error}}", map[string]interface{}{
   190  				"Error": mapErr.Error(),
   191  			}))
   192  		}
   193  		apps.Applications = append(apps.Applications, appMap)
   194  	}
   195  
   196  	contents, err := yaml.Marshal(apps)
   197  	if err != nil {
   198  		return err
   199  	}
   200  
   201  	_, err = f.Write(contents)
   202  	if err != nil {
   203  		return err
   204  	}
   205  
   206  	return nil
   207  }
   208  
   209  func buildRoute(routeSummary models.RouteSummary) map[string]string {
   210  	var route string
   211  	if routeSummary.Host != "" {
   212  		route = fmt.Sprintf("%s.", routeSummary.Host)
   213  	}
   214  
   215  	route = fmt.Sprintf("%s%s", route, routeSummary.Domain.Name)
   216  
   217  	if routeSummary.Path != "" {
   218  		route = fmt.Sprintf("%s%s", route, routeSummary.Path)
   219  	}
   220  
   221  	if routeSummary.Port != 0 {
   222  		route = fmt.Sprintf("%s:%d", route, routeSummary.Port)
   223  	}
   224  
   225  	return map[string]string{
   226  		"route": route,
   227  	}
   228  }
   229  
   230  func (m *appManifest) findOrCreateApplication(name string) int {
   231  	for i, app := range m.contents {
   232  		if app.Name == name {
   233  			return i
   234  		}
   235  	}
   236  	m.addApplication(name)
   237  	return len(m.contents) - 1
   238  }
   239  
   240  func (m *appManifest) addApplication(name string) {
   241  	m.contents = append(m.contents, models.Application{
   242  		ApplicationFields: models.ApplicationFields{
   243  			Name:            name,
   244  			EnvironmentVars: make(map[string]interface{}),
   245  		},
   246  	})
   247  }