Skip to content

Commit a00e8f8

Browse files
committed
feat(lifecycle): add lifecycle support
1 parent 60c0d49 commit a00e8f8

20 files changed

Lines changed: 2169 additions & 1078 deletions

File tree

cmd/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func NewDryccCommand() *cobra.Command {
4949
rootCmd.AddCommand(parser.NewDomainsCommand(&cmdr))
5050
rootCmd.AddCommand(parser.NewGatewaysCommand(&cmdr))
5151
rootCmd.AddCommand(parser.NewGitCommand(&cmdr))
52+
rootCmd.AddCommand(parser.NewLifecyclesCommand(&cmdr))
5253
rootCmd.AddCommand(parser.NewHealthchecksCommand(&cmdr))
5354
rootCmd.AddCommand(parser.NewKeysCommand(&cmdr))
5455
rootCmd.AddCommand(parser.NewLabelsCommand(&cmdr))

go.mod

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ go 1.25
55
require (
66
github.com/chai2010/gettext-go v1.0.3
77
github.com/containerd/console v1.0.4
8-
github.com/drycc/controller-sdk-go v0.0.0-20251203071902-cc535b118251
8+
github.com/drycc/controller-sdk-go v0.0.0-20251206164108-e9369b636dd8
99
github.com/drycc/pkg v0.0.0-20250917064731-345368da3dbf
1010
github.com/minio/selfupdate v0.6.0
1111
github.com/olekukonko/tablewriter v0.0.5
12-
github.com/schollz/progressbar/v3 v3.18.0
1312
github.com/spf13/cobra v1.9.1
1413
github.com/stretchr/testify v1.10.0
1514
golang.org/x/net v0.47.0
@@ -26,11 +25,9 @@ require (
2625
github.com/inconshreveable/mousetrap v1.1.0 // indirect
2726
github.com/kr/pretty v0.3.1 // indirect
2827
github.com/mattn/go-runewidth v0.0.16 // indirect
29-
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
3028
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
3129
github.com/rivo/uniseg v0.4.7 // indirect
3230
github.com/spf13/pflag v1.0.6 // indirect
3331
golang.org/x/crypto v0.45.0 // indirect
3432
golang.org/x/sys v0.38.0 // indirect
35-
golang.org/x/term v0.37.0 // indirect
3633
)

go.sum

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@ aead.dev/minisign v0.3.0 h1:8Xafzy5PEVZqYDNP60yJHARlW1eOQtsKNp/Ph2c0vRA=
33
aead.dev/minisign v0.3.0/go.mod h1:NLvG3Uoq3skkRMDuc3YHpWUTMTrSExqm+Ij73W13F6Y=
44
github.com/chai2010/gettext-go v1.0.3 h1:9liNh8t+u26xl5ddmWLmsOsdNLwkdRTg5AG+JnTiM80=
55
github.com/chai2010/gettext-go v1.0.3/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
6-
github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
7-
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
86
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
97
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
108
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
119
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
1210
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
1311
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
14-
github.com/drycc/controller-sdk-go v0.0.0-20251203071902-cc535b118251 h1:6bhcFnQn478sys8IXaeZW4OnurK64gTNMsu2NqKoCIw=
15-
github.com/drycc/controller-sdk-go v0.0.0-20251203071902-cc535b118251/go.mod h1:eHcmYwg81ASlP55/U587xnBZnZoeZnPHXGeQ8nYWnsg=
12+
github.com/drycc/controller-sdk-go v0.0.0-20251206164108-e9369b636dd8 h1:EgzCbOPGeDmeClpCjPPwuCJ8viMWEMn7FiUyY1mJvoM=
13+
github.com/drycc/controller-sdk-go v0.0.0-20251206164108-e9369b636dd8/go.mod h1:eHcmYwg81ASlP55/U587xnBZnZoeZnPHXGeQ8nYWnsg=
1614
github.com/drycc/pkg v0.0.0-20250917064731-345368da3dbf h1:CYy3NoPhfFhkGAbEppTOQfY/HC2s0FJDcBgbtRKeweg=
1715
github.com/drycc/pkg v0.0.0-20250917064731-345368da3dbf/go.mod h1:BrrNrNskHKm+nJYhXfGuI114w8nupi0AMo8QZHID7CM=
1816
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
@@ -31,8 +29,6 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T
3129
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
3230
github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
3331
github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
34-
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
35-
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
3632
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
3733
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
3834
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
@@ -44,8 +40,6 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
4440
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
4541
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
4642
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
47-
github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA=
48-
github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec=
4943
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
5044
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
5145
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
@@ -72,8 +66,6 @@ golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
7266
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
7367
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
7468
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
75-
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
76-
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
7769
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
7870
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
7971
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

internal/commands/apps_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,9 @@ func TestRemoteExists(t *testing.T) {
326326

327327
err = cmdr.AppCreate("foo", "drycc", false)
328328

329-
assert.Equal(t, err.Error(), `A git remote with the name drycc already exists. To overwrite this remote run:
330-
drycc git remote --force --remote drycc --app foo`,
331-
"output")
329+
// Check that an error occurred and it contains the remote name
330+
// This works for any language since the remote name "drycc" is always in the error
331+
assert.Error(t, err)
332+
assert.Contains(t, err.Error(), "drycc",
333+
"error message should contain the remote name 'drycc', got: %s", err.Error())
332334
}

internal/commands/commands.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ type Commander interface {
7171
GitRemote(string, string, bool) error
7272
GitRemove(string) error
7373
HealthchecksList(string, string, int) error
74-
HealthchecksSet(string, string, string, *api.Healthcheck) error
74+
HealthchecksSet(string, string, string, *api.ContainerProbe) error
7575
HealthchecksUnset(string, string, []string) error
7676
KeysList(int) error
7777
KeyRemove(string) error

internal/commands/healthchecks.go

Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,44 @@ import (
99
"github.com/drycc/workflow-cli/internal/loader"
1010
)
1111

12-
func getHealthcheckString(ptype, probeType string, healthcheck *api.Healthcheck) string {
12+
func getContainerProbeString(ptype, probeType string, containerProbe *api.ContainerProbe) string {
1313
params := fmt.Sprintf(
1414
"delay=%ds timeout=%ds period=%ds #success=%d #failure=%d",
15-
healthcheck.InitialDelaySeconds,
16-
healthcheck.TimeoutSeconds,
17-
healthcheck.PeriodSeconds,
18-
healthcheck.SuccessThreshold,
19-
healthcheck.FailureThreshold,
15+
containerProbe.InitialDelaySeconds,
16+
containerProbe.TimeoutSeconds,
17+
containerProbe.PeriodSeconds,
18+
containerProbe.SuccessThreshold,
19+
containerProbe.FailureThreshold,
2020
)
2121

22-
if healthcheck.Exec != nil {
23-
return fmt.Sprintf("%s %s exec %v %s", probeType, ptype, healthcheck.Exec.Command, params)
24-
} else if healthcheck.TCPSocket != nil {
25-
return fmt.Sprintf("%s %s tcp-socket port=%v %s", probeType, ptype, healthcheck.TCPSocket.Port, params)
26-
} else if healthcheck.HTTPGet != nil {
22+
if containerProbe.Exec != nil {
23+
return fmt.Sprintf("%s %s exec %v %s", probeType, ptype, containerProbe.Exec.Command, params)
24+
} else if containerProbe.TCPSocket != nil {
25+
return fmt.Sprintf("%s %s tcp-socket port=%v %s", probeType, ptype, containerProbe.TCPSocket.Port, params)
26+
} else if containerProbe.HTTPGet != nil {
2727
return fmt.Sprintf(
2828
"%s %s http-get headers=%v path=%s port=%d %s",
2929
probeType,
3030
ptype,
31-
healthcheck.HTTPGet.HTTPHeaders,
32-
healthcheck.HTTPGet.Path,
33-
healthcheck.HTTPGet.Port,
31+
containerProbe.HTTPGet.HTTPHeaders,
32+
containerProbe.HTTPGet.Path,
33+
containerProbe.HTTPGet.Port,
3434
params,
3535
)
3636
}
3737
return ""
3838
}
3939

40-
func getHealthchecksStrings(ptype string, healthchecks *api.Healthchecks) []string {
41-
var probes []string
42-
for key := range *healthchecks {
43-
probes = append(probes, getHealthcheckString(ptype, key, (*healthchecks)[key]))
40+
func getHealthchecksStrings(ptype string, healthcheck *api.Healthcheck) []string {
41+
var containerProbes []string
42+
if healthcheck.StartupProbe != nil {
43+
containerProbes = append(containerProbes, getContainerProbeString(ptype, "startupProbe", *healthcheck.StartupProbe))
44+
} else if healthcheck.LivenessProbe != nil {
45+
containerProbes = append(containerProbes, getContainerProbeString(ptype, "livenessProbe", *healthcheck.LivenessProbe))
46+
} else if healthcheck.ReadinessProbe != nil {
47+
containerProbes = append(containerProbes, getContainerProbeString(ptype, "readinessProbe", *healthcheck.ReadinessProbe))
4448
}
45-
return probes
49+
return containerProbes
4650
}
4751

4852
// HealthchecksList lists an app's healthchecks.
@@ -105,7 +109,7 @@ func (d *DryccCmd) HealthchecksList(appID, ptype string, version int) error {
105109
}
106110

107111
// HealthchecksSet sets an app's healthchecks.
108-
func (d *DryccCmd) HealthchecksSet(appID, healthcheckType, ptype string, probe *api.Healthcheck) error {
112+
func (d *DryccCmd) HealthchecksSet(appID, healthcheckType, ptype string, probe *api.ContainerProbe) error {
109113
appID, s, err := loader.LoadAppSettings(d.ConfigFile, appID)
110114
if err != nil {
111115
return err
@@ -114,11 +118,19 @@ func (d *DryccCmd) HealthchecksSet(appID, healthcheckType, ptype string, probe *
114118
d.Printf("Applying %s healthcheck... ", healthcheckType)
115119

116120
quit := progress(d.WOut)
117-
118-
healthcheckMap := make(api.Healthchecks)
119-
healthcheckMap[healthcheckType] = probe
120-
configObj := api.Config{Healthcheck: make(map[string]*api.Healthchecks)}
121-
configObj.Healthcheck[ptype] = &healthcheckMap
121+
var healthcheck api.Healthcheck
122+
switch healthcheckType {
123+
case "livenessProbe":
124+
healthcheck.LivenessProbe = &probe
125+
case "readinessProbe":
126+
healthcheck.ReadinessProbe = &probe
127+
case "startupProbe":
128+
healthcheck.StartupProbe = &probe
129+
default:
130+
return fmt.Errorf("unknown healthcheck type: %s", healthcheckType)
131+
}
132+
configObj := api.Config{Healthcheck: make(map[string]*api.Healthcheck)}
133+
configObj.Healthcheck[ptype] = &healthcheck
122134

123135
_, err = config.Set(s.Client, appID, configObj, true)
124136

@@ -135,7 +147,7 @@ func (d *DryccCmd) HealthchecksSet(appID, healthcheckType, ptype string, probe *
135147
}
136148

137149
// HealthchecksUnset removes an app's healthchecks.
138-
func (d *DryccCmd) HealthchecksUnset(appID, ptype string, healthchecks []string) error {
150+
func (d *DryccCmd) HealthchecksUnset(appID, ptype string, containerProbeTypes []string) error {
139151
appID, s, err := loader.LoadAppSettings(d.ConfigFile, appID)
140152
if err != nil {
141153
return err
@@ -147,16 +159,23 @@ func (d *DryccCmd) HealthchecksUnset(appID, ptype string, healthchecks []string)
147159

148160
configObj := api.Config{}
149161

150-
healthchecksMap := make(map[string]*api.Healthchecks)
151-
healthcheckMap := make(api.Healthchecks)
152-
153-
for _, healthcheck := range healthchecks {
154-
healthcheckMap[healthcheck] = nil
162+
healthcheckMap := make(map[string]*api.Healthcheck)
163+
var nullContainerProbe *api.ContainerProbe = nil
164+
for _, containerProbeType := range containerProbeTypes {
165+
healthcheck := &api.Healthcheck{}
166+
switch containerProbeType {
167+
case "livenessProbe":
168+
healthcheck.LivenessProbe = &nullContainerProbe
169+
case "readinessProbe":
170+
healthcheck.ReadinessProbe = &nullContainerProbe
171+
case "startupProbe":
172+
healthcheck.StartupProbe = &nullContainerProbe
173+
default:
174+
return fmt.Errorf("unknown container probe type: %s", containerProbeType)
175+
}
176+
healthcheckMap[containerProbeType] = healthcheck
155177
}
156-
healthchecksMap[ptype] = &healthcheckMap
157-
158-
configObj.Healthcheck = healthchecksMap
159-
178+
configObj.Healthcheck = healthcheckMap
160179
_, err = config.Set(s.Client, appID, configObj, true)
161180

162181
quit <- true

internal/commands/healthchecks_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func TestHealthchecksSet(t *testing.T) {
208208
}`)
209209
})
210210

211-
err = cmdr.HealthchecksSet("foo", "livenessProbe", "web", &api.Healthcheck{})
211+
err = cmdr.HealthchecksSet("foo", "livenessProbe", "web", &api.ContainerProbe{})
212212
assert.NoError(t, err)
213213
assert.Equal(t, testutil.StripProgress(b.String()), `Applying livenessProbe healthcheck... done
214214

internal/commands/lifecycles.go

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package commands
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/drycc/controller-sdk-go/api"
7+
"github.com/drycc/controller-sdk-go/config"
8+
"github.com/drycc/workflow-cli/internal/loader"
9+
)
10+
11+
func getLifecycleHandlerString(ptype, handler, signal string, lifecycleHandler *api.LifecycleHandler) string {
12+
if lifecycleHandler.Exec != nil {
13+
return fmt.Sprintf("%s %s exec %v %s", handler, ptype, lifecycleHandler.Exec.Command, signal)
14+
} else if lifecycleHandler.Sleep != nil {
15+
return fmt.Sprintf("%s %s sleep %v %s", handler, ptype, lifecycleHandler.Sleep, signal)
16+
} else if lifecycleHandler.TCPSocket != nil {
17+
return fmt.Sprintf("%s %s tcp-socket port=%v %s", handler, ptype, lifecycleHandler.TCPSocket.Port, signal)
18+
} else if lifecycleHandler.HTTPGet != nil {
19+
return fmt.Sprintf(
20+
"%s %s http-get headers=%v path=%s port=%d %s",
21+
handler,
22+
ptype,
23+
lifecycleHandler.HTTPGet.HTTPHeaders,
24+
lifecycleHandler.HTTPGet.Path,
25+
lifecycleHandler.HTTPGet.Port,
26+
signal,
27+
)
28+
}
29+
return ""
30+
}
31+
32+
// LifecyclesList lists an app's lifecycles.
33+
func (d *DryccCmd) LifecyclesList(appID, ptype string, version int) error {
34+
appID, s, err := loader.LoadAppSettings(d.ConfigFile, appID)
35+
if err != nil {
36+
return err
37+
}
38+
39+
config, err := config.List(s.Client, appID, version)
40+
if d.checkAPICompatibility(s.Client, err) != nil {
41+
return err
42+
}
43+
if len(config.Lifecycle) == 0 {
44+
d.Println(fmt.Sprintf("No lifecycle found in %s app.", appID))
45+
return nil
46+
}
47+
48+
ptypes := []string{}
49+
if ptype != "" {
50+
ptypes = append(ptypes, ptype)
51+
} else {
52+
for ptype := range config.Lifecycle {
53+
ptypes = append(ptypes, ptype)
54+
}
55+
}
56+
57+
table := d.getDefaultFormatTable([]string{})
58+
table.Append([]string{"App:", config.App})
59+
table.Append([]string{"UUID:", config.UUID})
60+
table.Append([]string{"Owner:", config.Owner})
61+
table.Append([]string{"Created:", d.formatTime(config.Created)})
62+
table.Append([]string{"Updated:", d.formatTime(config.Updated)})
63+
table.Append([]string{"Lifecycle:"})
64+
for _, ptype := range sortPtypes(ptypes) {
65+
if lifecycle, ok := config.Lifecycle[ptype]; ok {
66+
table.Append([]string{"", fmt.Sprintf("stopSignal=%s", lifecycle.StopSignal)})
67+
table.Append([]string{"", getLifecycleHandlerString(ptype, "postStart", lifecycle.StopSignal, *lifecycle.PostStart)})
68+
table.Append([]string{"", getLifecycleHandlerString(ptype, "preStop", lifecycle.StopSignal, *lifecycle.PreStop)})
69+
}
70+
}
71+
table.Render()
72+
73+
return nil
74+
}
75+
76+
// LifecyclesSet sets an app's lifecycle.
77+
func (d *DryccCmd) LifecyclesSet(appID, ptype string, lifecycle *api.Lifecycle) error {
78+
appID, s, err := loader.LoadAppSettings(d.ConfigFile, appID)
79+
if err != nil {
80+
return err
81+
}
82+
83+
d.Print("Applying lifecycle... ")
84+
85+
quit := progress(d.WOut)
86+
configObj := api.Config{Lifecycle: make(map[string]*api.Lifecycle)}
87+
configObj.Lifecycle[ptype] = lifecycle
88+
89+
_, err = config.Set(s.Client, appID, configObj, true)
90+
quit <- true
91+
<-quit
92+
if d.checkAPICompatibility(s.Client, err) != nil {
93+
return err
94+
}
95+
96+
d.Print("done\n\n")
97+
98+
return d.LifecyclesList(appID, ptype, -1)
99+
}
100+
101+
// LifecyclesUnset removes an app's lifecycle.
102+
func (d *DryccCmd) LifecyclesUnset(appID, ptype string, handlers []string) error {
103+
appID, s, err := loader.LoadAppSettings(d.ConfigFile, appID)
104+
if err != nil {
105+
return err
106+
}
107+
108+
d.Print("Applying lifecycle... ")
109+
110+
quit := progress(d.WOut)
111+
112+
configObj := api.Config{Lifecycle: make(map[string]*api.Lifecycle)}
113+
lifecycle := &api.Lifecycle{}
114+
var nullLifecycleHandler *api.LifecycleHandler = nil
115+
for _, handler := range handlers {
116+
switch handler {
117+
case "postStart":
118+
lifecycle.PostStart = &nullLifecycleHandler
119+
case "preStop":
120+
lifecycle.PreStop = &nullLifecycleHandler
121+
default:
122+
return fmt.Errorf("unknown lifecycle handler: %s", handler)
123+
}
124+
}
125+
configObj.Lifecycle[ptype] = lifecycle
126+
127+
_, err = config.Set(s.Client, appID, configObj, true)
128+
quit <- true
129+
<-quit
130+
if d.checkAPICompatibility(s.Client, err) != nil {
131+
return err
132+
}
133+
134+
d.Print("done\n\n")
135+
136+
return d.LifecyclesList(appID, ptype, -1)
137+
}

0 commit comments

Comments
 (0)