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