Skip to content

Commit

Permalink
Merge pull request #128 from b4nst/feat/support-yaml-bundle-files
Browse files Browse the repository at this point in the history
feat: add YAML and JSON support for bundles
  • Loading branch information
stefanprodan authored Jul 7, 2023
2 parents 097fc24 + 6c51f9e commit 30b3bb4
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 27 deletions.
56 changes: 41 additions & 15 deletions cmd/timoni/bundle_build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,47 +31,73 @@ func Test_BundleBuild(t *testing.T) {
))
g.Expect(err).ToNot(HaveOccurred())

bundleData := fmt.Sprintf(`
bundleCue := fmt.Sprintf(`
appName: string @timoni(env:string:TEST_BBUILD_NAME)
bundle: {
apiVersion: "v1alpha1"
name: "%[1]s"
name: string
instances: {
"\(appName)": {
module: {
url: "oci://%[2]s"
version: "%[3]s"
url: "oci://%[1]s"
version: "%[2]s"
}
namespace: "%[4]s"
namespace: "%[3]s"
values: server: enabled: false
values: domain: string @timoni(env:string:TEST_BBUILD_HOST)
}
backend: {
module: {
url: "oci://%[2]s"
version: "%[3]s"
url: "oci://%[1]s"
version: "%[2]s"
}
namespace: "%[4]s"
namespace: string
values: client: enabled: bool @timoni(env:bool:TEST_BBUILD_ENABLED)
}
}
}
`, bundleName, modURL, modVer, namespace)
`, modURL, modVer, namespace)

bundlePath := filepath.Join(t.TempDir(), "bundle.cue")
err = os.WriteFile(bundlePath, []byte(bundleData), 0644)
g.Expect(err).ToNot(HaveOccurred())
bundleData := bundleCue + fmt.Sprintf(`
bundle: name: "%[1]s"
bundle: instances: backend: namespace: "%[2]s"
`, bundleName, namespace)

bundleJson := fmt.Sprintf(`
{
"bundle": {
"name": "%[1]s"
}
}
`, bundleName)

bundleYaml := fmt.Sprintf(`
bundle:
instances:
backend:
namespace: %[1]s
`, namespace)

wd := t.TempDir()
cuePath := filepath.Join(wd, "bundle.cue")
g.Expect(os.WriteFile(cuePath, []byte(bundleCue), 0644)).ToNot(HaveOccurred())

yamlPath := filepath.Join(wd, "bundle.yaml")
g.Expect(os.WriteFile(yamlPath, []byte(bundleYaml), 0644)).ToNot(HaveOccurred())

jsonPath := filepath.Join(wd, "bundle.json")
g.Expect(os.WriteFile(jsonPath, []byte(bundleJson), 0644)).ToNot(HaveOccurred())

t.Setenv("TEST_BBUILD_NAME", "frontend")
t.Setenv("TEST_BBUILD_HOST", "my.host")
t.Setenv("TEST_BBUILD_ENABLED", "false")

t.Run("builds instances from bundle", func(t *testing.T) {
execCommands := map[string]func() (string, error){
"using a file": func() (string, error) {
"using files": func() (string, error) {
return executeCommand(fmt.Sprintf(
"bundle build -f %s -p main",
bundlePath,
"bundle build -f %s -f %s -f %s -p main",
cuePath, yamlPath, jsonPath,
))
},
"using stdin": func() (string, error) {
Expand Down
45 changes: 34 additions & 11 deletions internal/engine/bundle_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ import (
"path/filepath"

"cuelang.org/go/cue"
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/cuecontext"
"cuelang.org/go/cue/load"
cp "github.com/otiai10/copy"
"cuelang.org/go/cue/parser"
"cuelang.org/go/encoding/json"
"cuelang.org/go/encoding/yaml"

apiv1 "github.com/stefanprodan/timoni/api/v1alpha1"
)
Expand Down Expand Up @@ -69,23 +72,43 @@ func (b *BundleBuilder) InitWorkspace(workspace string) error {
var files []string
for i, file := range b.files {
_, fn := filepath.Split(file)
dstFile := filepath.Join(workspace, fmt.Sprintf("%v.%s", i, fn))
files = append(files, dstFile)
if err := cp.Copy(file, dstFile); err != nil {
return err
content, err := os.ReadFile(file)
if err != nil {
return fmt.Errorf("failed to read %s: %w", fn, err)
}
}

for _, f := range files {
_, fn := filepath.Split(f)
data, err := b.injector.Inject(f)
var parsefn func(string, []byte) (ast.Node, error)
switch ext := filepath.Ext(fn); ext {
case ".yaml", ".yml":
parsefn = func(filename string, src []byte) (ast.Node, error) { return yaml.Extract(filename, src) }
case ".json":
parsefn = func(filename string, src []byte) (ast.Node, error) { return json.Extract(filename, src) }
case ".cue":
parsefn = func(filename string, src []byte) (ast.Node, error) {
return parser.ParseFile(filename, src, parser.ParseComments)
}
default:
parsefn = func(filename string, src []byte) (ast.Node, error) {
return nil, fmt.Errorf("unsupported file extension: %s", ext)
}
}

node, err := parsefn(fn, content)
if err != nil {
return fmt.Errorf("failed to inject %s: %w", fn, err)
return fmt.Errorf("failed to parse %s: %w", fn, err)
}

if err := os.WriteFile(f, data, os.ModePerm); err != nil {
data, err := b.injector.InjectNode(node)
if err != nil {
return fmt.Errorf("failed to inject %s: %w", fn, err)
}

dstFile := filepath.Join(workspace, fmt.Sprintf("%v.%s.cue", i, fn))
if err := os.WriteFile(dstFile, data, os.ModePerm); err != nil {
return fmt.Errorf("failed to write %s: %w", fn, err)
}

files = append(files, dstFile)
}

schemaFile := filepath.Join(workspace, fmt.Sprintf("%v.schema.cue", len(b.files)+1))
Expand Down
6 changes: 5 additions & 1 deletion internal/engine/injector.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ func (in *Injector) Inject(src string) ([]byte, error) {
return nil, err
}

return in.InjectNode(tree)
}

func (in *Injector) InjectNode(tree ast.Node) ([]byte, error) {
output, err := in.injectFromEnv(tree)
if err != nil {
return nil, err
Expand All @@ -67,7 +71,7 @@ func (in *Injector) Inject(src string) ([]byte, error) {
return data, nil
}

func (in *Injector) injectFromEnv(tree *ast.File) (ast.Node, error) {
func (in *Injector) injectFromEnv(tree ast.Node) (ast.Node, error) {
var re error
f := func(c astutil.Cursor) bool {
n := c.Node()
Expand Down

0 comments on commit 30b3bb4

Please sign in to comment.