Skip to content

Commit

Permalink
feat(cmd): Add build Command to CLI Tool (#252)
Browse files Browse the repository at this point in the history
  • Loading branch information
jshlbrd authored Oct 7, 2024
1 parent 6cae3cd commit 5ffe528
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 4 deletions.
105 changes: 105 additions & 0 deletions cmd/substation/build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package main

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

"github.com/spf13/cobra"
)

func init() {
rootCmd.AddCommand(buildCmd)
buildCmd.PersistentFlags().BoolP("recursive", "R", false, "recursively build all files")
buildCmd.PersistentFlags().StringToString("ext-str", nil, "set external variables")
}

var buildCmd = &cobra.Command{
Use: "build [path]",
Short: "build configs",
Long: `'substation build' compiles configuration files.
The 'recursive' flag can be used to build all files in a directory,
and the current directory is used if no arg is provided.`,
Example: ` substation build [-R]
substation build [-R] /path/to/configs
substation build config.jsonnet
`,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
// Default to current directory if no path is provided
path := "."
if len(args) > 0 {
path = args[0]
}

// Catches an edge case where the user is looking for help.
if path == "help" {
fmt.Printf("warning: %q matched no files\n", path)
return nil
}

m, err := cmd.PersistentFlags().GetStringToString("ext-str")
if err != nil {
return err
}

r, err := cmd.Flags().GetBool("recursive")
if err != nil {
return err
}

return buildPath(path, m, r)
},
}

func buildPath(arg string, extVars map[string]string, recursive bool) error {
// Handle cases where the path is a file.
//
// Only `.jsonnet` files are built.
if filepath.Ext(arg) == ".jsonnet" {
return buildFile(arg, extVars)
}

if err := filepath.WalkDir(arg, func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
}

if d.IsDir() {
if !recursive && path != arg {
return filepath.SkipDir
}

return nil
}

// Only `.jsonnet` files are built.
if filepath.Ext(path) != ".jsonnet" {
return nil
}

return buildFile(path, extVars)
}); err != nil {
return err
}

return nil
}

func buildFile(arg string, extVars map[string]string) error {
mem, err := compileFile(arg, extVars)
if err != nil {
return err
}

dir, fname := pathVars(arg)
if err := os.WriteFile(filepath.Join(dir, fname)+".json", []byte(mem), 0o644); err != nil {
return err
}

// Print the file that was built.
fmt.Println(arg)

return nil
}
15 changes: 13 additions & 2 deletions cmd/substation/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package main

import (
"os"
"path/filepath"
"strings"

"github.com/google/go-jsonnet"
"github.com/spf13/cobra"
Expand All @@ -27,8 +29,8 @@ func init() {
})
}

// buildFile returns JSON from a Jsonnet file.
func buildFile(f string, extVars map[string]string) (string, error) {
// compileFile returns JSON from a Jsonnet file.
func compileFile(f string, extVars map[string]string) (string, error) {
vm := jsonnet.MakeVM()
for k, v := range extVars {
vm.ExtVar(k, v)
Expand All @@ -42,6 +44,15 @@ func buildFile(f string, extVars map[string]string) (string, error) {
return res, nil
}

// pathVars returns the directory and file name of a file path.
func pathVars(p string) (string, string) {
dir, fn := filepath.Split(p)
ext := filepath.Ext(fn)
fn = strings.TrimSuffix(fn, ext)

return dir, fn
}

func main() {
err := rootCmd.Execute()
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions cmd/substation/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ production resources, such as any enrichment or send transforms.
}

// If the Jsonnet cannot compile, then the file is invalid.
mem, err := buildFile(arg, m)
mem, err := compileFile(arg, m)
if err != nil {
fmt.Printf("?\t%s\t[config error]\n", arg)

Expand Down Expand Up @@ -332,7 +332,7 @@ production resources, such as any enrichment or send transforms.
}

// If the Jsonnet cannot compile, then the file is invalid.
mem, err := buildFile(entry, m)
mem, err := compileFile(entry, m)
if err != nil {
fmt.Printf("?\t%s\t[config error]\n", entry)

Expand Down

0 comments on commit 5ffe528

Please sign in to comment.