Skip to content

Commit

Permalink
removed resource properties from score files (#20)
Browse files Browse the repository at this point in the history
Signed-off-by: Eugene Yarshevich <yarshevich@gmail.com>
Signed-off-by: Eugene Y. <ghen@users.noreply.github.com>
Co-authored-by: Eugene Yarshevich <yarshevich@gmail.com>
Co-authored-by: Eugene Y <ghen@users.noreply.github.com>
  • Loading branch information
3 people committed Jul 5, 2023
1 parent 6943d87 commit 1ec922c
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 128 deletions.
4 changes: 0 additions & 4 deletions examples/02-environment/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ containers:
resources:
env:
type: environment
properties:
NAME:
type: string
default: World
```

If there is a need to set the `NAME` variable value for the environment the workload would be deployed into, an `env.yaml` file can be used:
Expand Down
4 changes: 0 additions & 4 deletions examples/02-environment/score.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,3 @@ containers:
resources:
env:
type: environment
properties:
NAME:
type: string
default: World
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.19
require (
github.com/imdario/mergo v0.3.13
github.com/mitchellh/mapstructure v1.5.0
github.com/score-spec/score-go v0.0.0-20230601114155-58fa99cb56f8
github.com/score-spec/score-go v0.0.0-20230615134243-75a810d22ad1
github.com/spf13/cobra v1.6.0
github.com/stretchr/testify v1.8.0
github.com/tidwall/sjson v1.2.5
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/score-spec/score-go v0.0.0-20230601114155-58fa99cb56f8 h1:gIOGix8DrqtGbEEBPimUON83Bk+AVnZRpanCKsWXa3s=
github.com/score-spec/score-go v0.0.0-20230601114155-58fa99cb56f8/go.mod h1:kqDzGrkDasa4D1A9MWgHPVPoRVa+zZgFijYOZNDLSpM=
github.com/score-spec/score-go v0.0.0-20230615134243-75a810d22ad1 h1:i/6Z1cPwKOEJp0jNK3oyh1RCWnGR1Cn4cAorRdCIe2M=
github.com/score-spec/score-go v0.0.0-20230615134243-75a810d22ad1/go.mod h1:kqDzGrkDasa4D1A9MWgHPVPoRVa+zZgFijYOZNDLSpM=
github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI=
github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
Expand Down
17 changes: 2 additions & 15 deletions internal/helm/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,25 +123,12 @@ func TestScoreConvert(t *testing.T) {
Resources: map[string]score.ResourceSpec{
"env": {
Type: "environment",
Properties: map[string]score.ResourcePropertySpec{
"DEBUG": {Default: false, Required: false},
"LOGS_LEVEL": {Default: "WARN", Required: false},
},
},
"app-db": {
Properties: map[string]score.ResourcePropertySpec{
"host": {Default: "localhost", Required: true},
"port": {Default: 5432, Required: false},
"name": {Required: true},
"user.name": {Required: true, Secret: true},
"password": {Required: true, Secret: true},
},
Type: "postgres",
},
"dns": {
Type: "dns",
Properties: map[string]score.ResourcePropertySpec{
"domain": {Required: false},
},
},
"data": {
Type: "volume",
Expand Down Expand Up @@ -173,7 +160,7 @@ func TestScoreConvert(t *testing.T) {
},
map[string]interface{}{
"name": "DEBUG",
"value": "false", // fallback to default value
"value": "", // fallback to default value
},
map[string]interface{}{
"name": "DOMAIN_NAME",
Expand Down
91 changes: 48 additions & 43 deletions internal/helm/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,22 @@ import (
"fmt"
"log"
"os"
"strings"

"github.com/mitchellh/mapstructure"

score "github.com/score-spec/score-go/types"
)

// templatesContext ia an utility type that provides a context for '${...}' templates substitution
type templatesContext map[string]string
type templatesContext struct {
meta map[string]interface{}
resources score.ResourcesSpecs
values map[string]interface{}
}

// buildContext initializes a new templatesContext instance
func buildContext(metadata score.WorkloadMeta, resources score.ResourcesSpecs, values map[string]interface{}) (templatesContext, error) {
var ctx = make(map[string]string)

func buildContext(metadata score.WorkloadMeta, resources score.ResourcesSpecs, values map[string]interface{}) (*templatesContext, error) {
var metadataMap = make(map[string]interface{})
if decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
TagName: "json",
Expand All @@ -32,51 +35,23 @@ func buildContext(metadata score.WorkloadMeta, resources score.ResourcesSpecs, v
return nil, err
} else {
decoder.Decode(metadata)
for key, val := range metadataMap {
var ref = fmt.Sprintf("metadata.%s", key)
if _, exists := ctx[ref]; exists {
return nil, fmt.Errorf("ambiguous property reference '%s'", ref)
}
ctx[ref] = fmt.Sprintf("%v", val)
}
}

for resName, res := range resources {
ctx[fmt.Sprintf("resources.%s", resName)] = resName

for propName, prop := range res.Properties {
var ref = fmt.Sprintf("resources.%s.%s", resName, propName)
if _, exists := ctx[ref]; exists {
return nil, fmt.Errorf("ambiguous property reference '%s'", ref)
}

// Use the default value provided (if any)
var val = fmt.Sprintf("%v", prop.Default)

// Override the default value for the property (if provided)
if src, ok := values[resName]; ok {
if srcMap, ok := src.(map[string]interface{}); ok {
if v, ok := srcMap[propName]; ok {
val = fmt.Sprintf("%v", v)
}
}
}

ctx[ref] = val
}
}

return ctx, nil
return &templatesContext{
meta: metadataMap,
resources: resources,
values: values,
}, nil
}

// Substitute replaces all matching '${...}' templates in a source string
func (context templatesContext) Substitute(src string) string {
return os.Expand(src, context.mapVar)
func (ctx *templatesContext) Substitute(src string) string {
return os.Expand(src, ctx.mapVar)
}

// MapVar replaces objects and properties references with corresponding values
// Returns an empty string if the reference can't be resolved
func (context templatesContext) mapVar(ref string) string {
func (ctx *templatesContext) mapVar(ref string) string {
if ref == "" {
return ""
}
Expand All @@ -90,10 +65,40 @@ func (context templatesContext) mapVar(ref string) string {
return ref
}

if res, ok := context[ref]; ok {
return res
var segments = strings.SplitN(ref, ".", 2)
switch segments[0] {
case "metadata":
if len(segments) == 2 {
if val, exists := ctx.meta[segments[1]]; exists {
return fmt.Sprintf("%v", val)
}
}

case "resources":
if len(segments) == 2 {
segments = strings.SplitN(segments[1], ".", 2)
var resName = segments[0]
if _, exists := ctx.resources[resName]; exists {
if len(segments) == 1 {
return resName
} else {
var propName = segments[1]

var val = ""
if src, ok := ctx.values[resName]; ok {
if srcMap, ok := src.(map[string]interface{}); ok {
if v, ok := srcMap[propName]; ok {
val = fmt.Sprintf("%v", v)
}
}
}

return val
}
}
}
}

log.Printf("Warning: Can not resolve '%s'. Resource or property is not declared.", ref)
log.Printf("Warning: Can not resolve '%s' reference.", ref)
return ""
}
89 changes: 30 additions & 59 deletions internal/helm/templates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,20 @@ import (
assert "github.com/stretchr/testify/assert"
)

func TestBuildContext(t *testing.T) {
func TestMapVar(t *testing.T) {
var meta = score.WorkloadMeta{
Name: "test-name",
}

var resources = score.ResourcesSpecs{
"env": score.ResourceSpec{
Type: "environment",
Properties: map[string]score.ResourcePropertySpec{
"DEBUG": {Required: false, Default: true},
},
},
"db": score.ResourceSpec{
Type: "postgres",
Properties: map[string]score.ResourcePropertySpec{
"host": {Required: true, Default: "."},
"port": {Required: true, Default: "5342"},
"name": {Required: true},
},
},
"dns": score.ResourceSpec{
Type: "dns",
Properties: map[string]score.ResourcePropertySpec{
"domain": {},
},
},
}

Expand All @@ -55,50 +44,18 @@ func TestBuildContext(t *testing.T) {
context, err := buildContext(meta, resources, values)
assert.NoError(t, err)

assert.Equal(t, templatesContext{
"metadata.name": "test-name",

"resources.env": "env",
"resources.env.DEBUG": "true",

"resources.db": "db",
"resources.db.host": "localhost",
"resources.db.port": "5342",
"resources.db.name": "test-db",

"resources.dns": "dns",
"resources.dns.domain": "test.domain.name",
}, context)
}

func TestMapVar(t *testing.T) {
var context = templatesContext{
"metadata.name": "test-name",

"resources.env": "env",
"resources.env.DEBUG": "true",

"resources.db": "db",
"resources.db.host": "localhost",
"resources.db.port": "5342",
"resources.db.name": "test-db",

"resources.dns": "shared.dns",
"resources.dns.domain": "test.domain.name",
}

assert.Equal(t, "", context.mapVar(""))
assert.Equal(t, "$", context.mapVar("$"))

assert.Equal(t, "test-name", context.mapVar("metadata.name"))
assert.Equal(t, "", context.mapVar("metadata.name.nil"))
assert.Equal(t, "", context.mapVar("metadata.nil"))

assert.Equal(t, "true", context.mapVar("resources.env.DEBUG"))
assert.Equal(t, "", context.mapVar("resources.env.DEBUG"))

assert.Equal(t, "db", context.mapVar("resources.db"))
assert.Equal(t, "localhost", context.mapVar("resources.db.host"))
assert.Equal(t, "5342", context.mapVar("resources.db.port"))
assert.Equal(t, "", context.mapVar("resources.db.port"))
assert.Equal(t, "test-db", context.mapVar("resources.db.name"))
assert.Equal(t, "", context.mapVar("resources.db.name.nil"))
assert.Equal(t, "", context.mapVar("resources.db.nil"))
Expand All @@ -107,21 +64,35 @@ func TestMapVar(t *testing.T) {
}

func TestSubstitute(t *testing.T) {
var context = templatesContext{
"metadata.name": "test-name",

"resources.env": "env",
"resources.env.DEBUG": "true",
var meta = score.WorkloadMeta{
Name: "test-name",
}

"resources.db": "db",
"resources.db.host": "localhost",
"resources.db.port": "5342",
"resources.db.name": "test-db",
var resources = score.ResourcesSpecs{
"env": score.ResourceSpec{
Type: "environment",
},
"db": score.ResourceSpec{
Type: "postgres",
},
"dns": score.ResourceSpec{
Type: "dns",
},
}

"resources.dns": "dns",
"resources.dns.domain": "test.domain.name",
var values = map[string]interface{}{
"db": map[string]interface{}{
"host": "localhost",
"name": "test-db",
},
"dns": map[string]interface{}{
"domain": "test.domain.name",
},
}

context, err := buildContext(meta, resources, values)
assert.NoError(t, err)

assert.Equal(t, "", context.Substitute(""))
assert.Equal(t, "abc", context.Substitute("abc"))
assert.Equal(t, "abc $ abc", context.Substitute("abc $$ abc"))
Expand All @@ -130,10 +101,10 @@ func TestSubstitute(t *testing.T) {
assert.Equal(t, "The name is 'test-name'", context.Substitute("The name is '${metadata.name}'"))
assert.Equal(t, "The name is ''", context.Substitute("The name is '${metadata.nil}'"))

assert.Equal(t, "resources.env.DEBUG", context.Substitute("resources.env.DEBUG"))
assert.Equal(t, "resources.badref.DEBUG", context.Substitute("resources.badref.DEBUG"))

assert.Equal(t, "db", context.Substitute("${resources.db}"))
assert.Equal(t,
"postgresql://:@localhost:5342/test-db",
"postgresql://:@localhost:/test-db",
context.Substitute("postgresql://${resources.db.user}:${resources.db.password}@${resources.db.host}:${resources.db.port}/${resources.db.name}"))
}

0 comments on commit 1ec922c

Please sign in to comment.