Skip to content

Commit 16d828d

Browse files
committed
refactor: match implementation of dokku_config from ansible modules
1 parent d174a63 commit 16d828d

1 file changed

Lines changed: 98 additions & 45 deletions

File tree

tasks/config_task.go

Lines changed: 98 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,105 @@ package tasks
22

33
import (
44
"encoding/base64"
5+
"encoding/json"
56
"fmt"
67
"omakase/subprocess"
78
)
89

910
type ConfigTask struct {
10-
App string `required:"true" yaml:"app"`
11-
Key string `required:"true" yaml:"key"`
12-
Value string `required:"true" yaml:"value"`
13-
State string `required:"true" yaml:"state" default:"present"`
11+
App string `required:"true" yaml:"app"`
12+
Restart bool `yaml:"restart" default:"true"`
13+
Config map[string]string `yaml:"config"`
14+
State string `required:"true" yaml:"state" default:"present"`
1415
}
1516

1617
func (t ConfigTask) DesiredState() string {
1718
return t.State
1819
}
1920

2021
func (t ConfigTask) Execute() TaskOutputState {
21-
funcMap := map[string]func(string, string, string) TaskOutputState{
22+
funcMap := map[string]func(ConfigTask) TaskOutputState{
2223
"present": setConfig,
2324
"absent": unsetConfig,
2425
}
2526

2627
fn := funcMap[t.State]
27-
return fn(t.App, t.Key, t.Value)
28+
return fn(t)
2829
}
2930

30-
func getConfig(app string, key string) (string, bool) {
31+
func getConfig(t ConfigTask) (map[string]string, error) {
32+
var config map[string]string
3133
result, err := subprocess.CallExecCommand(subprocess.ExecCommandInput{
3234
Command: "dokku",
3335
Args: []string{
3436
"--quiet",
35-
"config:get",
36-
app,
37-
key,
37+
"config:export",
38+
"--format",
39+
"json",
40+
t.App,
3841
},
3942
WorkingDirectory: "/tmp",
4043
})
4144
if err != nil {
42-
return "", false
45+
return config, err
4346
}
44-
return result.StdoutContents(), true
45-
}
4647

47-
func setConfig(app, key, value string) TaskOutputState {
48-
currentValue, ok := getConfig(app, key)
49-
if ok && currentValue == value {
50-
return TaskOutputState{
51-
Changed: false,
52-
State: "present",
53-
}
48+
err = json.Unmarshal(result.StdoutBytes(), &config)
49+
if err != nil {
50+
return config, err
5451
}
52+
return config, nil
53+
}
5554

55+
func setConfig(t ConfigTask) TaskOutputState {
5656
state := TaskOutputState{
5757
Changed: false,
5858
State: "absent",
5959
}
6060

61-
// todo: rename no-restart to skip-deploy
62-
base64Value := base64.StdEncoding.EncodeToString([]byte(value))
61+
currentConfig, err := getConfig(t)
62+
if err != nil {
63+
state.Error = err
64+
state.Message = err.Error()
65+
return state
66+
}
67+
68+
desiredConfig := make(map[string]string)
69+
for key, value := range t.Config {
70+
if _, ok := currentConfig[key]; !ok {
71+
desiredConfig[key] = value
72+
continue
73+
}
74+
if currentConfig[key] != value {
75+
desiredConfig[key] = value
76+
}
77+
}
78+
79+
if len(desiredConfig) == 0 {
80+
state.State = "present"
81+
return state
82+
}
83+
84+
args := []string{
85+
"--quiet",
86+
"config:set",
87+
"--encoded",
88+
}
89+
90+
if !t.Restart {
91+
// todo: rename no-restart to skip-deploy in dokku
92+
args = append(args, "--no-restart")
93+
}
94+
95+
args = append(args, t.App)
96+
97+
for key, value := range desiredConfig {
98+
args = append(args, fmt.Sprintf("%s=%s", key, base64.StdEncoding.EncodeToString([]byte(value))))
99+
}
100+
63101
result, err := subprocess.CallExecCommand(subprocess.ExecCommandInput{
64102
Command: "dokku",
65-
Args: []string{
66-
"--quiet",
67-
"config:set",
68-
"--encoded",
69-
"--no-restart",
70-
app,
71-
fmt.Sprintf("%s=%s", key, base64Value),
72-
},
103+
Args: args,
73104
})
74105
if err != nil {
75106
state.Error = err
@@ -82,28 +113,50 @@ func setConfig(app, key, value string) TaskOutputState {
82113
return state
83114
}
84115

85-
func unsetConfig(app, key, value string) TaskOutputState {
86-
if _, ok := getConfig(app, key); !ok {
87-
return TaskOutputState{
88-
Changed: false,
89-
State: "absent",
90-
}
91-
}
92-
116+
func unsetConfig(t ConfigTask) TaskOutputState {
93117
state := TaskOutputState{
94118
Changed: false,
95119
State: "present",
96120
}
121+
currentConfig, err := getConfig(t)
122+
if err != nil {
123+
state.Error = err
124+
state.Message = err.Error()
125+
return state
126+
}
127+
128+
desiredConfig := make(map[string]bool)
129+
for key := range t.Config {
130+
if _, ok := currentConfig[key]; ok {
131+
desiredConfig[key] = true
132+
}
133+
}
134+
135+
if len(desiredConfig) == 0 {
136+
state.State = "absent"
137+
return state
138+
}
139+
140+
args := []string{
141+
"--quiet",
142+
"config:unset",
143+
t.App,
144+
}
145+
146+
if !t.Restart {
147+
// todo: rename no-restart to skip-deploy in dokku
148+
args = append(args, "--no-restart")
149+
}
150+
151+
args = append(args, t.App)
152+
153+
for key := range desiredConfig {
154+
args = append(args, key)
155+
}
97156

98157
result, err := subprocess.CallExecCommand(subprocess.ExecCommandInput{
99158
Command: "dokku",
100-
Args: []string{
101-
"--quiet",
102-
"config:unset",
103-
"--no-restart",
104-
app,
105-
key,
106-
},
159+
Args: args,
107160
})
108161
if err != nil {
109162
state.Error = err

0 commit comments

Comments
 (0)