Skip to content

Commit

Permalink
add support stack global options for templates
Browse files Browse the repository at this point in the history
  • Loading branch information
speier committed Dec 12, 2024
1 parent 619c958 commit bfa3776
Show file tree
Hide file tree
Showing 22 changed files with 1,457 additions and 50 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION=v0.2.3
VERSION=v0.2.4

tag:
@git tag -a ${VERSION} -m "version ${VERSION}" && git push origin ${VERSION}
74 changes: 69 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,80 @@ go build

## Usage

```bash
```
comet [command] [flags]
```

For detailed command documentation, use:
```bash
```
comet --help
```

## Commands

### `comet version`

**Description:** Print the version.

**Usage:**
```
comet version
```

### `comet plan`

**Description:** Show changes required by the current configuration.

**Usage:**
```
comet plan <stack> [component]
```

### `comet output`

**Description:** Show output values from components.

**Usage:**
```
comet output <stack> [component]
```

### `comet list`

**Description:** List stacks or components.

**Usage:**
```
comet list [stack]
```

### `comet destroy`

**Description:** Destroy previously-created infrastructure.

**Usage:**
```
comet destroy <stack> [component]
```

### `comet clean`

**Description:** Delete Terraform-related folders and files.

**Usage:**
```
comet clean <stack> [component]
```

### `comet apply`

**Description:** Create or update infrastructure.

**Usage:**
```
comet apply <stack> [component]
```

## Configuration

Comet can be configured using `comet.yaml` in your project directory.
Expand All @@ -51,12 +116,11 @@ Comet can be configured using `comet.yaml` in your project directory.
### Setup

1. Clone the repository
```bash
```
git clone https://github.com/moonwalker/comet.git
```

2. Build the project
```bash
```
go build
```

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/moonwalker/comet
go 1.23

require (
dario.cat/mergo v1.0.1
github.com/1password/onepassword-sdk-go v0.1.5
github.com/arsham/figurine v1.3.0
github.com/bmatcuk/doublestar/v4 v4.7.1
Expand Down
6 changes: 3 additions & 3 deletions internal/exec/tf/tfexec.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (e *executor) Plan(component *schema.Component) (bool, error) {
return false, err
}

planfile := fmt.Sprintf(planFileFmt, component.Stack.Name, component.Name)
planfile := fmt.Sprintf(planFileFmt, component.Stack, component.Name)
return tf.Plan(context.Background(), tfexec.VarFile(varsfile), tfexec.Out(planfile))
}

