@@ -2,74 +2,105 @@ package tasks
22
33import (
44 "encoding/base64"
5+ "encoding/json"
56 "fmt"
67 "omakase/subprocess"
78)
89
910type 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
1617func (t ConfigTask ) DesiredState () string {
1718 return t .State
1819}
1920
2021func (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