Skip to content

Commit e9369b6

Browse files
committed
feat(config): add lifecycle
1 parent cc535b1 commit e9369b6

33 files changed

Lines changed: 271 additions & 206 deletions

api/apps.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ type AppUpdateRequest struct {
2929

3030
// AppRunRequest is the definition of POST /v2/apps/<app id>/run.
3131
type AppRunRequest struct {
32-
Command string `json:"command"`
33-
Volumes map[string]interface{} `json:"volumes,omitempty"`
34-
Timeout uint32 `json:"timeout,omitempty"`
35-
Expires uint32 `json:"expires,omitempty"`
32+
Command string `json:"command"`
33+
Volumes map[string]any `json:"volumes,omitempty"`
34+
Timeout uint32 `json:"timeout,omitempty"`
35+
Expires uint32 `json:"expires,omitempty"`
3636
}
3737

3838
// AppLogsRequest is the definition of websocket /v2/apps/<app id>/logs

api/appsettings.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,4 @@ type Autoscale struct {
7676
}
7777

7878
// Labels can contain any user-defined key value
79-
type Labels map[string]interface{}
79+
type Labels map[string]any

api/builds.go

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,35 @@ package api
22

33
// Build is the structure of the build object.
44
type Build struct {
5-
App string `json:"app"`
6-
Created string `json:"created"`
7-
Dockerfile string `json:"dockerfile,omitempty"`
8-
Image string `json:"image,omitempty"`
9-
Stack string `json:"stack,omitempty"`
10-
Owner string `json:"owner"`
11-
Procfile map[string]string `json:"procfile"`
12-
Dryccfile map[string]interface{} `json:"dryccfile"`
13-
Sha string `json:"sha,omitempty"`
14-
Updated string `json:"updated"`
15-
UUID string `json:"uuid"`
5+
App string `json:"app"`
6+
Created string `json:"created"`
7+
Dockerfile string `json:"dockerfile,omitempty"`
8+
Image string `json:"image,omitempty"`
9+
Stack string `json:"stack,omitempty"`
10+
Owner string `json:"owner"`
11+
Procfile map[string]string `json:"procfile"`
12+
Dryccfile map[string]any `json:"dryccfile"`
13+
Sha string `json:"sha,omitempty"`
14+
Updated string `json:"updated"`
15+
UUID string `json:"uuid"`
1616
}
1717

1818
// CreateBuildRequest is the structure of POST /v2/apps/<app id>/builds/.
1919
type CreateBuildRequest struct {
20-
Image string `json:"image"`
21-
Stack string `json:"stack,omitempty"`
22-
Procfile map[string]string `json:"procfile,omitempty"`
23-
Dryccfile map[string]interface{} `json:"dryccfile,omitempty"`
20+
Image string `json:"image"`
21+
Stack string `json:"stack,omitempty"`
22+
Procfile map[string]string `json:"procfile,omitempty"`
23+
Dryccfile map[string]any `json:"dryccfile,omitempty"`
2424
}
2525

2626
// BuildHookRequest is a hook request to create a new build.
2727
type BuildHookRequest struct {
28-
Sha string `json:"sha"`
29-
User string `json:"receive_user"`
30-
App string `json:"receive_repo"`
31-
Image string `json:"image"`
32-
Stack string `json:"stack"`
33-
Procfile ProcessType `json:"procfile"`
34-
Dockerfile string `json:"dockerfile"`
35-
Dryccfile map[string]interface{} `json:"dryccfile"`
28+
Sha string `json:"sha"`
29+
User string `json:"receive_user"`
30+
App string `json:"receive_repo"`
31+
Image string `json:"image"`
32+
Stack string `json:"stack"`
33+
Procfile ProcessType `json:"procfile"`
34+
Dockerfile string `json:"dockerfile"`
35+
Dryccfile map[string]any `json:"dryccfile"`
3636
}

api/config.go

Lines changed: 96 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import (
77
)
88

99
// ConfigTags is the key, value for tag
10-
type ConfigTags map[string]interface{}
10+
type ConfigTags map[string]any
1111

1212
// ConfigVar represents a configuration variable for an app.
1313
type ConfigVar struct {
14-
Name string `json:"name"`
15-
Value interface{} `json:"value"`
14+
Name string `json:"name"`
15+
Value any `json:"value"`
1616
}
1717

1818
// ConfigValue represents a configuration value with its type and group.
@@ -59,17 +59,19 @@ type Config struct {
5959
ValuesRefs ValuesRefs `json:"values_refs,omitempty"`
6060
// Limits is used to set process resources limits. The key is the process name
6161
// and the value is a limit plan. Ex: std1.xlarge.c1m1
62-
Limits map[string]interface{} `json:"limits,omitempty"`
62+
Limits map[string]any `json:"limits,omitempty"`
6363
// Timeout is used to set termination grace period. The key is the process name
6464
// and the value is a number in seconds, e.g. 30
65-
Timeout map[string]interface{} `json:"termination_grace_period,omitempty"`
65+
Timeout map[string]any `json:"termination_grace_period,omitempty"`
66+
// Lifecycle is a map of lifecycles for each process type.
67+
Lifecycle map[string]*Lifecycle `json:"lifecycle,omitempty"`
6668
// Healthcheck is map of healthchecks for each process that the application uses.
67-
Healthcheck map[string]*Healthchecks `json:"healthcheck,omitempty"`
69+
Healthcheck map[string]*Healthcheck `json:"healthcheck,omitempty"`
6870
// Tags restrict applications to run on k8s nodes with that label.
6971
Tags map[string]ConfigTags `json:"tags,omitempty"`
7072
// Registry is a key-value pair to provide authentication for container registries.
7173
// The key is the username and the value is the password.
72-
Registry map[string]map[string]interface{} `json:"registry,omitempty"`
74+
Registry map[string]map[string]any `json:"registry,omitempty"`
7375
// Created is the time that the application was created and cannot be updated.
7476
Created string `json:"created,omitempty"`
7577
// Updated is the last time the configuration was changed and cannot be updated.
@@ -85,39 +87,74 @@ type ConfigHookRequest struct {
8587
App string `json:"receive_repo"`
8688
}
8789

88-
// Healthchecks is a map of healthcheck probes.
89-
// The valid values are "startupProbe" "livenessProbe" and "readinessProbe".
90-
type Healthchecks map[string]*Healthcheck
90+
// Lifecycle defines actions to take in the container lifecycle.
91+
type Lifecycle struct {
92+
PostStart **LifecycleHandler `json:"postStart,omitempty"`
93+
PreStop **LifecycleHandler `json:"preStop,omitempty"`
94+
StopSignal string `json:"stopSignal,omitempty"`
95+
}
96+
97+
// LifecycleHandler defines actions to take in the container lifecycle.
98+
type LifecycleHandler struct {
99+
Exec *ExecAction `json:"exec,omitempty"`
100+
HTTPGet *HTTPGetAction `json:"httpGet,omitempty"`
101+
Sleep *SleepAction `json:"sleep,omitempty"`
102+
TCPSocket *TCPSocketAction `json:"tcpSocket,omitempty"`
103+
}
104+
105+
// String displays the LifecycleHandler in a readable format.
106+
func (l LifecycleHandler) String() string {
107+
var doc bytes.Buffer
108+
tmpl, err := template.New("healthcheck").Parse(`Exec Probe: {{or .Exec "N/A"}}
109+
GRPC Action: {{or .GRPC "N/A"}}
110+
HTTP GET Action: {{or .HTTPGet "N/A"}}
111+
Sleep Action: {{or .Sleep "N/A"}}
112+
TCP Socket Action: {{or .TCPSocket "N/A"}}`)
113+
if err != nil {
114+
panic(err)
115+
}
116+
if err := tmpl.Execute(&doc, l); err != nil {
117+
panic(err)
118+
}
119+
return doc.String()
120+
}
91121

92-
// Healthcheck is the structure for an application healthcheck.
93-
// Healthchecks only need to provide information about themselves.
94-
// All the information is pushed to the server and handled by kubernetes.
122+
// Healthcheck defines a container healthcheck.
95123
type Healthcheck struct {
96-
InitialDelaySeconds int `json:"initialDelaySeconds"`
97-
TimeoutSeconds int `json:"timeoutSeconds"`
98-
PeriodSeconds int `json:"periodSeconds"`
99-
SuccessThreshold int `json:"successThreshold"`
100-
FailureThreshold int `json:"failureThreshold"`
101-
Exec *ExecProbe `json:"exec,omitempty"`
102-
HTTPGet *HTTPGetProbe `json:"httpGet,omitempty"`
103-
TCPSocket *TCPSocketProbe `json:"tcpSocket,omitempty"`
104-
}
105-
106-
// String displays the HealthcheckHTTPGetProbe in a readable format.
107-
func (h Healthcheck) String() string {
124+
StartupProbe **ContainerProbe `json:"startupProbe,omitempty"`
125+
LivenessProbe **ContainerProbe `json:"livenessProbe,omitempty"`
126+
ReadinessProbe **ContainerProbe `json:"readinessProbe,omitempty"`
127+
}
128+
129+
// ContainerProbe defines a container healthcheck probe.
130+
type ContainerProbe struct {
131+
InitialDelaySeconds int `json:"initialDelaySeconds"`
132+
TimeoutSeconds int `json:"timeoutSeconds"`
133+
PeriodSeconds int `json:"periodSeconds"`
134+
SuccessThreshold int `json:"successThreshold"`
135+
FailureThreshold int `json:"failureThreshold"`
136+
Exec *ExecAction `json:"exec,omitempty"`
137+
GRPC *GRPCAction `json:"grpc,omitempty"`
138+
HTTPGet *HTTPGetAction `json:"httpGet,omitempty"`
139+
TCPSocket *TCPSocketAction `json:"tcpSocket,omitempty"`
140+
}
141+
142+
// String displays the ContainerProbe in a readable format.
143+
func (c ContainerProbe) String() string {
108144
var doc bytes.Buffer
109145
tmpl, err := template.New("healthcheck").Parse(`Initial Delay (seconds): {{.InitialDelaySeconds}}
110146
Timeout (seconds): {{.TimeoutSeconds}}
111147
Period (seconds): {{.PeriodSeconds}}
112148
Success Threshold: {{.SuccessThreshold}}
113149
Failure Threshold: {{.FailureThreshold}}
114150
Exec Probe: {{or .Exec "N/A"}}
151+
GRPC Probe: {{or .GRPC "N/A"}}
115152
HTTP GET Probe: {{or .HTTPGet "N/A"}}
116153
TCP Socket Probe: {{or .TCPSocket "N/A"}}`)
117154
if err != nil {
118155
panic(err)
119156
}
120-
if err := tmpl.Execute(&doc, h); err != nil {
157+
if err := tmpl.Execute(&doc, c); err != nil {
121158
panic(err)
122159
}
123160
return doc.String()
@@ -135,38 +172,60 @@ func (k KVPair) String() string {
135172
}
136173

137174
// ExecProbe executes a command within a Pod.
138-
type ExecProbe struct {
175+
type ExecAction struct {
139176
Command []string `json:"command"`
140177
}
141178

142-
// String displays the ExecProbe in a readable format.
143-
func (e ExecProbe) String() string {
179+
// String displays the ExecAction in a readable format.
180+
func (e ExecAction) String() string {
144181
return fmt.Sprintf(`Command=%s`, e.Command)
145182
}
146183

147-
// HTTPGetProbe performs an HTTP GET request to the Pod
184+
// HTTPGetAction performs an HTTP GET request to the Pod
148185
// with the given path, port and headers.
149-
type HTTPGetProbe struct {
186+
type HTTPGetAction struct {
150187
Path string `json:"path,omitempty"`
151188
Port int `json:"port"`
152189
HTTPHeaders []*KVPair `json:"httpHeaders,omitempty"`
153190
}
154191

155-
// String displays the HTTPGetProbe in a readable format.
156-
func (h HTTPGetProbe) String() string {
192+
// String displays the HTTPGetAction in a readable format.
193+
func (h HTTPGetAction) String() string {
157194
return fmt.Sprintf(`Path="%s" Port=%d HTTPHeaders=%s`,
158195
h.Path,
159196
h.Port,
160197
h.HTTPHeaders)
161198
}
162199

163-
// TCPSocketProbe attempts to open a socket connection to the
200+
// TCPSocketAction attempts to open a socket connection to the
164201
// Pod on the given port.
165-
type TCPSocketProbe struct {
202+
type TCPSocketAction struct {
166203
Port int `json:"port"`
167204
}
168205

169-
// String displays the TCPSocketProbe in a readable format.
170-
func (t TCPSocketProbe) String() string {
206+
// String displays the TCPSocketAction in a readable format.
207+
func (t TCPSocketAction) String() string {
171208
return fmt.Sprintf("Port=%d", t.Port)
172209
}
210+
211+
// GRPCAction performs an GRPC request to the Pod
212+
// with the given path, port and headers.
213+
type GRPCAction struct {
214+
Port int `json:"port"`
215+
Service string `json:"service,omitempty"`
216+
}
217+
218+
// String displays the GRPCAction in a readable format.
219+
func (g GRPCAction) String() string {
220+
return fmt.Sprintf(`Port=%d Service="%s"`, g.Port, g.Service)
221+
}
222+
223+
// SleepAction pauses for a specified number of seconds.
224+
type SleepAction struct {
225+
Seconds int `json:"seconds"`
226+
}
227+
228+
// String displays the SleepAction in a readable format.
229+
func (s SleepAction) String() string {
230+
return fmt.Sprintf(`Seconds=%d`, s.Seconds)
231+
}

api/config_test.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,23 @@ import (
66
)
77

88
func TestHealthcheckString(t *testing.T) {
9-
h := Healthcheck{}
9+
h := ContainerProbe{}
1010

1111
expected := strings.TrimSpace(`Initial Delay (seconds): 0
1212
Timeout (seconds): 0
1313
Period (seconds): 0
1414
Success Threshold: 0
1515
Failure Threshold: 0
1616
Exec Probe: N/A
17+
GRPC Probe: N/A
1718
HTTP GET Probe: N/A
1819
TCP Socket Probe: N/A`)
1920

2021
if strings.TrimSpace(h.String()) != expected {
2122
t.Errorf("Expected:\n\n%s\n\nGot:\n\n%s", expected, h.String())
2223
}
2324

24-
h.HTTPGet = &HTTPGetProbe{
25+
h.HTTPGet = &HTTPGetAction{
2526
Path: "/",
2627
Port: 80,
2728
HTTPHeaders: []*KVPair{{Name: "X-DRYCC-IS", Value: "AWESOME"}},
@@ -33,16 +34,20 @@ Period (seconds): 0
3334
Success Threshold: 0
3435
Failure Threshold: 0
3536
Exec Probe: N/A
37+
GRPC Probe: N/A
3638
HTTP GET Probe: Path="/" Port=80 HTTPHeaders=[X-DRYCC-IS=AWESOME]
3739
TCP Socket Probe: N/A`)
3840

3941
if strings.TrimSpace(h.String()) != expected {
4042
t.Errorf("Expected:\n\n%s\n\nGot:\n\n%s", expected, h.String())
4143
}
4244

43-
h.Exec = &ExecProbe{Command: []string{"echo", "hi"}}
44-
45-
h.TCPSocket = &TCPSocketProbe{
45+
h.Exec = &ExecAction{Command: []string{"echo", "hi"}}
46+
h.GRPC = &GRPCAction{
47+
Port: 80,
48+
Service: "myservice",
49+
}
50+
h.TCPSocket = &TCPSocketAction{
4651
Port: 80,
4752
}
4853

@@ -52,6 +57,7 @@ Period (seconds): 0
5257
Success Threshold: 0
5358
Failure Threshold: 0
5459
Exec Probe: Command=[echo hi]
60+
GRPC Probe: Port=80 Service="myservice"
5561
HTTP GET Probe: Path="/" Port=80 HTTPHeaders=[X-DRYCC-IS=AWESOME]
5662
TCP Socket Probe: Port=80`)
5763

api/gateways.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ type Gateway struct {
2020

2121
// Listener represents a gateway listener configuration.
2222
type Listener struct {
23-
Name string `json:"name,omitempty"`
24-
Port int `json:"port,omitempty"`
25-
Protocol string `json:"protocol,omitempty"`
26-
AllowedRoutes interface{} `json:"allowedRoutes,omitempty"`
23+
Name string `json:"name,omitempty"`
24+
Port int `json:"port,omitempty"`
25+
Protocol string `json:"protocol,omitempty"`
26+
AllowedRoutes any `json:"allowedRoutes,omitempty"`
2727
}
2828

2929
// Address represents a gateway address configuration.

api/limits.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ package api
22

33
// LimitSpec is the definition of GET /v2/limits/specs/
44
type LimitSpec struct {
5-
ID string `json:"id"`
6-
CPU map[string]interface{} `json:"cpu"`
7-
Memory map[string]interface{} `json:"memory"`
8-
Features map[string]interface{} `json:"features"`
9-
Keywords []string `json:"keywords"`
10-
Disabled bool `json:"disabled"`
5+
ID string `json:"id"`
6+
CPU map[string]any `json:"cpu"`
7+
Memory map[string]any `json:"memory"`
8+
Features map[string]any `json:"features"`
9+
Keywords []string `json:"keywords"`
10+
Disabled bool `json:"disabled"`
1111
}
1212

1313
// LimitPlan is the definition of GET /v2/limits/plans/
1414
type LimitPlan struct {
15-
ID string `json:"id"`
16-
Spec LimitSpec `json:"spec"`
17-
CPU int `json:"cpu"`
18-
Memory int `json:"memory"`
19-
Features map[string]interface{} `json:"features"`
20-
Disabled bool `json:"disabled"`
15+
ID string `json:"id"`
16+
Spec LimitSpec `json:"spec"`
17+
CPU int `json:"cpu"`
18+
Memory int `json:"memory"`
19+
Features map[string]any `json:"features"`
20+
Disabled bool `json:"disabled"`
2121
}

0 commit comments

Comments
 (0)