Skip to content

Commit 2d9e4b2

Browse files
committed
feat(config): add typed values
1 parent 55c26f1 commit 2d9e4b2

13 files changed

Lines changed: 211 additions & 164 deletions

cmd/cmd.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ type Commander interface {
3737
CertAttach(string, string) error
3838
CertDetach(string, string) error
3939
ConfigList(string, string) error
40-
ConfigSet(string, []string) error
41-
ConfigUnset(string, []string) error
42-
ConfigPull(string, bool, bool) error
43-
ConfigPush(string, string) error
40+
ConfigSet(string, string, []string) error
41+
ConfigUnset(string, string, []string) error
42+
ConfigPull(string, string, string, bool, bool) error
43+
ConfigPush(string, string, string) error
4444
DomainsList(string, int) error
4545
DomainsAdd(string, string) error
4646
DomainsRemove(string, string) error

cmd/config.go

Lines changed: 41 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
)
1414

1515
// ConfigList lists an app's config.
16-
func (d *DryccCmd) ConfigList(appID string, format string) error {
16+
func (d *DryccCmd) ConfigList(appID string, procType string) error {
1717
s, appID, err := load(d.ConfigFile, appID)
1818
if err != nil {
1919
return err
@@ -23,35 +23,26 @@ func (d *DryccCmd) ConfigList(appID string, format string) error {
2323
return err
2424
}
2525

26-
keys := *sortKeys(config.Values)
27-
switch format {
28-
case "oneline":
29-
var kv []string
30-
for _, key := range keys {
31-
kv = append(kv, fmt.Sprintf("%s=%s", key, config.Values[key]))
32-
}
33-
d.Println(strings.Join(kv, " "))
34-
case "diff":
35-
for _, key := range keys {
36-
d.Println(fmt.Sprintf("%s=%s", key, config.Values[key]))
37-
}
38-
default:
39-
table := d.getDefaultFormatTable([]string{"UUID", "OWNER", "NAME", "VALUE"})
40-
for _, key := range keys {
41-
table.Append([]string{
42-
config.UUID,
43-
config.Owner,
44-
key,
45-
fmt.Sprintf("%v", config.Values[key]),
46-
})
47-
}
48-
table.Render()
26+
configValues := config.Values
27+
if procType != "" {
28+
configValues = config.TypedValues[procType]
29+
}
30+
31+
keys := *sortKeys(configValues)
32+
table := d.getDefaultFormatTable([]string{"NAME", "VALUE"})
33+
34+
for _, key := range keys {
35+
table.Append([]string{
36+
key,
37+
fmt.Sprintf("%v", configValues[key]),
38+
})
4939
}
40+
table.Render()
5041
return nil
5142
}
5243

5344
// ConfigSet sets an app's config variables.
54-
func (d *DryccCmd) ConfigSet(appID string, configVars []string) error {
45+
func (d *DryccCmd) ConfigSet(appID string, procType string, configVars []string) error {
5546
s, appID, err := load(d.ConfigFile, appID)
5647

5748
if err != nil {
@@ -84,8 +75,12 @@ to set up healthchecks. This functionality has been deprecated. In the future, p
8475
d.Print("Creating config... ")
8576

8677
quit := progress(d.WOut)
87-
configObj := api.Config{Values: configMap}
88-
configObj, err = config.Set(s.Client, appID, configObj)
78+
configObj, err := config.Set(s.Client, appID, func() api.Config {
79+
if procType != "" {
80+
return api.Config{TypedValues: map[string]api.ConfigValues{procType: configMap}}
81+
}
82+
return api.Config{Values: configMap}
83+
}())
8984
quit <- true
9085
<-quit
9186
if d.checkAPICompatibility(s.Client, err) != nil {
@@ -98,11 +93,11 @@ to set up healthchecks. This functionality has been deprecated. In the future, p
9893
d.Print("done\n\n")
9994
}
10095

101-
return d.ConfigList(appID, "")
96+
return d.ConfigList(appID, procType)
10297
}
10398

10499
// ConfigUnset removes a config variable from an app.
105-
func (d *DryccCmd) ConfigUnset(appID string, configVars []string) error {
100+
func (d *DryccCmd) ConfigUnset(appID string, procType string, configVars []string) error {
106101
s, appID, err := load(d.ConfigFile, appID)
107102

108103
if err != nil {
@@ -132,11 +127,11 @@ func (d *DryccCmd) ConfigUnset(appID string, configVars []string) error {
132127

133128
d.Print("done\n\n")
134129

135-
return d.ConfigList(appID, "")
130+
return d.ConfigList(appID, procType)
136131
}
137132

138133
// ConfigPull pulls an app's config to a file.
139-
func (d *DryccCmd) ConfigPull(appID string, interactive bool, overwrite bool) error {
134+
func (d *DryccCmd) ConfigPull(appID, procType, fileName string, interactive bool, overwrite bool) error {
140135
s, appID, err := load(d.ConfigFile, appID)
141136

142137
if err != nil {
@@ -153,36 +148,34 @@ func (d *DryccCmd) ConfigPull(appID string, interactive bool, overwrite bool) er
153148
if err != nil {
154149
return err
155150
}
151+
configValues := configVars.Values
152+
if procType != "" {
153+
configValues = configVars.TypedValues[procType]
154+
}
156155

157156
if (stat.Mode() & os.ModeCharDevice) == 0 {
158-
d.Print(formatConfig(configVars.Values))
157+
d.Print(formatConfig(configValues))
159158
return nil
160159
}
161160

162-
filename := ".env"
163-
164161
if !overwrite {
165-
if _, err := os.Stat(filename); err == nil {
166-
return fmt.Errorf("%s already exists, pass -o to overwrite", filename)
162+
if _, err := os.Stat(fileName); err == nil {
163+
return fmt.Errorf("%s already exists, pass -o to overwrite", fileName)
167164
}
168165
}
169166

170167
if interactive {
171-
contents, err := os.ReadFile(filename)
172-
168+
contents, err := os.ReadFile(fileName)
173169
if err != nil {
174170
return err
175171
}
176172
localConfigVars := strings.Split(string(contents), "\n")
177-
178173
configMap, err := parseConfig(localConfigVars[:len(localConfigVars)-1])
179174
if err != nil {
180175
return err
181176
}
182-
183-
for key, value := range configVars.Values {
177+
for key, value := range configValues {
184178
localValue, ok := configMap[key]
185-
186179
if ok {
187180
if value != localValue {
188181
var confirm string
@@ -198,15 +191,13 @@ func (d *DryccCmd) ConfigPull(appID string, interactive bool, overwrite bool) er
198191
configMap[key] = value
199192
}
200193
}
201-
202-
return os.WriteFile(filename, []byte(formatConfig(configMap)), 0755)
194+
return os.WriteFile(fileName, []byte(formatConfig(configMap)), 0755)
203195
}
204-
205-
return os.WriteFile(filename, []byte(formatConfig(configVars.Values)), 0755)
196+
return os.WriteFile(fileName, []byte(formatConfig(configValues)), 0755)
206197
}
207198

208199
// ConfigPush pushes an app's config from a file.
209-
func (d *DryccCmd) ConfigPush(appID, fileName string) error {
200+
func (d *DryccCmd) ConfigPush(appID, procType string, fileName string) error {
210201
stat, err := os.Stdin.Stat()
211202

212203
if err != nil {
@@ -238,11 +229,11 @@ func (d *DryccCmd) ConfigPush(appID, fileName string) error {
238229
}
239230
}
240231

241-
return d.ConfigSet(appID, config)
232+
return d.ConfigSet(appID, procType, config)
242233
}
243234

244-
func parseConfig(configVars []string) (map[string]interface{}, error) {
245-
configMap := make(map[string]interface{})
235+
func parseConfig(configVars []string) (api.ConfigValues, error) {
236+
configMap := make(api.ConfigValues)
246237

247238
regex := regexp.MustCompile(`^([A-z_]+[A-z0-9_]*)=([\s\S]*)$`)
248239
for _, config := range configVars {

cmd/config_test.go

Lines changed: 88 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ func TestParseConfig(t *testing.T) {
2020

2121
actual, err := parseConfig([]string{"FOO=bar"})
2222
assert.NoError(t, err)
23-
assert.Equal(t, actual, map[string]interface{}{"FOO": "bar"}, "map")
23+
assert.Equal(t, actual, api.ConfigValues{"FOO": "bar"}, "map")
2424

2525
actual, err = parseConfig([]string{"FOO="})
2626
assert.NoError(t, err)
27-
assert.Equal(t, actual, map[string]interface{}{"FOO": ""}, "map")
27+
assert.Equal(t, actual, api.ConfigValues{"FOO": ""}, "map")
2828
}
2929

3030
func TestParseSSHKey(t *testing.T) {
@@ -105,6 +105,11 @@ func TestConfigList(t *testing.T) {
105105
"TRUE": "false",
106106
"FLOAT": "12.34"
107107
},
108+
"typed_values": {
109+
"web": {
110+
"PORT": "9000"
111+
}
112+
},
108113
"memory": {},
109114
"cpu": {},
110115
"tags": {},
@@ -121,23 +126,20 @@ func TestConfigList(t *testing.T) {
121126
err = cmdr.ConfigList("foo", "")
122127
assert.NoError(t, err)
123128

124-
assert.Equal(t, b.String(), `UUID OWNER NAME VALUE
125-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk FLOAT 12.34
126-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk NCC 1701
127-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk TEST testing
128-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk TRUE false
129+
assert.Equal(t, b.String(), `NAME VALUE
130+
FLOAT 12.34
131+
NCC 1701
132+
TEST testing
133+
TRUE false
129134
`, "output")
130-
b.Reset()
131-
132-
err = cmdr.ConfigList("foo", "oneline")
133-
assert.NoError(t, err)
134-
assert.Equal(t, b.String(), "FLOAT=12.34 NCC=1701 TEST=testing TRUE=false\n", "output")
135135

136136
b.Reset()
137-
138-
err = cmdr.ConfigList("foo", "diff")
137+
err = cmdr.ConfigList("foo", "web")
139138
assert.NoError(t, err)
140-
assert.Equal(t, b.String(), "FLOAT=12.34\nNCC=1701\nTEST=testing\nTRUE=false\n", "output")
139+
assert.Equal(t, b.String(), `NAME VALUE
140+
PORT 9000
141+
`, "output")
142+
141143
}
142144

143145
func TestConfigSet(t *testing.T) {
@@ -182,17 +184,17 @@ func TestConfigSet(t *testing.T) {
182184
var b bytes.Buffer
183185
cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
184186

185-
err = cmdr.ConfigSet("foo", []string{"TRUE=false", "SSH_KEY=-----BEGIN OPENSSH PRIVATE KEY-----"})
187+
err = cmdr.ConfigSet("foo", "", []string{"TRUE=false", "SSH_KEY=-----BEGIN OPENSSH PRIVATE KEY-----"})
186188
assert.NoError(t, err)
187189

188190
assert.Equal(t, testutil.StripProgress(b.String()), `Creating config... done
189191
190-
UUID OWNER NAME VALUE
191-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk FLOAT 12.34
192-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk NCC 1701
193-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk SSH_KEY LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0=
194-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk TEST testing
195-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk TRUE false
192+
NAME VALUE
193+
FLOAT 12.34
194+
NCC 1701
195+
SSH_KEY LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0=
196+
TEST testing
197+
TRUE false
196198
`, "output")
197199
}
198200

@@ -236,15 +238,73 @@ func TestConfigUnset(t *testing.T) {
236238
var b bytes.Buffer
237239
cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
238240

239-
err = cmdr.ConfigUnset("foo", []string{"FOO"})
241+
err = cmdr.ConfigUnset("foo", "", []string{"FOO"})
242+
assert.NoError(t, err)
243+
244+
assert.Equal(t, testutil.StripProgress(b.String()), `Removing config... done
245+
246+
NAME VALUE
247+
FLOAT 12.34
248+
NCC 1701
249+
TEST testing
250+
TRUE false
251+
`, "output")
252+
}
253+
254+
func TestConfigUnsetTypedValues(t *testing.T) {
255+
t.Parallel()
256+
cf, server, err := testutil.NewTestServerAndClient()
257+
if err != nil {
258+
t.Fatal(err)
259+
}
260+
defer server.Close()
261+
262+
server.Mux.HandleFunc("/v2/apps/foo/config/", func(w http.ResponseWriter, r *http.Request) {
263+
testutil.SetHeaders(w)
264+
if r.Method == "POST" {
265+
testutil.AssertBody(t, api.Config{
266+
Values: map[string]interface{}{
267+
"FOO": nil,
268+
},
269+
}, r)
270+
}
271+
272+
fmt.Fprintf(w, `{
273+
"owner": "jkirk",
274+
"app": "foo",
275+
"values": {
276+
"RELEASE_VERSION": "v1"
277+
},
278+
"typed_values": {
279+
"web": {
280+
"TEST": "testing",
281+
"NCC": "1701",
282+
"TRUE": "false",
283+
"FLOAT": "12.34"
284+
}
285+
},
286+
"memory": {},
287+
"cpu": {},
288+
"tags": {},
289+
"registry": {},
290+
"created": "2014-01-01T00:00:00UTC",
291+
"updated": "2014-01-01T00:00:00UTC",
292+
"uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
293+
}`)
294+
})
295+
296+
var b bytes.Buffer
297+
cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
298+
299+
err = cmdr.ConfigUnset("foo", "web", []string{"FOO"})
240300
assert.NoError(t, err)
241301

242302
assert.Equal(t, testutil.StripProgress(b.String()), `Removing config... done
243303
244-
UUID OWNER NAME VALUE
245-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk FLOAT 12.34
246-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk NCC 1701
247-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk TEST testing
248-
de1bf5b5-4a72-4f94-a10c-d2a3741cdf75 jkirk TRUE false
304+
NAME VALUE
305+
FLOAT 12.34
306+
NCC 1701
307+
TEST testing
308+
TRUE false
249309
`, "output")
250310
}

cmd/registry.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,9 @@ func (d *DryccCmd) RegistryList(appID string) error {
2323
if len(config.Registry) == 0 {
2424
d.Println(fmt.Sprintf("No registrys found in %s app.", appID))
2525
} else {
26-
table := d.getDefaultFormatTable([]string{"UUID", "OWNER", "KEY", "VALUE"})
26+
table := d.getDefaultFormatTable([]string{"KEY", "VALUE"})
2727
for _, key := range *sortKeys(config.Registry) {
2828
table.Append([]string{
29-
config.UUID,
30-
config.Owner,
3129
key,
3230
fmt.Sprintf("%v", config.Registry[key]),
3331
})

0 commit comments

Comments
 (0)