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 }