diff --git a/go.mod b/go.mod index 657e6ea..fcc5c56 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,12 @@ module github.com/score-spec/score-humanitec -go 1.19 +go 1.21 require ( github.com/golang/mock v1.6.0 github.com/imdario/mergo v0.3.13 github.com/mitchellh/mapstructure v1.5.0 - github.com/score-spec/score-go v0.0.0-20231024094556-308a07ae2536 + github.com/score-spec/score-go v1.1.0 github.com/sendgrid/rest v2.6.9+incompatible github.com/spf13/cobra v1.6.0 github.com/stretchr/testify v1.8.1 diff --git a/go.sum b/go.sum index 81cffba..b48f664 100644 --- a/go.sum +++ b/go.sum @@ -15,12 +15,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= -github.com/score-spec/score-go v0.0.0-20230905115428-131acdd2f5cf h1:0Dt+qyYoGTXPPU5Xq/KxLDtQMMA8hX+oJ8EsjFWUajQ= -github.com/score-spec/score-go v0.0.0-20230905115428-131acdd2f5cf/go.mod h1:3l9mvrtYKzxXDQVcYkQBD3ABTPkTzWhUMYNfGlpctoo= -github.com/score-spec/score-go v0.0.0-20231024093959-ed5a5d548352 h1:yycML7iVHv/65wo4ao7uH5cvIYgQhB184iKAy7suNBk= -github.com/score-spec/score-go v0.0.0-20231024093959-ed5a5d548352/go.mod h1:3l9mvrtYKzxXDQVcYkQBD3ABTPkTzWhUMYNfGlpctoo= -github.com/score-spec/score-go v0.0.0-20231024094556-308a07ae2536 h1:WBWWWSbAR2oJapUZyCm4IZ5LJfkT5IUlHtmcJNBLFiY= -github.com/score-spec/score-go v0.0.0-20231024094556-308a07ae2536/go.mod h1:3l9mvrtYKzxXDQVcYkQBD3ABTPkTzWhUMYNfGlpctoo= +github.com/score-spec/score-go v1.1.0 h1:63WM1u93NtGgMuPtVZ/UBfzg/BpYuY8sBquaL0BkrXU= +github.com/score-spec/score-go v1.1.0/go.mod h1:nt6TOq2Ld9SiH3Fd9NF8tiJ9L7S17OE3FNgCrSet5GQ= github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekueiEMJ7NEoxJo0= github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE= github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= diff --git a/internal/command/run.go b/internal/command/run.go index 77efd99..a687a41 100644 --- a/internal/command/run.go +++ b/internal/command/run.go @@ -18,11 +18,12 @@ import ( "github.com/imdario/mergo" "github.com/mitchellh/mapstructure" - "github.com/score-spec/score-humanitec/internal/humanitec" - "github.com/score-spec/score-humanitec/internal/humanitec/extensions" "github.com/spf13/cobra" "github.com/tidwall/sjson" + "github.com/score-spec/score-humanitec/internal/humanitec" + "github.com/score-spec/score-humanitec/internal/humanitec/extensions" + yaml "gopkg.in/yaml.v3" loader "github.com/score-spec/score-go/loader" @@ -86,7 +87,7 @@ func run(cmd *cobra.Command, args []string) error { return nil } -func loadSpec(scoreFile, overridesFile, extensionsFile string, skipValidation bool) (*score.WorkloadSpec, *extensions.HumanitecExtensionsSpec, error) { +func loadSpec(scoreFile, overridesFile, extensionsFile string, skipValidation bool) (*score.Workload, *extensions.HumanitecExtensionsSpec, error) { // Open source file // log.Printf("Reading '%s'...\n", scoreFile) @@ -188,6 +189,15 @@ func loadSpec(scoreFile, overridesFile, extensionsFile string, skipValidation bo } } + // Apply upgrades to fix backports or backward incompatible things + if changes, err := schema.ApplyCommonUpgradeTransforms(srcMap); err != nil { + return nil, nil, fmt.Errorf("failed to upgrade spec: %w", err) + } else if len(changes) > 0 { + for _, change := range changes { + log.Printf("Applying upgrade to specification: %s\n", change) + } + } + // Validate SCORE spec // if !skipValidation { @@ -200,7 +210,7 @@ func loadSpec(scoreFile, overridesFile, extensionsFile string, skipValidation bo // Convert SCORE spec // - var spec score.WorkloadSpec + var spec score.Workload log.Print("Applying SCORE spec...\n") if err = mapstructure.Decode(srcMap, &spec); err != nil { return nil, nil, fmt.Errorf("applying workload spec: %w", err) diff --git a/internal/humanitec/convert.go b/internal/humanitec/convert.go index 26b5687..e4307e7 100644 --- a/internal/humanitec/convert.go +++ b/internal/humanitec/convert.go @@ -16,6 +16,7 @@ import ( mergo "github.com/imdario/mergo" score "github.com/score-spec/score-go/types" + extensions "github.com/score-spec/score-humanitec/internal/humanitec/extensions" humanitec "github.com/score-spec/score-humanitec/internal/humanitec_go/types" ) @@ -64,21 +65,23 @@ func parseResourceId(ref string) (workload, scope, resId string, err error) { // getProbeDetails extracts an httpGet probe details from the source spec. // Returns nil if the source spec is empty. -func getProbeDetails(probe *score.ContainerProbeSpec) map[string]interface{} { - if probe.HTTPGet.Path == "" { +func getProbeDetails(probe *score.ContainerProbe) map[string]interface{} { + if probe.HttpGet.Path == "" { return nil } var res = map[string]interface{}{ "type": "http", - "path": probe.HTTPGet.Path, - "port": probe.HTTPGet.Port, + "path": probe.HttpGet.Path, + "port": probe.HttpGet.Port, } - if len(probe.HTTPGet.HTTPHeaders) > 0 { + if len(probe.HttpGet.HttpHeaders) > 0 { var hdrs = map[string]string{} - for _, hdr := range probe.HTTPGet.HTTPHeaders { - hdrs[hdr.Name] = hdr.Value + for _, hdr := range probe.HttpGet.HttpHeaders { + if hdr.Name != nil && hdr.Value != nil { + hdrs[*hdr.Name] = *hdr.Value + } } res["headers"] = hdrs } @@ -123,20 +126,22 @@ func mergeFileContent(content interface{}, target string) (string, error) { } // convertFileMountSpec extracts a mount file details from the source spec. -func convertFileMountSpec(f *score.FileMountSpec, context *templatesContext, baseDir string) (string, map[string]interface{}, error) { +func convertFileMountSpec(f *score.ContainerFilesElem, context *templatesContext, baseDir string) (string, map[string]interface{}, error) { var err error var content string - if f.Source != "" { - content, err = readFile(baseDir, f.Source) + if f.Source != nil { + content, err = readFile(baseDir, *f.Source) + } else if f.Content != nil { + content, err = mergeFileContent(*f.Content, f.Target) } else { - content, err = mergeFileContent(f.Content, f.Target) + err = fmt.Errorf("file is missing source or content") } if err != nil { return "", nil, err } - if f.NoExpand { + if f.NoExpand != nil && *f.NoExpand { content = context.Escape(content) } else { content = context.Substitute(content) @@ -144,14 +149,14 @@ func convertFileMountSpec(f *score.FileMountSpec, context *templatesContext, bas return f.Target, map[string]interface{}{ - "mode": f.Mode, + "mode": DerefOr(f.Mode, ""), "value": content, }, nil } // convertContainerSpec extracts a container details from the source spec. -func convertContainerSpec(name string, spec *score.ContainerSpec, context *templatesContext, baseDir string) (map[string]interface{}, error) { +func convertContainerSpec(name string, spec *score.Container, context *templatesContext, baseDir string) (map[string]interface{}, error) { var containerSpec = map[string]interface{}{ "id": name, } @@ -171,17 +176,27 @@ func convertContainerSpec(name string, spec *score.ContainerSpec, context *templ } containerSpec["variables"] = envVars } - if len(spec.Resources.Requests) > 0 || len(spec.Resources.Limits) > 0 { - containerSpec["resources"] = map[string]interface{}{ - "requests": spec.Resources.Requests, - "limits": spec.Resources.Limits, + if spec.Resources != nil { + containerResources := make(map[string]interface{}) + if out := getContainerResources(spec.Resources.Limits); len(out) > 0 { + containerResources["limits"] = out + } + if out := getContainerResources(spec.Resources.Requests); len(out) > 0 { + containerResources["requests"] = out + } + if len(containerResources) > 0 { + containerSpec["resources"] = containerResources } } - if probe := getProbeDetails(&spec.LivenessProbe); len(probe) > 0 { - containerSpec["liveness_probe"] = probe + if spec.LivenessProbe != nil { + if probe := getProbeDetails(spec.LivenessProbe); len(probe) > 0 { + containerSpec["liveness_probe"] = probe + } } - if probe := getProbeDetails(&spec.ReadinessProbe); len(probe) > 0 { - containerSpec["readiness_probe"] = probe + if spec.ReadinessProbe != nil { + if probe := getProbeDetails(spec.ReadinessProbe); len(probe) > 0 { + containerSpec["readiness_probe"] = probe + } } if len(spec.Files) > 0 { var files = map[string]interface{}{} @@ -199,8 +214,8 @@ func convertContainerSpec(name string, spec *score.ContainerSpec, context *templ for _, vol := range spec.Volumes { volumes[vol.Target] = map[string]interface{}{ "id": context.Substitute(vol.Source), - "sub_path": vol.Path, - "read_only": vol.ReadOnly, + "sub_path": DerefOr(vol.Path, ""), + "read_only": DerefOr(vol.ReadOnly, false), } } containerSpec["volume_mounts"] = volumes @@ -209,8 +224,19 @@ func convertContainerSpec(name string, spec *score.ContainerSpec, context *templ return containerSpec, nil } +func getContainerResources(requests *score.ResourcesLimits) map[string]interface{} { + out := make(map[string]interface{}) + if requests.Cpu != nil { + out["cpu"] = *requests.Cpu + } + if requests.Memory != nil { + out["memory"] = *requests.Memory + } + return out +} + // ConvertSpec converts SCORE specification into Humanitec deployment delta. -func ConvertSpec(name, envID, baseDir, workloadSourceURL string, spec *score.WorkloadSpec, ext *extensions.HumanitecExtensionsSpec) (*humanitec.CreateDeploymentDeltaRequest, error) { +func ConvertSpec(name, envID, baseDir, workloadSourceURL string, spec *score.Workload, ext *extensions.HumanitecExtensionsSpec) (*humanitec.CreateDeploymentDeltaRequest, error) { ctx, err := buildContext(spec.Metadata, spec.Resources, ext.Resources) if err != nil { return nil, fmt.Errorf("preparing context: %w", err) @@ -235,21 +261,13 @@ func ConvertSpec(name, envID, baseDir, workloadSourceURL string, spec *score.Wor "annotations": annotations, "containers": containers, } - if len(spec.Service.Ports) > 0 { + if spec.Service != nil && len(spec.Service.Ports) > 0 { var ports = map[string]interface{}{} for pName, pSpec := range spec.Service.Ports { - var proto = pSpec.Protocol - if proto == "" { - proto = "TCP" // Defaults to "TCP" - } - var targetPport = pSpec.TargetPort - if targetPport == 0 { - targetPport = pSpec.Port // Defaults to the published port - } ports[pName] = map[string]interface{}{ - "protocol": proto, + "protocol": string(DerefOr(pSpec.Protocol, score.ServicePortProtocolTCP)), "service_port": pSpec.Port, - "container_port": targetPport, + "container_port": DerefOr(pSpec.TargetPort, pSpec.Port), } } workloadSpec["service"] = map[string]interface{}{ @@ -283,7 +301,8 @@ func ConvertSpec(name, envID, baseDir, workloadSourceURL string, spec *score.Wor continue default: - resId, hasAnnotation := res.Metadata.Annotations[AnnotationLabelResourceId] + resAnnotations, _ := res.Metadata["annotations"].(map[string]interface{}) + resId, hasAnnotation := resAnnotations[AnnotationLabelResourceId].(string) if resId == "" { resId = fmt.Sprintf("externals.%s", name) } @@ -298,13 +317,10 @@ func ConvertSpec(name, envID, baseDir, workloadSourceURL string, spec *score.Wor } } // END (DEPRECATED) - var class = "default" - if res.Class != "" { - class = res.Class - } + var class = DerefOr(res.Class, "default") if mod, scope, resName, err := parseResourceId(resId); err != nil { log.Printf("Warning: %v.\n", err) - } else if mod == "" || mod == spec.Metadata.Name { + } else if mod == "" || mod == spec.Metadata["name"].(string) { if scope == "externals" { var extRes = map[string]interface{}{ "type": res.Type, @@ -349,7 +365,7 @@ func ConvertSpec(name, envID, baseDir, workloadSourceURL string, spec *score.Wor }, Modules: humanitec.ModuleDeltas{ Add: map[string]map[string]interface{}{ - spec.Metadata.Name: workload, + spec.Metadata["name"].(string): workload, }, }, } diff --git a/internal/humanitec/convert_test.go b/internal/humanitec/convert_test.go index 7305445..ba0fba2 100644 --- a/internal/humanitec/convert_test.go +++ b/internal/humanitec/convert_test.go @@ -12,9 +12,10 @@ import ( "testing" score "github.com/score-spec/score-go/types" + "github.com/stretchr/testify/assert" + "github.com/score-spec/score-humanitec/internal/humanitec/extensions" humanitec "github.com/score-spec/score-humanitec/internal/humanitec_go/types" - "github.com/stretchr/testify/assert" ) func TestParseResourceId(t *testing.T) { @@ -105,7 +106,7 @@ func TestScoreConvert(t *testing.T) { var tests = []struct { Name string - Source *score.WorkloadSpec + Source *score.Workload Extensions *extensions.HumanitecExtensionsSpec Output *humanitec.CreateDeploymentDeltaRequest WorkloadSourceURL string @@ -113,23 +114,23 @@ func TestScoreConvert(t *testing.T) { }{ { Name: "Should convert SCORE to deployment delta", - Source: &score.WorkloadSpec{ - Metadata: score.WorkloadMeta{ - Name: "backend", + Source: &score.Workload{ + Metadata: score.WorkloadMetadata{ + "name": "backend", }, - Service: score.ServiceSpec{ - Ports: score.ServicePortsSpecs{ - "www": score.ServicePortSpec{ + Service: &score.WorkloadService{ + Ports: score.WorkloadServicePorts{ + "www": score.ServicePort{ Port: 80, - TargetPort: 8080, + TargetPort: Ref(8080), }, - "admin": score.ServicePortSpec{ + "admin": score.ServicePort{ Port: 8080, }, }, }, - Containers: score.ContainersSpecs{ - "backend": score.ContainerSpec{ + Containers: score.WorkloadContainers{ + "backend": score.Container{ Image: "busybox", Command: []string{ "/bin/sh", @@ -141,28 +142,28 @@ func TestScoreConvert(t *testing.T) { Variables: map[string]string{ "CONNECTION_STRING": "test connection string", }, - Resources: score.ContainerResourcesRequirementsSpec{ - Limits: map[string]interface{}{ - "memory": "128Mi", - "cpu": "500m", + Resources: &score.ContainerResources{ + Limits: &score.ResourcesLimits{ + Memory: Ref("128Mi"), + Cpu: Ref("500m"), }, - Requests: map[string]interface{}{ - "memory": "64Mi", - "cpu": "250m", + Requests: &score.ResourcesLimits{ + Memory: Ref("64Mi"), + Cpu: Ref("250m"), }, }, - LivenessProbe: score.ContainerProbeSpec{ - HTTPGet: score.HTTPGetActionSpec{ + LivenessProbe: &score.ContainerProbe{ + HttpGet: score.HttpProbe{ Path: "/alive", Port: 8080, }, }, - ReadinessProbe: score.ContainerProbeSpec{ - HTTPGet: score.HTTPGetActionSpec{ + ReadinessProbe: &score.ContainerProbe{ + HttpGet: score.HttpProbe{ Path: "/health", Port: 8080, - HTTPHeaders: []score.HTTPHeaderSpec{ - {Name: "Custom-Header", Value: "Ops!"}, + HttpHeaders: []score.HttpProbeHttpHeadersElem{ + {Name: Ref("Custom-Header"), Value: Ref("Ops!")}, }, }, }, @@ -242,12 +243,12 @@ func TestScoreConvert(t *testing.T) { }, { Name: "Should convert all resources references", - Source: &score.WorkloadSpec{ - Metadata: score.WorkloadMeta{ - Name: "test", + Source: &score.Workload{ + Metadata: score.WorkloadMetadata{ + "name": "test", }, - Containers: score.ContainersSpecs{ - "backend": score.ContainerSpec{ + Containers: score.WorkloadContainers{ + "backend": score.Container{ Variables: map[string]string{ "DEBUG": "${resources.env.DEBUG}", "LOGS_LEVEL": "${pod.debug.level}", @@ -257,42 +258,41 @@ func TestScoreConvert(t *testing.T) { "EXTERNAL_RESOURCE": "${resources.external-resource.name}", "SENSITIVE_BUCKET": "${resources.sensitive-bucket.name}", }, - Files: []score.FileMountSpec{ + Files: []score.ContainerFilesElem{ { Target: "/etc/backend/config.yaml", - Mode: "666", - Content: []interface{}{ - "---", - "DEBUG: ${resources.env.DEBUG}", - }, + Mode: Ref("666"), + Content: Ref(`--- +DEBUG: ${resources.env.DEBUG} +`), }, { Target: "/etc/backend/config.yml", - Mode: "666", - Content: "DEBUG: ${resources.env.DEBUG}", - NoExpand: true, + Mode: Ref("666"), + Content: Ref("DEBUG: ${resources.env.DEBUG}"), + NoExpand: Ref(true), }, { Target: "/etc/backend/config.txt", - Mode: "666", - Source: "testdata/config.txt", - NoExpand: true, + Mode: Ref("666"), + Source: Ref("testdata/config.txt"), + NoExpand: Ref(true), }, }, - Volumes: []score.VolumeMountSpec{ + Volumes: []score.ContainerVolumesElem{ { Source: "${resources.data}", - Path: "sub/path", + Path: Ref("sub/path"), Target: "/mnt/data", - ReadOnly: true, + ReadOnly: Ref(true), }, }, }, }, - Resources: map[string]score.ResourceSpec{ + Resources: map[string]score.Resource{ "env": { - Metadata: score.ResourceMeta{ - Annotations: map[string]string{ + Metadata: score.ResourceMetadata{ + "annotations": map[string]interface{}{ AnnotationLabelResourceId: "externals.should-ignore-this-one", }, }, @@ -308,13 +308,13 @@ func TestScoreConvert(t *testing.T) { Type: "volume", }, "db": { - Metadata: score.ResourceMeta{ - Annotations: map[string]string{ + Metadata: score.ResourceMetadata{ + "annotations": map[string]interface{}{ AnnotationLabelResourceId: "externals.annotations-db-id", }, }, Type: "postgres", - Class: "large", + Class: Ref("large"), Params: map[string]interface{}{ "extensions": map[string]interface{}{ "uuid-ossp": map[string]interface{}{ @@ -328,8 +328,8 @@ func TestScoreConvert(t *testing.T) { Type: "service", }, "external-resource": { - Metadata: score.ResourceMeta{ - Annotations: map[string]string{ + Metadata: score.ResourceMetadata{ + "annotations": map[string]interface{}{ AnnotationLabelResourceId: "modules.test-module.externals.test-resource", }, }, @@ -342,13 +342,13 @@ func TestScoreConvert(t *testing.T) { }, }, "sensitive-bucket": { - Metadata: score.ResourceMeta{ - Annotations: map[string]string{ + Metadata: score.ResourceMetadata{ + "annotations": map[string]interface{}{ AnnotationLabelResourceId: "shared.sensitive-bucket", }, }, Type: "bucket", - Class: "sensitive", + Class: Ref("sensitive"), }, }, }, @@ -407,7 +407,7 @@ func TestScoreConvert(t *testing.T) { "files": map[string]interface{}{ "/etc/backend/config.yaml": map[string]interface{}{ "mode": "666", - "value": "---\nDEBUG: ${values.DEBUG}", + "value": "---\nDEBUG: ${values.DEBUG}\n", }, "/etc/backend/config.yml": map[string]interface{}{ "mode": "666", diff --git a/internal/humanitec/ref.go b/internal/humanitec/ref.go new file mode 100644 index 0000000..529585f --- /dev/null +++ b/internal/humanitec/ref.go @@ -0,0 +1,12 @@ +package humanitec + +func Ref[k any](input k) *k { + return &input +} + +func DerefOr[k any](input *k, def k) k { + if input == nil { + return def + } + return *input +} diff --git a/internal/humanitec/templates.go b/internal/humanitec/templates.go index d5a3244..890e2c1 100644 --- a/internal/humanitec/templates.go +++ b/internal/humanitec/templates.go @@ -16,6 +16,7 @@ import ( "github.com/mitchellh/mapstructure" score "github.com/score-spec/score-go/types" + extensions "github.com/score-spec/score-humanitec/internal/humanitec/extensions" ) @@ -26,12 +27,12 @@ var ( // templatesContext ia an utility type that provides a context for '${...}' templates substitution type templatesContext struct { meta map[string]interface{} - resources score.ResourcesSpecs + resources score.WorkloadResources extensions extensions.HumanitecResourcesSpecs } // buildContext initializes a new templatesContext instance -func buildContext(metadata score.WorkloadMeta, resources score.ResourcesSpecs, ext extensions.HumanitecResourcesSpecs) (*templatesContext, error) { +func buildContext(metadata score.WorkloadMetadata, resources score.WorkloadResources, ext extensions.HumanitecResourcesSpecs) (*templatesContext, error) { var metadataMap = make(map[string]interface{}) if decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ TagName: "json", @@ -141,7 +142,8 @@ func (ctx *templatesContext) mapVar(ref string) string { if res.Type == "workload" { log.Println("Warning: 'workload' is a reserved resource type. Its usage may lead to compatibility issues with future releases of this application.") } - resId, hasAnnotation := res.Metadata.Annotations[AnnotationLabelResourceId] + resAnnotations, _ := res.Metadata["annotations"].(map[string]interface{}) + resId, hasAnnotation := resAnnotations[AnnotationLabelResourceId].(string) // DEPRECATED: Should use resource annotations instead if resExt, hasMeta := ctx.extensions[resName]; hasMeta && !hasAnnotation { if resExt.Scope == "" || resExt.Scope == "external" { @@ -152,8 +154,8 @@ func (ctx *templatesContext) mapVar(ref string) string { } // END (DEPRECATED) - if hasAnnotation && strings.HasPrefix(resId, "shared.") && (res.Class != "" && res.Class != "default") { - resId = resId + "-class-" + res.Class + if hasAnnotation && strings.HasPrefix(resId, "shared.") && (res.Class != nil && *res.Class != "" && *res.Class != "default") { + resId = resId + "-class-" + *res.Class } if resId != "" { diff --git a/internal/humanitec/templates_test.go b/internal/humanitec/templates_test.go index f425d25..eb74c74 100644 --- a/internal/humanitec/templates_test.go +++ b/internal/humanitec/templates_test.go @@ -17,21 +17,21 @@ import ( ) func TestMapVar(t *testing.T) { - var meta = score.WorkloadMeta{ - Name: "test-name", + var meta = score.WorkloadMetadata{ + "name": "test-name", } - var resources = score.ResourcesSpecs{ - "env": score.ResourceSpec{ + var resources = score.WorkloadResources{ + "env": score.Resource{ Type: "environment", }, - "db": score.ResourceSpec{ + "db": score.Resource{ Type: "postgres", }, - "dns": score.ResourceSpec{ + "dns": score.Resource{ Type: "dns", }, - "service-a": score.ResourceSpec{ + "service-a": score.Resource{ Type: "service", }, } @@ -65,21 +65,21 @@ func TestMapVar(t *testing.T) { } func TestEscape(t *testing.T) { - var meta = score.WorkloadMeta{ - Name: "test-name", + var meta = score.WorkloadMetadata{ + "name": "test-name", } - var resources = score.ResourcesSpecs{ - "env": score.ResourceSpec{ + var resources = score.WorkloadResources{ + "env": score.Resource{ Type: "environment", }, - "db": score.ResourceSpec{ + "db": score.Resource{ Type: "postgres", }, - "dns": score.ResourceSpec{ + "dns": score.Resource{ Type: "dns", }, - "service-a": score.ResourceSpec{ + "service-a": score.Resource{ Type: "service", }, } @@ -109,36 +109,36 @@ func TestEscape(t *testing.T) { } func TestSubstitute(t *testing.T) { - var meta = score.WorkloadMeta{ - Name: "test-name", + var meta = score.WorkloadMetadata{ + "name": "test-name", } - var resources = score.ResourcesSpecs{ - "env": score.ResourceSpec{ + var resources = score.WorkloadResources{ + "env": score.Resource{ Type: "environment", }, - "db": score.ResourceSpec{ + "db": score.Resource{ Type: "postgres", }, - "dns": score.ResourceSpec{ + "dns": score.Resource{ Type: "dns", }, - "service-a": score.ResourceSpec{ + "service-a": score.Resource{ Type: "service", }, - "shared-res": score.ResourceSpec{ + "shared-res": score.Resource{ Type: "s3", - Metadata: score.ResourceMeta{ - Annotations: map[string]string{ + Metadata: score.ResourceMetadata{ + "annotations": map[string]interface{}{ AnnotationLabelResourceId: "shared.main-s3", }, }, }, - "shared-res-admin": score.ResourceSpec{ + "shared-res-admin": score.Resource{ Type: "s3", - Class: "admin", - Metadata: score.ResourceMeta{ - Annotations: map[string]string{ + Class: Ref("admin"), + Metadata: score.ResourceMetadata{ + "annotations": map[string]interface{}{ AnnotationLabelResourceId: "shared.main-s3", }, }, @@ -173,21 +173,21 @@ func TestSubstitute(t *testing.T) { } func TestSubstituteAll(t *testing.T) { - var meta = score.WorkloadMeta{ - Name: "test-name", + var meta = score.WorkloadMetadata{ + "name": "test-name", } - var resources = score.ResourcesSpecs{ - "env": score.ResourceSpec{ + var resources = score.WorkloadResources{ + "env": score.Resource{ Type: "environment", }, - "db": score.ResourceSpec{ + "db": score.Resource{ Type: "postgres", }, - "dns": score.ResourceSpec{ + "dns": score.Resource{ Type: "dns", }, - "service-a": score.ResourceSpec{ + "service-a": score.Resource{ Type: "service", }, }