func singleAppManifest() *manifest.Manifest { return &manifest.Manifest{ Path: "manifest.yml", Data: generic.NewMap(map[interface{}]interface{}{ "applications": []interface{}{ generic.NewMap(map[interface{}]interface{}{ "name": "manifest-app-name", "memory": "128MB", "instances": 1, "host": "manifest-host", "domain": "manifest-example.com", "stack": "custom-stack", "timeout": 360, "buildpack": "some-buildpack", "command": `JAVA_HOME=$PWD/.openjdk JAVA_OPTS="-Xss995K" ./bin/start.sh run`, "path": filepath.Clean("some/path/from/manifest"), "env": generic.NewMap(map[interface{}]interface{}{ "FOO": "baz", "PATH": "/u/apps/my-app/bin", }), }), }, }), } }
func envVarOrEmptyMap(yamlMap generic.Map, errs *[]error) *map[string]interface{} { key := "env" switch envVars := yamlMap.Get(key).(type) { case nil: aMap := make(map[string]interface{}, 0) return &aMap case map[string]interface{}: yamlMap.Set(key, generic.NewMap(yamlMap.Get(key))) return envVarOrEmptyMap(yamlMap, errs) case map[interface{}]interface{}: yamlMap.Set(key, generic.NewMap(yamlMap.Get(key))) return envVarOrEmptyMap(yamlMap, errs) case generic.Map: merrs := validateEnvVars(envVars) if merrs != nil { *errs = append(*errs, merrs...) return nil } result := make(map[string]interface{}, envVars.Count()) generic.Each(envVars, func(key, value interface{}) { result[key.(string)] = value }) return &result default: *errs = append(*errs, fmt.Errorf(T("Expected {{.Name}} to be a set of key => value, but it was a {{.Type}}.", map[string]interface{}{"Name": key, "Type": envVars}))) return nil } }
func (resource EventResourceNewV2) ToFields() models.EventFields { metadata := generic.NewMap(resource.Entity.Metadata) if metadata.Has("request") { metadata = generic.NewMap(metadata.Get("request")) } return models.EventFields{ Guid: resource.Metadata.Guid, Name: resource.Entity.Type, Timestamp: resource.Entity.Timestamp, Description: formatDescription(metadata, knownMetadataKeys), ActorName: resource.Entity.ActorName, } }
func (m *appManifest) Save(f io.Writer) error { y := generic.NewMap() apps := []generic.Map{} for _, app := range m.contents { appMap, mapErr := generateAppMap(app) if mapErr != nil { return fmt.Errorf(T("Error saving manifest: {{.Error}}", map[string]interface{}{ "Error": mapErr.Error(), })) } apps = append(apps, appMap) } y.Set("applications", apps) contents, err := yaml.Marshal(y) if err != nil { return err } _, err = f.Write(contents) if err != nil { return err } return nil }
func (m Manifest) Applications() ([]models.AppParams, error) { rawData, err := expandProperties(m.Data, generator.NewWordGenerator()) if err != nil { return []models.AppParams{}, err } data := generic.NewMap(rawData) appMaps, err := m.getAppMaps(data) if err != nil { return []models.AppParams{}, err } var apps []models.AppParams var mapToAppErrs []error for _, appMap := range appMaps { app, err := mapToAppParams(filepath.Dir(m.Path), appMap) if err != nil { mapToAppErrs = append(mapToAppErrs, err) continue } apps = append(apps, app) } if len(mapToAppErrs) > 0 { message := "" for i := range mapToAppErrs { message = message + fmt.Sprintf("%s\n", mapToAppErrs[i].Error()) } return []models.AppParams{}, errors.New(message) } return apps, nil }
func (m Manifest) getAppMaps(data generic.Map) (apps []generic.Map, errs []error) { globalProperties := data.Except([]interface{}{"applications"}) if data.Has("applications") { appMaps, ok := data.Get("applications").([]interface{}) if !ok { errs = append(errs, errors.New(T("Expected applications to be a list"))) return } for _, appData := range appMaps { if !generic.IsMappable(appData) { errs = append(errs, errors.NewWithFmt(T("Expected application to be a list of key/value pairs\nError occurred in manifest near:\n'{{.YmlSnippet}}'", map[string]interface{}{"YmlSnippet": appData}))) continue } appMap := generic.DeepMerge(globalProperties, generic.NewMap(appData)) apps = append(apps, appMap) } } else { apps = append(apps, globalProperties) } return }
func (m Manifest) Applications() (apps []models.AppParams, err error) { rawData, errs := expandProperties(m.Data, words.NewWordGenerator()) if len(errs) > 0 { err = errors.NewWithSlice(errs) return } data := generic.NewMap(rawData) appMaps, errs := m.getAppMaps(data) if len(errs) > 0 { err = errors.NewWithSlice(errs) return } for _, appMap := range appMaps { app, errs := mapToAppParams(filepath.Dir(m.Path), appMap) if len(errs) > 0 { err = errors.NewWithSlice(errs) continue } apps = append(apps, app) } return }
func (m Manifest) getAppMaps(data generic.Map) ([]generic.Map, error) { globalProperties := data.Except([]interface{}{"applications"}) var apps []generic.Map var errs []error if data.Has("applications") { appMaps, ok := data.Get("applications").([]interface{}) if !ok { return []generic.Map{}, errors.New(T("Expected applications to be a list")) } for _, appData := range appMaps { if !generic.IsMappable(appData) { errs = append(errs, fmt.Errorf(T("Expected application to be a list of key/value pairs\nError occurred in manifest near:\n'{{.YmlSnippet}}'", map[string]interface{}{"YmlSnippet": appData}))) continue } appMap := generic.DeepMerge(globalProperties, generic.NewMap(appData)) apps = append(apps, appMap) } } else { apps = append(apps, globalProperties) } if len(errs) > 0 { message := "" for i := range errs { message = message + fmt.Sprintf("%s\n", errs[i].Error()) } return []generic.Map{}, errors.New(message) } return apps, nil }
func envVarOrEmptyMap(yamlMap generic.Map, errs *[]error) *map[string]string { key := "env" switch envVars := yamlMap.Get(key).(type) { case nil: aMap := make(map[string]string, 0) return &aMap case map[string]interface{}: yamlMap.Set(key, generic.NewMap(yamlMap.Get(key))) return envVarOrEmptyMap(yamlMap, errs) case map[interface{}]interface{}: yamlMap.Set(key, generic.NewMap(yamlMap.Get(key))) return envVarOrEmptyMap(yamlMap, errs) case generic.Map: merrs := validateEnvVars(envVars) if merrs != nil { *errs = append(*errs, merrs...) return nil } result := make(map[string]string, envVars.Count()) generic.Each(envVars, func(key, value interface{}) { switch value.(type) { case string: result[key.(string)] = value.(string) case int64, int, int32: result[key.(string)] = fmt.Sprintf("%d", value) case float32, float64: result[key.(string)] = fmt.Sprintf("%f", value) default: *errs = append(*errs, errors.NewWithFmt(T("Expected environment variable {{.PropertyName}} to have a string value, but it was a {{.PropertyType}}.", map[string]interface{}{"PropertyName": key, "PropertyType": value}))) } }) return &result default: *errs = append(*errs, errors.NewWithFmt(T("Expected {{.Name}} to be a set of key => value, but it was a {{.Type}}.", map[string]interface{}{"Name": key, "Type": envVars}))) return nil } }
func manifestWithServicesAndEnv() *manifest.Manifest { return &manifest.Manifest{ Data: generic.NewMap(map[interface{}]interface{}{ "applications": []interface{}{ generic.NewMap(map[interface{}]interface{}{ "name": "app1", "services": []interface{}{"app1-service", "global-service"}, "env": generic.NewMap(map[interface{}]interface{}{ "SOMETHING": "definitely-something", }), }), generic.NewMap(map[interface{}]interface{}{ "name": "app2", "services": []interface{}{"app2-service", "global-service"}, "env": generic.NewMap(map[interface{}]interface{}{ "SOMETHING": "nothing", }), }), }, }), } }
func parseManifest(file io.Reader) (yamlMap generic.Map, err error) { decoder := candiedyaml.NewDecoder(file) yamlMap = generic.NewMap() err = decoder.Decode(yamlMap) if err != nil { return } if !generic.IsMappable(yamlMap) { err = errors.New(T("Invalid manifest. Expected a map")) return } return }
func expandProperties(input interface{}, babbler words.WordGenerator) (output interface{}, errs []error) { switch input := input.(type) { case string: match := propertyRegex.FindStringSubmatch(input) if match != nil { if match[0] == "${random-word}" { output = strings.Replace(input, "${random-word}", strings.ToLower(babbler.Babble()), -1) } else { err := errors.NewWithFmt(T("Property '{{.PropertyName}}' found in manifest. This feature is no longer supported. Please remove it and try again.", map[string]interface{}{"PropertyName": match[0]})) errs = append(errs, err) } } else { output = input } case []interface{}: outputSlice := make([]interface{}, len(input)) for index, item := range input { itemOutput, itemErrs := expandProperties(item, babbler) outputSlice[index] = itemOutput errs = append(errs, itemErrs...) } output = outputSlice case map[interface{}]interface{}: outputMap := make(map[interface{}]interface{}) for key, value := range input { itemOutput, itemErrs := expandProperties(value, babbler) outputMap[key] = itemOutput errs = append(errs, itemErrs...) } output = outputMap case generic.Map: outputMap := generic.NewMap() generic.Each(input, func(key, value interface{}) { itemOutput, itemErrs := expandProperties(value, babbler) outputMap.Set(key, itemOutput) errs = append(errs, itemErrs...) }) output = outputMap default: output = input } return }
func parseManifest(file io.Reader) (yamlMap generic.Map, err error) { manifest, err := ioutil.ReadAll(file) if err != nil { return } mmap := make(map[interface{}]interface{}) err = yaml.Unmarshal(manifest, &mmap) if err != nil { return } if !generic.IsMappable(mmap) || len(mmap) == 0 { err = errors.New(T("Invalid manifest. Expected a map")) return } yamlMap = generic.NewMap(mmap) return }
func NewEmptyManifest() (m *Manifest) { return &Manifest{Data: generic.NewMap()} }
func expandProperties(input interface{}, babbler generator.WordGenerator) (interface{}, error) { var errs []error var output interface{} switch input := input.(type) { case string: match := propertyRegex.FindStringSubmatch(input) if match != nil { if match[0] == "${random-word}" { output = strings.Replace(input, "${random-word}", strings.ToLower(babbler.Babble()), -1) } else { err := fmt.Errorf(T("Property '{{.PropertyName}}' found in manifest. This feature is no longer supported. Please remove it and try again.", map[string]interface{}{"PropertyName": match[0]})) errs = append(errs, err) } } else { output = input } case []interface{}: outputSlice := make([]interface{}, len(input)) for index, item := range input { itemOutput, itemErr := expandProperties(item, babbler) if itemErr != nil { errs = append(errs, itemErr) break } outputSlice[index] = itemOutput } output = outputSlice case map[interface{}]interface{}: outputMap := make(map[interface{}]interface{}) for key, value := range input { itemOutput, itemErr := expandProperties(value, babbler) if itemErr != nil { errs = append(errs, itemErr) break } outputMap[key] = itemOutput } output = outputMap case generic.Map: outputMap := generic.NewMap() generic.Each(input, func(key, value interface{}) { itemOutput, itemErr := expandProperties(value, babbler) if itemErr != nil { errs = append(errs, itemErr) return } outputMap.Set(key, itemOutput) }) output = outputMap default: output = input } if len(errs) > 0 { message := "" for _, err := range errs { message = message + fmt.Sprintf("%s\n", err.Error()) } return nil, errors.New(message) } return output, nil }
. "github.com/onsi/gomega" . "github.com/cloudfoundry/cli/testhelpers/matchers" ) func NewManifest(path string, data generic.Map) (m *manifest.Manifest) { return &manifest.Manifest{Path: path, Data: data} } var _ = Describe("Manifests", func() { It("merges global properties into each app's properties", func() { m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ "instances": "3", "memory": "512M", "applications": []interface{}{ map[interface{}]interface{}{ "name": "bitcoin-miner", "no-route": true, }, }, })) apps, err := m.Applications() Expect(err).NotTo(HaveOccurred()) Expect(*apps[0].InstanceCount).To(Equal(3)) Expect(*apps[0].Memory).To(Equal(int64(512))) Expect(apps[0].NoRoute).To(BeTrue()) }) Context("when there is no applications block", func() { It("returns a single application with the global properties", func() {
)) Expect(ui.Outputs).ToNot(ContainSubstrings([]string{"existing-app.example.com"})) Expect(routeRepo.FindByHostAndDomainCalledWith.Domain.Name).To(Equal("example.com")) Expect(routeRepo.FindByHostAndDomainCalledWith.Host).To(Equal("")) Expect(routeRepo.CreatedHost).To(Equal("")) Expect(routeRepo.CreatedDomainGuid).To(Equal("domain-guid")) }) }) }) Describe("service instances", func() { BeforeEach(func() { serviceRepo.FindInstanceByNameMap = generic.NewMap(map[interface{}]interface{}{ "global-service": maker.NewServiceInstance("global-service"), "app1-service": maker.NewServiceInstance("app1-service"), "app2-service": maker.NewServiceInstance("app2-service"), }) manifestRepo.ReadManifestReturns.Manifest = manifestWithServicesAndEnv() }) Context("when the service is not bound", func() { BeforeEach(func() { appRepo.ReadReturns.Error = errors.NewModelNotFoundError("App", "the-app") }) It("binds service instances to the app", func() { callPush() Expect(len(serviceBinder.AppsToBind)).To(Equal(4)) Expect(serviceBinder.AppsToBind[0].Name).To(Equal("app1"))
func (r *FakeRepo) ReadManifest(path string) (*manifest.Manifest, error) { yamlMap := generic.NewMap() candiedyaml.Unmarshal([]byte(r.yaml), yamlMap) return &manifest.Manifest{Data: yamlMap}, r.err }
"strings" . "github.com/cloudfoundry/cli/testhelpers/matchers" ) func NewManifest(path string, data generic.Map) (m *manifest.Manifest) { return &manifest.Manifest{Path: path, Data: data} } var _ = Describe("Manifests", func() { It("merges global properties into each app's properties", func() { m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ "instances": "3", "memory": "512M", "applications": []interface{}{ map[interface{}]interface{}{ "name": "bitcoin-miner", "no-route": true, }, }, })) apps, err := m.Applications() Expect(err).NotTo(HaveOccurred()) Expect(*apps[0].InstanceCount).To(Equal(3)) Expect(*apps[0].Memory).To(Equal(int64(512))) Expect(apps[0].NoRoute).To(BeTrue()) }) Describe("when there is no applications block", func() { It("returns a single application with the global properties", func() {
var ( ui *testterm.FakeUI config core_config.Repository cmd *ServiceKeys requirementsFactory *testreq.FakeReqFactory serviceRepo *testapi.FakeServiceRepo serviceKeyRepo *testapi.FakeServiceKeyRepo ) BeforeEach(func() { ui = &testterm.FakeUI{} config = testconfig.NewRepositoryWithDefaults() serviceRepo = &testapi.FakeServiceRepo{} serviceInstance := models.ServiceInstance{} serviceInstance.Guid = "fake-instance-guid" serviceRepo.FindInstanceByNameMap = generic.NewMap() serviceRepo.FindInstanceByNameMap.Set("fake-service-instance", serviceInstance) serviceKeyRepo = testapi.NewFakeServiceKeyRepo() cmd = NewListServiceKeys(ui, config, serviceRepo, serviceKeyRepo) requirementsFactory = &testreq.FakeReqFactory{LoginSuccess: true, TargetedSpaceSuccess: true, ServiceInstanceNotFound: false} requirementsFactory.ServiceInstance = serviceInstance }) var callListServiceKeys = func(args []string) bool { return testcmd.RunCommand(cmd, args, requirementsFactory) } Describe("requirements", func() { It("fails when not logged in", func() { requirementsFactory = &testreq.FakeReqFactory{LoginSuccess: false} Expect(callListServiceKeys([]string{"fake-service-instance", "fake-service-key"})).To(BeFalse())
func generateAppMap(app models.Application) (generic.Map, error) { if app.Stack == nil { return generic.NewMap(), errors.New(T("required attribute 'stack' missing")) } if app.Memory == 0 { return generic.NewMap(), errors.New(T("required attribute 'memory' missing")) } if app.DiskQuota == 0 { return generic.NewMap(), errors.New(T("required attribute 'disk_quota' missing")) } if app.InstanceCount == 0 { return generic.NewMap(), errors.New(T("required attribute 'instances' missing")) } m := generic.NewMap() m.Set("name", app.Name) m.Set("memory", fmt.Sprintf("%dM", app.Memory)) m.Set("instances", app.InstanceCount) m.Set("disk_quota", fmt.Sprintf("%dM", app.DiskQuota)) m.Set("stack", app.Stack.Name) if len(app.AppPorts) > 0 { m.Set("app-ports", app.AppPorts) } if app.BuildpackUrl != "" { m.Set("buildpack", app.BuildpackUrl) } if app.HealthCheckTimeout > 0 { m.Set("timeout", app.HealthCheckTimeout) } if app.Command != "" { m.Set("command", app.Command) } switch len(app.Routes) { case 0: m.Set("no-route", true) case 1: const noHostname = "" m.Set("domain", app.Routes[0].Domain.Name) host := app.Routes[0].Host if host == noHostname { m.Set("no-hostname", true) } else { m.Set("host", host) } default: hosts, domains := separateHostsAndDomains(app.Routes) switch len(hosts) { case 0: m.Set("no-hostname", true) case 1: m.Set("host", hosts[0]) default: m.Set("hosts", hosts) } switch len(domains) { case 1: m.Set("domain", domains[0]) default: m.Set("domains", domains) } } if len(app.Services) > 0 { var services []string for _, s := range app.Services { services = append(services, s.Name) } m.Set("services", services) } if len(app.EnvironmentVars) > 0 { m.Set("env", app.EnvironmentVars) } return m, nil }