func envVarOrEmptyMap(yamlMap generic.Map, errs *ManifestErrors) *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{}) { result[key.(string)] = value.(string) }) return &result default: *errs = append(*errs, errors.New(fmt.Sprintf("Expected %s to be a set of key => value, but it was a %T.", key, envVars))) return nil } }
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 (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, KNOWN_METADATA_KEYS), } }
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 TestParsingManifestWithNulls(t *testing.T) { _, errs := manifest.NewManifest(generic.NewMap(map[string]interface{}{ "applications": []interface{}{ map[string]interface{}{ "buildpack": nil, "disk_quota": nil, "domain": nil, "host": nil, "name": nil, "path": nil, "stack": nil, "memory": nil, "instances": nil, "timeout": nil, "no-route": nil, "services": nil, "env": nil, }, }, })) assert.Error(t, errs) errorSlice := strings.Split(errs.Error(), "\n") manifestKeys := []string{"buildpack", "disk_quota", "domain", "host", "name", "path", "stack", "memory", "instances", "timeout", "no-route", "services", "env"} for _, key := range manifestKeys { testassert.SliceContains(t, errorSlice, testassert.Lines{{key, "not be null"}}) } }
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("Expected applications to be a list")) return } for _, appData := range appMaps { if !generic.IsMappable(appData) { errs = append(errs, errors.New(fmt.Sprintf("Expected application to be a list of key/value pairs\nError occurred in manifest near:\n'%s'", 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 mapToAppSet(basePath string, data generic.Map) (appSet []models.AppParams, errs ManifestErrors) { if data.Has("applications") { appMaps, ok := data.Get("applications").([]interface{}) if !ok { errs = append(errs, errors.New("Expected applications to be a list")) return } // we delete applications so that we may merge top level app params into each app data.Delete("applications") for _, appData := range appMaps { if !generic.IsMappable(appData) { errs = append(errs, errors.New("Expected application to be a dictionary")) continue } appMap := generic.DeepMerge(data, generic.NewMap(appData)) appParams, appErrs := mapToAppParams(basePath, appMap) if !appErrs.Empty() { errs = append(errs, appErrs) continue } appSet = append(appSet, appParams) } } return }
func (model Application) ToParams() (params AppParams) { params = NewAppParams(generic.NewMap(map[interface{}]interface{}{ "guid": model.Guid, "name": model.Name, "buildpack": model.BuildpackUrl, "command": model.Command, "disk_quota": model.DiskQuota, "instances": model.InstanceCount, "memory": model.Memory, "state": strings.ToUpper(model.State), "stack_guid": model.Stack.Guid, "space_guid": model.SpaceGuid, "env": generic.NewMap(model.EnvironmentVars), })) return }
func validateEnvVars(input interface{}) (errs ManifestErrors) { envVars := generic.NewMap(input) generic.Each(envVars, func(key, value interface{}) { if value == nil { errs = append(errs, errors.New(fmt.Sprintf("env var '%s' should not be null", key))) } }) return }
func TestParsingEmptyManifestDoesNotSetCommand(t *testing.T) { m, err := manifest.NewManifest(generic.NewMap(map[string]interface{}{ "applications": []interface{}{ map[string]interface{}{}, }, })) assert.NoError(t, err) assert.False(t, m.Applications[0].Has("command")) }
func manifestWithServicesAndEnv() *manifest.Manifest { return &manifest.Manifest{ Applications: []cf.AppParams{ cf.NewAppParams(generic.NewMap(map[interface{}]interface{}{ "name": "app1", "services": []string{"app1-service", "global-service"}, "env": generic.NewMap(map[string]interface{}{ "SOMETHING": "definitely-something", }), })), cf.NewAppParams(generic.NewMap(map[interface{}]interface{}{ "name": "app2", "services": []string{"app2-service", "global-service"}, "env": generic.NewMap(map[string]interface{}{ "SOMETHING": "nothing", }), })), }, } }
func TestManifestWithInheritance(t *testing.T) { repo := NewManifestDiskRepository() m, err := repo.ReadManifest("../../fixtures/inherited-manifest.yml") assert.NoError(t, err) assert.Equal(t, m.Applications[0].Get("name"), "base-app") assert.Equal(t, m.Applications[0].Get("services"), []string{"base-service"}) assert.Equal(t, m.Applications[0].Get("env"), generic.NewMap(map[string]string{ "foo": "bar", "will-be-overridden": "my-value", })) assert.Equal(t, m.Applications[1].Get("name"), "my-app") env := generic.NewMap(m.Applications[1].Get("env")) assert.Equal(t, env.Get("will-be-overridden"), "my-value") assert.Equal(t, env.Get("foo"), "bar") services := m.Applications[1].Get("services") assert.Equal(t, services, []string{"base-service", "foo-service"}) }
func testManifestWithAbsolutePathOnWindows() { m, errs := manifest.NewManifest(`C:\some\path`, generic.NewMap(map[interface{}]interface{}{ "applications": []interface{}{ map[interface{}]interface{}{ "path": `C:\another\path`, }, }, })) Expect(errs).To(BeEmpty()) Expect(*m.Applications[0].Path).To(Equal(`C:\another\path`)) }
func testManifestWithAbsolutePathOnPosix() { m, errs := manifest.NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{ "applications": []interface{}{ map[interface{}]interface{}{ "path": "/another/path-segment", }, }, })) Expect(errs).To(BeEmpty()) Expect(*m.Applications[0].Path).To(Equal("/another/path-segment")) }
func setEnvVarOrEmptyMap(appMap, yamlMap generic.Map, key string, errs *ManifestErrors) { if !yamlMap.Has(key) { appMap.Set(key, generic.NewMap()) return } envVars := yamlMap.Get(key) if !generic.IsMappable(envVars) { *errs = append(*errs, errors.New(fmt.Sprintf("Expected %s to be a set of key => value.", key))) return } merrs := validateEnvVars(envVars) if merrs != nil { *errs = append(*errs, merrs) return } appMap.Set(key, generic.NewMap(envVars)) }
func TestParsingManifestWithNullCommand(t *testing.T) { m, err := manifest.NewManifest(generic.NewMap(map[string]interface{}{ "applications": []interface{}{ map[string]interface{}{ "command": nil, }, }, })) assert.NoError(t, err) assert.Equal(t, m.Applications[0].Get("command"), "") }
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("Expected environment variable %s to have a string value, but it was a %T.", key, value)) } }) return &result default: *errs = append(*errs, errors.NewWithFmt("Expected %s to be a set of key => value, but it was a %T.", key, 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 singleAppManifest() *manifest.Manifest { return &manifest.Manifest{ Applications: []cf.AppParams{ cf.NewAppParams(generic.NewMap(map[interface{}]interface{}{ "name": "manifest-app-name", "memory": uint64(128), "instances": 1, "host": "manifest-host", "domain": "manifest-example.com", "stack": "custom-stack", "timeout": uint64(360), "buildpack": "some-buildpack", "command": `JAVA_HOME=$PWD/.openjdk JAVA_OPTS="-Xss995K" ./bin/start.sh run`, "path": "../../fixtures/example-app", "env": generic.NewMap(map[string]interface{}{ "FOO": "baz", "PATH": "/u/apps/my-app/bin", }), })), }, } }
func TestParsingManifestWithTimeoutSetsHealthCheckTimeout(t *testing.T) { m, err := manifest.NewManifest(generic.NewMap(map[string]interface{}{ "applications": []interface{}{ map[string]interface{}{ "name": "bitcoin-miner", "timeout": "360", }, }, })) assert.NoError(t, err) assert.Equal(t, m.Applications[0].Get("health_check_timeout"), 360) assert.False(t, m.Applications[0].Has("timeout")) }
func TestManifestWithInvalidMemory(t *testing.T) { _, err := manifest.NewManifest(generic.NewMap(map[string]interface{}{ "instances": "3", "memory": "512", "applications": []interface{}{ map[string]interface{}{ "name": "bitcoin-miner", }, }, })) assert.Error(t, err) assert.Contains(t, err.Error(), "memory") }
func TestParsingManifestWithPropertiesReturnsErrors(t *testing.T) { _, err := manifest.NewManifest(generic.NewMap(map[string]interface{}{ "applications": []interface{}{ map[string]interface{}{ "env": map[string]interface{}{ "bar": "many-${foo}-are-cool", }, }, }, })) assert.Error(t, err) assert.Contains(t, err.Error(), "Properties are not supported. Found property '${foo}'") }
func parseManifest(file io.Reader) (yamlMap generic.Map, err error) { yamlBytes, err := ioutil.ReadAll(file) if err != nil { return } document, err := gamble.Parse(string(yamlBytes)) if err != nil { return } yamlMap = generic.NewMap(document) return }
func (repo CloudControllerApplicationRepository) formatAppJSON(input cf.AppParams) (data string, apiResponse net.ApiResponse) { params := generic.NewMap() for _, allowedKey := range allowedAppKeys { if input.Has(allowedKey) { params.Set(allowedKey, input.Get(allowedKey)) } } if params.Has("command") && params.Get("command").(string) == "null" { params.Set("command", "") } else if params.Has("command") { params.Set("command", stringOrNull(params.Get("command"))) } if params.Has("buildpack") { params.Set("buildpack", stringOrNull(params.Get("buildpack"))) } if params.Has("stack_guid") { params.Set("stack_guid", stringOrNull(params.Get("stack_guid"))) } if params.Has("state") { params.Set("state", strings.ToUpper(params.Get("state").(string))) } if params.Has("name") { reg := regexp.MustCompile("^[0-9a-zA-Z\\-_]*$") if !reg.MatchString(params.Get("name").(string)) { apiResponse = net.NewApiResponseWithMessage("App name is invalid: name can only contain letters, numbers, underscores and hyphens") return } } vals := []string{} if !params.IsEmpty() { vals = append(vals, mapToJsonValues(params)...) } if input.Has("env") { envVars := input.Get("env").(generic.Map) if !envVars.IsEmpty() { envVal := fmt.Sprintf(`"environment_json":{%s}`, strings.Join(mapToJsonValues(envVars), ",")) vals = append(vals, envVal) } } data = fmt.Sprintf("{%s}", strings.Join(vals, ",")) return }
func setEnvVar(appMap generic.Map, env interface{}, errs *ManifestErrors) { if !generic.IsMappable(env) { *errs = append(*errs, errors.New("Expected env vars to be a set of key => value.")) return } merrs := validateEnvVars(env) if merrs != nil { *errs = append(*errs, merrs) return } appMap.Set("env", generic.NewMap(env)) }
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("Invalid manifest. Expected a map") return } return }
func TestParsingManifestWithEmptyEnvVarIsInvalid(t *testing.T) { _, err := manifest.NewManifest(generic.NewMap(map[string]interface{}{ "env": map[string]interface{}{ "bar": nil, }, "applications": []interface{}{ map[string]interface{}{ "name": "bad app", }, }, })) assert.Error(t, err) assert.Contains(t, err.Error(), "env var 'bar' should not be null") }
func TestManifestWithGlobalAndAppSpecificProperties(t *testing.T) { m, err := manifest.NewManifest(generic.NewMap(map[string]interface{}{ "instances": "3", "memory": "512M", "applications": []interface{}{ map[string]interface{}{ "name": "bitcoin-miner", }, }, })) assert.NoError(t, err) apps := m.Applications assert.Equal(t, apps[0].Get("instances"), 3) assert.Equal(t, apps[0].Get("memory").(uint64), uint64(512)) }
func mapToAppParams(yamlMap generic.Map) (appParams cf.AppParams, errs ManifestErrors) { appParams = cf.NewEmptyAppParams() errs = checkForNulls(yamlMap) if !errs.Empty() { return } for _, key := range []string{"buildpack", "command", "disk_quota", "domain", "host", "name", "path", "stack", "no-route"} { if yamlMap.Has(key) { setStringVal(appParams, key, yamlMap.Get(key), &errs) } } if yamlMap.Has("memory") { memory, err := formatters.ToMegabytes(yamlMap.Get("memory").(string)) if err != nil { errs = append(errs, errors.New(fmt.Sprintf("Unexpected value for app memory:\n%s", err.Error()))) return } appParams.Set("memory", memory) } if yamlMap.Has("timeout") { setIntVal(appParams, "health_check_timeout", yamlMap.Get("timeout"), &errs) } if yamlMap.Has("instances") { setIntVal(appParams, "instances", yamlMap.Get("instances"), &errs) } if yamlMap.Has("services") { setStringSlice(appParams, "services", yamlMap.Get("services"), &errs) } else { appParams.Set("services", []string{}) } if yamlMap.Has("env") { setEnvVar(appParams, yamlMap.Get("env"), &errs) } else { appParams.Set("env", generic.NewMap()) } return }