Skip to content

Commit

Permalink
feat: function to normalize the spec
Browse files Browse the repository at this point in the history
Signed-off-by: Johannes Würbach <[email protected]>
  • Loading branch information
johanneswuerbach committed Mar 20, 2024
1 parent b611331 commit 2f2e139
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 18 deletions.
39 changes: 21 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Reference library for the parsing and loading SCORE files in Go.
This can be added to your project via:

```sh
$ go get -u github.com/score-spec/score-go@latest
go get -u github.com/score-spec/score-go@latest
```

**NOTE**: if you project is still using the hand-written types, you will need to stay on `github.com/score-spec/[email protected]`
Expand All @@ -17,58 +17,61 @@ This library includes a few utility methods to parse source SCORE files.

```go
import (
"io"
"os"

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

func main() {
var (
err error
src io.Reader
)
src, err := os.Open("score.yaml")
if err != nil {
panic(err)
}
defer src.Close()

if src, err = os.Open("score.yaml"); err != nil {
var srcMap map[string]interface{}
if err := loader.ParseYAML(&srcMap, src); err != nil {
panic(err)
}
defer src.Close()

var srcMap map[string]interface{}
if err = loader.ParseYAML(&srcMap, src); err != nil {
if err := schema.Validate(srcMap); err != nil {
panic(err)
}

var spec score.Workload
if err := loader.MapSpec(&spec, srcMap); err != nil {
panic(err)
}

var spec score.WorkloadSpec
if err = loader.MapSpec(&spec, srcMap); err != nil {
if err := loader.Normalize(&spec, "."); err != nil {
panic(err)
}

// Do something with the spec
// ...
}

```

## Upgrading the schema version

When the Score JSON schema is updated in https://github.com/score-spec/schema, this repo should be updated to match.
When the Score JSON schema is updated in <https://github.com/score-spec/schema>, this repo should be updated to match.

First update the subtree:

```
```sh
make update-schema
```

Then regenerate the defined types:

```
```sh
make generate
```

And ensure the tests still pass:

```
```sh
go test -v ./...
```
1 change: 1 addition & 0 deletions loader/fixtures/test_file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello World
43 changes: 43 additions & 0 deletions loader/normalize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package loader

import (
"fmt"
"os"
"path/filepath"

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

// Normalize normalizes the target Workload by:
// * embedding container file sources as content
func Normalize(w *types.Workload, baseDir string) error {
for name, c := range w.Containers {
for i, f := range c.Files {
if f.Source != nil {
raw, err := readFile(baseDir, *f.Source)
if err != nil {
return fmt.Errorf("embedding file '%s' for container '%s': %w", *f.Source, name, err)
}

c.Files[i].Source = nil
c.Files[i].Content = &raw
}
}
}

return nil
}

// readFile reads a text file into memory
func readFile(baseDir, path string) (string, error) {
if !filepath.IsAbs(path) {
path = filepath.Join(baseDir, path)
}

raw, err := os.ReadFile(path)
if err != nil {
return "", err
}

return string(raw), nil
}
94 changes: 94 additions & 0 deletions loader/normalize_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package loader

import (
"errors"
"io"
"testing"

"github.com/score-spec/score-go/types"
"github.com/stretchr/testify/assert"
)

func TestNormalize(t *testing.T) {
var tests = []struct {
Name string
Source io.Reader
Input *types.Workload
Output *types.Workload
Error error
}{
{
Name: "Embeds source file",
Input: &types.Workload{
ApiVersion: "score.dev/v1b1",
Metadata: types.WorkloadMetadata{
"name": "hello-world",
},
Containers: types.WorkloadContainers{
"hello": types.Container{
Files: []types.ContainerFilesElem{
{
Source: stringRef("./test_file.txt"),
Target: "/etc/hello-world/config.yaml",
Mode: stringRef("666"),
NoExpand: boolRef(true),
},
},
},
},
},
Output: &types.Workload{
ApiVersion: "score.dev/v1b1",
Metadata: types.WorkloadMetadata{
"name": "hello-world",
},
Containers: types.WorkloadContainers{
"hello": types.Container{
Files: []types.ContainerFilesElem{
{
Target: "/etc/hello-world/config.yaml",
Mode: stringRef("666"),
Content: stringRef("Hello World\n"),
NoExpand: boolRef(true),
},
},
},
},
},
},
{
Name: "Errors when the source file does not exist",
Input: &types.Workload{
ApiVersion: "score.dev/v1b1",
Metadata: types.WorkloadMetadata{
"name": "hello-world",
},
Containers: types.WorkloadContainers{
"hello": types.Container{
Files: []types.ContainerFilesElem{
{
Source: stringRef("./not_existing.txt"),
Target: "/etc/hello-world/config.yaml",
Mode: stringRef("666"),
NoExpand: boolRef(true),
},
},
},
},
},
Error: errors.New("embedding file './not_existing.txt' for container 'hello': open fixtures/not_existing.txt: no such file or directory"),
},
}

for _, tt := range tests {
t.Run(tt.Name, func(t *testing.T) {
var err = Normalize(tt.Input, "./fixtures")
if tt.Error != nil {
assert.EqualError(t, err, tt.Error.Error())
} else {
assert.NoError(t, err)
assert.Equal(t, tt.Output, tt.Input)
}
})
}
}

0 comments on commit 2f2e139

Please sign in to comment.