/
dev.go
185 lines (155 loc) · 5.57 KB
/
dev.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package cmd
import (
"fmt"
"os"
"strings"
"time"
"github.com/jumppad-labs/jumppad/cmd/view"
"github.com/jumppad-labs/jumppad/pkg/clients"
"github.com/jumppad-labs/jumppad/pkg/jumppad"
"github.com/jumppad-labs/jumppad/pkg/utils"
"github.com/spf13/cobra"
)
func newDevCmd() *cobra.Command {
var variables []string
var variablesFile string
var interval string
var ttyFlag bool
devCmd := &cobra.Command{
Use: "dev",
Short: "Watches config for changes and automatically runs `up` when a change is detected",
Long: "Watches config for changes and automatically runs `up` when a change is detected",
Example: `
jumppad dev ./
`,
Args: cobra.ArbitraryArgs,
RunE: newDevCmdFunc(&variables, &variablesFile, &interval, &ttyFlag),
SilenceUsage: true,
}
devCmd.Flags().StringSliceVarP(&variables, "var", "", nil, "Allows setting variables from the command line, variables are specified as a key and value, e.g --var key=value. Can be specified multiple times")
devCmd.Flags().StringVarP(&variablesFile, "vars-file", "", "", "Load variables from a location other than *.vars files in the blueprint folder. E.g --vars-file=./file.vars")
devCmd.Flags().StringVarP(&interval, "interval", "", "5s", "Interval to check for changes. E.g. --interval=5s")
devCmd.Flags().BoolVarP(&ttyFlag, "disable-tty", "", false, "Enable/disable output to TTY")
return devCmd
}
func newDevCmdFunc(variables *[]string, variablesFile, interval *string, ttyFlag *bool) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {
// create the output view
var v view.View
var err error
if *ttyFlag {
v, err = view.NewLogView()
if err != nil {
return fmt.Errorf("unable to create output view: %s", err)
}
} else {
v, err = view.NewTTYView()
if err != nil {
return fmt.Errorf("unable to create output view: %s", err)
}
}
engineClients, _ := clients.GenerateClients(v.Logger())
engine, _, err := createEngine(v.Logger(), engineClients)
if err != nil {
return fmt.Errorf("unable to create engine: %s", err)
}
// create the shipyard and sub folders in the users home directory
utils.CreateFolders()
d, err := time.ParseDuration(*interval)
if err != nil {
return fmt.Errorf("invalid duration %s, please specify a duration using go syntax, e.g. 5s, 1m", *interval)
}
// set the source
src := ""
if len(args) == 1 {
src = args[0]
} else {
src = "./"
}
if src == "." {
src = "./"
}
// parse the vars into a map
vars := map[string]string{}
for _, v := range *variables {
parts := strings.Split(v, "=")
if len(parts) == 2 {
vars[parts[0]] = parts[1]
}
}
if variablesFile != nil && *variablesFile != "" {
if _, err := os.Stat(*variablesFile); err != nil {
return fmt.Errorf("variables file %s, does not exist", *variablesFile)
}
} else {
vf := ""
variablesFile = &vf
}
// create the certificates for the connector
if cb, err := engineClients.Connector.GetLocalCertBundle(utils.CertsDir("")); err != nil || cb == nil {
// generate certs
v.Logger().Debug("Generating TLS Certificates for Ingress", "path", utils.CertsDir(""))
_, err := engineClients.Connector.GenerateLocalCertBundle(utils.CertsDir(""))
if err != nil {
return fmt.Errorf("unable to generate connector certificates: %s", err)
}
}
// start the connector
if !engineClients.Connector.IsRunning() {
cb, err := engineClients.Connector.GetLocalCertBundle(utils.CertsDir(""))
if err != nil {
return fmt.Errorf("unable to get certificates to secure ingress: %s", err)
}
v.Logger().Debug("Starting API server")
err = engineClients.Connector.Start(cb)
if err != nil {
return fmt.Errorf("unable to start API server: %s", err)
}
}
// start the
go doUpdates(v, engine, src, vars, *variablesFile, d)
// Show the view
err = v.Display()
if err != nil {
return err
}
return nil
}
}
func doUpdates(v view.View, e jumppad.Engine, source string, variables map[string]string, variableFile string, interval time.Duration) {
v.Logger().Debug("P_Init: Checking cmd-line parameters....................")
v.Logger().Debug("V_Init: Allocate screens................................")
v.Logger().Debug("M_LoadDefaults: Load system defaults....................")
v.Logger().Debug("Z_Init: Init zone memory allocation daemon..............")
v.Logger().Debug("DPMI Memory: 8xa11000, 8x800000 allocated...............")
v.Logger().Debug("W_Init: Init WADfiles...................................")
v.Logger().Debug("W_Init: adding doom1.wad................................")
v.Logger().Debug("W_Init: shareware version...............................")
v.Logger().Debug("startskill: 2 deathmatch: 0 startepisode: 1")
v.UpdateStatus("Checking for changes...", false)
for {
time.Sleep(interval)
new, changed, removed, _, err := e.Diff(source, variables, variableFile)
if err != nil {
v.Logger().Error(err.Error())
}
v.Logger().Debug("Changes detected", "new", len(new), "changed", len(changed), "removed", len(removed))
for _, n := range changed {
v.Logger().Debug("Changed", "resource", n.Metadata().ResourceID)
}
if len(new) > 0 || len(changed) > 0 || len(removed) > 0 {
v.UpdateStatus(
fmt.Sprintf(
"Applying changes, %d resources to add, %d resources changed, %d resources to delete, running up",
len(new),
len(changed),
len(removed),
), true)
_, err := e.ApplyWithVariables(source, variables, variableFile)
if err != nil {
v.Logger().Error(err.Error())
}
v.UpdateStatus("Checking for changes...", false)
}
}
}