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