Skip to content

Commit 9521a92

Browse files
committed
feat: variant export go SRC_DIR DST_DIR for building single executable binary of your command
1 parent 4bcd96a commit 9521a92

File tree

6 files changed

+156
-19
lines changed

6 files changed

+156
-19
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ jobs:
2323
which kubectl
2424
sudo apt-get update -y
2525
sudo apt-get install ruby -y
26-
make test
26+
make test smoke

Makefile

+8
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,11 @@ lint: bin/golangci-lint
2525
--disable gochecknoglobals \
2626
--disable gochecknoinits \
2727
--disable gomnd,funlen,prealloc,gocritic,lll,gocognit
28+
29+
.PHONY: smoke
30+
smoke: build
31+
make build
32+
./variant export go examples/simple build/simple
33+
go build -o build/simple/simple ./build/simple
34+
build/simple/simple -h | tee smoke.log
35+
grep "Namespace to interact with" smoke.log

export_go.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package variant
2+
3+
import (
4+
"github.com/spf13/cobra"
5+
)
6+
7+
func newExportGo(r *Runner) *cobra.Command {
8+
return &cobra.Command{
9+
Use: "go SRC_DIR DST_DIR",
10+
Short: "Copy and generate DST_DIR/main.go for building the single executable binary with `go build DST_DIR`",
11+
Example: `$ variant export go examples/simple build
12+
13+
$ go build -o build/simple ./build
14+
15+
$ build/simple -h
16+
17+
$ build/simple app deploy -n default
18+
`,
19+
Args: cobra.ExactArgs(2),
20+
RunE: func(c *cobra.Command, args []string) error {
21+
err := r.ap.ExportGo(args[0], args[1])
22+
if err != nil {
23+
c.SilenceUsage = true
24+
}
25+
return err
26+
},
27+
}
28+
}

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ require (
1717
github.com/variantdev/vals v0.0.0-20191123083656-fc61ba6e8746
1818
github.com/zclconf/go-cty v1.2.0
1919
github.com/zclconf/go-cty-yaml v1.0.1
20+
golang.org/x/tools v0.0.0-20191026034945-b2104f82a97d
2021
gopkg.in/yaml.v2 v2.2.2
2122
gopkg.in/yaml.v3 v3.0.0-20190924164351-c8b7dadae555
2223
)

pkg/app/app_shim.go

+93-6
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,85 @@ import (
66
"io/ioutil"
77
"os"
88
"path/filepath"
9+
"strings"
910

1011
"github.com/hashicorp/hcl/v2"
1112

1213
"github.com/mumoshu/variant2/pkg/conf"
1314
)
1415