Expand Down Expand Up @@ -143,7 +143,7 @@ func (e *executor) Output(component *schema.Component) (map[string]*schema.Outpu
// utils

func prepareProvision(component *schema.Component, generateBackend bool) (string, error) {
varsfile := fmt.Sprintf(varsFileFmt, component.Stack.Name, component.Name)
varsfile := fmt.Sprintf(varsFileFmt, component.Stack, component.Name)
err := writeJSON(component.Inputs, component.Path, varsfile)
if err != nil {
return "", err
Expand Down Expand Up @@ -237,7 +237,7 @@ func writeProvidersTF(component *schema.Component) error {
sb.WriteString("}\n\n")
}

for _, line := range component.Stack.Appends["providers"] {
for _, line := range component.Appends["providers"] {
sb.WriteString(line)
sb.WriteString("\n")
}
Expand Down
7 changes: 4 additions & 3 deletions internal/parser/js/js.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,11 @@ func (vm *jsinterpreter) secretsFunc(ref string) any {
return res
}

func (vm *jsinterpreter) registerStack(stack *schema.Stack) func(string) goja.Value {
return func(name string) goja.Value {
log.Debug("register stack", "name", name)
func (vm *jsinterpreter) registerStack(stack *schema.Stack) func(string, map[string]interface{}) goja.Value {
return func(name string, options map[string]interface{}) goja.Value {
log.Debug("register stack", "name", name, "options", options)
stack.Name = name
stack.Options = options
return vm.rt.ToValue(stack)
}
}
Expand Down
38 changes: 29 additions & 9 deletions internal/schema/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ import (
"fmt"
"path"

"dario.cat/mergo"
cp "github.com/otiai10/copy"
)

type (
Component struct {
Stack *Stack `json:"stack"`
Stack string `json:"stack"`
Backend Backend `json:"backend"`
Appends map[string][]string `json:"appends"`
Name string `json:"name"`
Path string `json:"path"`
Backend Backend `json:"backend"`
Inputs map[string]interface{} `json:"inputs"`
Providers map[string]interface{} `json:"providers"`
}
Expand All @@ -21,7 +23,7 @@ type (
// copy component to workdir if needed
func (c *Component) EnsurePath(config *Config) error {
if len(config.WorkDir) > 0 {
dest := path.Join(config.WorkDir, c.Stack.Name, c.Name)
dest := path.Join(config.WorkDir, c.Stack, c.Name)
err := cp.Copy(c.Path, dest)
if err != nil {
return err
Expand All @@ -34,25 +36,43 @@ func (c *Component) EnsurePath(config *Config) error {

// property ref template to resolve later
func (c *Component) PropertyRef(property string) string {
return fmt.Sprintf(`{{ (state "%s" "%s").%s }}`, c.Stack.Name, c.Name, property)
return fmt.Sprintf(`{{ (state "%s" "%s").%s }}`, c.Stack, c.Name, property)
}

// resolve templates in component
func (c *Component) ResolveVars(stacks *Stacks, executor Executor) error {
tdata := map[string]interface{}{"stack": c.Stack.Name, "component": c.Name}
stack, err := stacks.GetStack(c.Stack)
if err != nil {
return err
}

tdata := map[string]interface{}{"stack": stack.Name, "component": c.Name}
err = mergo.Merge(&tdata, stack.Options)
if err != nil {
return err
}

funcMap := map[string]interface{}{
"state": stateFunc(stacks, executor),
}

// set backend from stack's backend template
c.Backend.Config = tpl(c.Stack.Backend.Config, tdata, funcMap)
// template backend
c.Backend.Config, err = tpl(c.Backend.Config, tdata, funcMap)
if err != nil {
return err
}

// template vars
c.Inputs = tpl(c.Inputs, tdata, funcMap)
c.Inputs, err = tpl(c.Inputs, tdata, funcMap)
if err != nil {
return err
}

// template providers
c.Providers = tpl(c.Providers, tdata, funcMap)
c.Providers, err = tpl(c.Providers, tdata, funcMap)
if err != nil {
return err
}

return nil
}
Expand Down
10 changes: 6 additions & 4 deletions internal/schema/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ type (
Path string `json:"path"`
Type string `json:"type"`
Name string `json:"name"`
Options any `json:"options"`
Backend Backend `json:"backend"`
Components []*Component `json:"components"`
Appends map[string][]string `json:"appends"`
Components []*Component `json:"components"`
}

Stacks struct {
Expand All @@ -32,8 +33,8 @@ func NewStack(path string, t string) *Stack {
return &Stack{
Path: path,
Type: t,
Components: make([]*Component, 0),
Appends: make(map[string][]string, 0),
Components: make([]*Component, 0),
}
}

Expand All @@ -43,10 +44,11 @@ func (s *Stack) Valid() bool {

func (s *Stack) AddComponent(name, path string, inputs map[string]interface{}, providers map[string]interface{}) *Component {
c := &Component{
Stack: s,
Stack: s.Name,
Backend: s.Backend,
Appends: s.Appends,
Name: name,
Path: path,
Backend: s.Backend,
Inputs: inputs,
Providers: providers,
}
Expand Down
17 changes: 6 additions & 11 deletions internal/schema/tpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ import (
"encoding/json"
"strings"
"text/template"

"github.com/moonwalker/comet/internal/log"
)

func tpl(v any, data any, funcMap map[string]any) map[string]interface{} {
func tpl(v any, data any, funcMap map[string]any) (map[string]interface{}, error) {
res := make(map[string]interface{})

jb, err := json.Marshal(v)
if err != nil {
log.Error("template json marshal failed", "error", err)
return res
return nil, err
}

// remove escaped quotes
Expand All @@ -24,21 +21,19 @@ func tpl(v any, data any, funcMap map[string]any) map[string]interface{} {
t := template.New("t").Funcs(funcMap)
tmpl, err := t.Parse(js)
if err != nil {
log.Error("template parse failed", "error", err)
return res
return nil, err
}

var b bytes.Buffer
err = tmpl.Execute(&b, data)
if err != nil {
log.Error("template execute failed", "error", err)
return res
return nil, err
}

err = json.Unmarshal(b.Bytes(), &res)
if err != nil {
log.Error("template json unmarshal failed", "error", err)
return nil, err
}

return res
return res, nil
}
15 changes: 1 addition & 14 deletions stacks/dev.stack.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const opts = {
common_name: 'comet'
}

const stage = stack('dev')
const stage = stack('dev', { opts })

backend('gcs', {
bucket: 'mw-tf-state',
Expand Down Expand Up @@ -43,19 +43,6 @@ const helm = {
}

const metsrv = component('metsrv', 'test/modules/kubernetes', {
inputs: {
values: {
sources: ['ingress', 'gateway-httproute'],
provider: 'cloudflare',
extraArgs: ['--cloudflare-proxied', '123 foo', '456 bar', 'baz'],
env: [
{
name: 'CF_API_TOKEN',
value: env.COMET_TEST
}
]
}
},
providers: {
// google: {},
kubernetes: k8s,
Expand Down
12 changes: 12 additions & 0 deletions vendor/dario.cat/mergo/.deepsource.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version = 1

test_patterns = [
"*_test.go"
]

[[analyzers]]
name = "go"
enabled = true

[analyzers.meta]
import_path = "dario.cat/mergo"
36 changes: 36 additions & 0 deletions vendor/dario.cat/mergo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#### joe made this: http://goel.io/joe

#### go ####
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Golang/Intellij
.idea

# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/

#### vim ####
# Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]

# Session
Session.vim

# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
Loading

0 comments on commit bfa3776

Please sign in to comment.