16+
func (app *App) ExportGo(srcDir, dstDir string) error {
17+
if err := os.MkdirAll(dstDir, 0755); err != nil {
18+
return err
19+
}
20+
21+
files, _, err := newConfigFromDir(srcDir)
22+
if err != nil {
23+
return err
24+
}
25+
26+
merged, err := merge(files)
27+
if err != nil {
28+
return err
29+
}
30+
31+
backquote := "<<<backquote>>>"
32+
33+
code := []byte(fmt.Sprintf(`package main
34+
35+
import (
36+
"errors"
37+
"os"
38+
"path/filepath"
39+
"strings"
40+
41+
variant "github.com/mumoshu/variant2"
42+
)
43+
44+
func main() {
45+
source := strings.Replace(%s, "`+backquote+`", "`+"`"+`", -1)
46+
47+
var args []string
48+
49+
if len(os.Args) > 1 {
50+
args = os.Args[1:]
51+
}
52+
53+
bin := filepath.Base(os.Args[0])
54+
55+
err := variant.MustEval(bin, source).Run(args)
56+
57+
var verr variant.Error
58+
59+
var code int
60+
61+
if err != nil {
62+
if ok := errors.As(err, &verr); ok {
63+
code = verr.ExitCode
64+
} else {
65+
code = 1
66+
}
67+
} else {
68+
code = 0
69+
}
70+
71+
os.Exit(code)
72+
}
73+
`, "`"+strings.Replace(string(merged)+"\n", "`", backquote, -1)+"`"))
74+
75+
if err := os.MkdirAll(dstDir, 0755); err != nil {
76+
return err
77+
}
78+
79+
exportDir := filepath.Join(dstDir, "main.go")
80+
81+
if err := ioutil.WriteFile(exportDir, code, 0644); err != nil {
82+
return err
83+
}
84+
85+
return nil
86+
}
87+
1588
func (app *App) ExportShim(srcDir, dstDir string) error {
1689
if err := os.MkdirAll(dstDir, 0755); err != nil {
1790
return err
@@ -32,20 +105,34 @@ func (app *App) ExportShim(srcDir, dstDir string) error {
32105
return exportWithShim(binName, files, dstDir)
33106
}
34107

108+
func merge(files map[string]*hcl.File) ([]byte, error) {
109+
buf := bytes.Buffer{}
110+
111+
for _, file := range files {
112+
if _, err := buf.Write(file.Bytes); err != nil {
113+
return nil, err
114+
}
115+
116+
if _, err := buf.Write([]byte("\n")); err != nil {
117+
return nil, err
118+
}
119+
}
120+
121+
return buf.Bytes(), nil
122+
}
123+
35124
func exportWithShim(variantBin string, files map[string]*hcl.File, dstDir string) error {
36125
binName := filepath.Base(dstDir)
37126

38127
binPath := filepath.Join(dstDir, binName)
39128
cfgPath := filepath.Join(dstDir, binName+conf.VariantFileExt)
40129

41-
buf := bytes.Buffer{}
42-
43-
for _, file := range files {
44-
buf.Write(file.Bytes)
45-
buf.Write([]byte("\n"))
130+
bs, err := merge(files)
131+
if err != nil {
132+
return err
46133
}
47134

48-
if err := ioutil.WriteFile(cfgPath, buf.Bytes(), 0644); err != nil {
135+
if err := ioutil.WriteFile(cfgPath, bs, 0644); err != nil {
49136
return err
50137
}
51138

variant.go

+25-12
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,14 @@ func (r Runner) Job(job string, opts State) (JobRun, error) {
642642
return nil, fmt.Errorf("job %q not added", job)
643643
}
644644

645+
if opts.Options == nil {
646+
opts.Options = map[string]interface{}{}
647+
}
648+
649+
if opts.Parameters == nil {
650+
opts.Parameters = map[string]interface{}{}
651+
}
652+
645653
jr := f(opts)
646654

647655
return jr, nil
@@ -740,19 +748,23 @@ func (r *Runner) createVariantRootCommand() *cobra.Command {
740748
Use: "export SUBCOMMAND SRC_DIR OUTPUT_PATH",
741749
Short: "Export the Variant command defined in SRC_DIR to OUTPUT_PATH",
742750
}
743-
shimCmd := &cobra.Command{
744-
Use: "shim SRC_DIR DST_DIR",
745-
Short: "Copy and generate shim for the Variant command defined in the SRC",
746-
Args: cobra.ExactArgs(2),
747-
RunE: func(c *cobra.Command, args []string) error {
748-
err := r.ap.ExportShim(args[0], args[1])
749-
if err != nil {
750-
c.SilenceUsage = true
751-
}
752-
return err
753-
},
751+
{
752+
shimCmd := &cobra.Command{
753+
Use: "shim SRC_DIR DST_DIR",
754+
Short: "Copy and generate shim for the Variant command defined in the SRC",
755+
Args: cobra.ExactArgs(2),
756+
RunE: func(c *cobra.Command, args []string) error {
757+
err := r.ap.ExportShim(args[0], args[1])
758+
if err != nil {
759+
c.SilenceUsage = true
760+
}
761+
return err
762+
},
763+
}
764+
765+
exportCmd.AddCommand(shimCmd)
766+
exportCmd.AddCommand(newExportGo(r))
754767
}
755-
exportCmd.AddCommand(shimCmd)
756768

757769
generateCmd := &cobra.Command{
758770
Use: "generate RESOURCE DIR",
@@ -771,6 +783,7 @@ func (r *Runner) createVariantRootCommand() *cobra.Command {
771783
return err
772784
},
773785
}
786+
774787
generateCmd.AddCommand(generateShimCmd)
775788
}
776789

0 commit comments

Comments
 (0)