Skip to content

Commit 72235ec

Browse files
authored
feat(autoscale): add support for autoscale per proc type on an application (#89)
1 parent fc22df3 commit 72235ec

3 files changed

Lines changed: 114 additions & 14 deletions

File tree

api/appsettings.go

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package api
22

3+
import (
4+
"bytes"
5+
"text/template"
6+
)
7+
38
// AppSettings is the structure of an app's settings.
49
type AppSettings struct {
510
// Owner is the app owner. It cannot be updated with AppSettings.Set(). See app.Transfer().
@@ -16,8 +21,9 @@ type AppSettings struct {
1621
// Maintenance determines if the application is taken down for maintenance or not.
1722
Maintenance *bool `json:"maintenance,omitempty"`
1823
// Routable determines if the application should be exposed by the router.
19-
Routable *bool `json:"routable,omitempty"`
20-
Whitelist []string `json:"whitelist,omitempty"`
24+
Routable *bool `json:"routable,omitempty"`
25+
Whitelist []string `json:"whitelist,omitempty"`
26+
Autoscale map[string]*Autoscale `json:"autoscale,omitempty"`
2127
}
2228

2329
// NewRoutable returns a default value for the AppSettings.Routable field.
@@ -30,3 +36,28 @@ func NewRoutable() *bool {
3036
type Whitelist struct {
3137
Addresses []string `json:"addresses"`
3238
}
39+
40+
// String displays the Autoscale rule in a readable format.
41+
func (a Autoscale) String() string {
42+
var doc bytes.Buffer
43+
tmpl, err := template.New("autoscale").Parse(`Min Replicas: {{.Min}}
44+
Max Replicas: {{.Max}}
45+
CPU: {{.CPUPercent}}%`)
46+
if err != nil {
47+
panic(err)
48+
}
49+
if err := tmpl.Execute(&doc, a); err != nil {
50+
panic(err)
51+
}
52+
return doc.String()
53+
}
54+
55+
// Autoscales contains a hash of process types and the autoscale rules
56+
type Autoscales map[string]*Autoscale
57+
58+
// Autoscale is a per proc type scaling information
59+
type Autoscale struct {
60+
Min int `json:"min"`
61+
Max int `json:"max"`
62+
CPUPercent int `json:"cpu_percent"`
63+
}

api/appsettings_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package api
2+
3+
import (
4+
"strings"
5+
"testing"
6+
)
7+
8+
func TestAutoscaleString(t *testing.T) {
9+
a := Autoscale{}
10+
11+
expected := strings.TrimSpace(`Min Replicas: 0
12+
Max Replicas: 0
13+
CPU: 0%`)
14+
15+
if strings.TrimSpace(a.String()) != expected {
16+
t.Errorf("Expected:\n\n%s\n\nGot:\n\n%s", expected, a.String())
17+
}
18+
19+
a2 := Autoscale{
20+
Min: 3,
21+
Max: 8,
22+
CPUPercent: 40,
23+
}
24+
25+
expected2 := strings.TrimSpace(`Min Replicas: 3
26+
Max Replicas: 8
27+
CPU: 40%`)
28+
29+
if strings.TrimSpace(a2.String()) != expected2 {
30+
t.Errorf("Expected:\n\n%s\n\nGot:\n\n%s", expected2, a2.String())
31+
}
32+
}

appsettings/appsettings_test.go

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const appSettingsFixture string = `
1919
"maintenance": true,
2020
"routable": true,
2121
"whitelist": ["1.2.3.4", "0.0.0.0/0"],
22+
"autoscale": {"cmd": {"min": 3, "max": 8, "cpu_percent": 40}},
2223
"created": "2014-01-01T00:00:00UTC",
2324
"updated": "2014-01-01T00:00:00UTC",
2425
"uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
@@ -29,17 +30,18 @@ const appSettingsUnsetFixture string = `
2930
{
3031
"owner": "test",
3132
"app": "unset-test",
32-
"maintenance": true,
33+
"maintenance": true,
3334
"routable": true,
3435
"whitelist": ["1.2.3.4", "0.0.0.0/0"],
36+
"autoscale": {"cmd": {"min": 3, "max": 8, "cpu_percent": 40}},
3537
"created": "2014-01-01T00:00:00UTC",
3638
"updated": "2014-01-01T00:00:00UTC",
3739
"uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
3840
}
3941
`
4042

41-
const appSettingsSetExpected string = `{"maintenance":true,"routable":true,"whitelist":["1.2.3.4","0.0.0.0/0"]}`
42-
const appSettingsUnsetExpected string = `{"maintenance":true,"routable":true,"whitelist":["1.2.3.4","0.0.0.0/0"]}`
43+
const appSettingsSetExpected string = `{"maintenance":true,"routable":true,"whitelist":["1.2.3.4","0.0.0.0/0"],"autoscale":{"cmd":{"min":3,"max":8,"cpu_percent":40}}}`
44+
const appSettingsUnsetExpected string = `{"maintenance":true,"routable":true,"whitelist":["1.2.3.4","0.0.0.0/0"],"autoscale":{"cmd":{"min":3,"max":8,"cpu_percent":40}}}`
4345

4446
var trueVar = true
4547

@@ -129,15 +131,29 @@ func TestAppSettingsSet(t *testing.T) {
129131
Routable: api.NewRoutable(),
130132
Maintenance: &trueVar,
131133
Whitelist: []string{"1.2.3.4", "0.0.0.0/0"},
132-
Created: "2014-01-01T00:00:00UTC",
133-
Updated: "2014-01-01T00:00:00UTC",
134-
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
134+
Autoscale: map[string]*api.Autoscale{
135+
"cmd": {
136+
Min: 3,
137+
Max: 8,
138+
CPUPercent: 40,
139+
},
140+
},
141+
Created: "2014-01-01T00:00:00UTC",
142+
Updated: "2014-01-01T00:00:00UTC",
143+
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
135144
}
136145

137146
appSettingsVars := api.AppSettings{
138147
Maintenance: &trueVar,
139148
Routable: api.NewRoutable(),
140149
Whitelist: []string{"1.2.3.4", "0.0.0.0/0"},
150+
Autoscale: map[string]*api.Autoscale{
151+
"cmd": {
152+
Min: 3,
153+
Max: 8,
154+
CPUPercent: 40,
155+
},
156+
},
141157
}
142158

143159
actual, err := Set(deis, "example-go", appSettingsVars)
@@ -169,15 +185,29 @@ func TestAppSettingsUnset(t *testing.T) {
169185
Maintenance: &trueVar,
170186
Routable: api.NewRoutable(),
171187
Whitelist: []string{"1.2.3.4", "0.0.0.0/0"},
172-
Created: "2014-01-01T00:00:00UTC",
173-
Updated: "2014-01-01T00:00:00UTC",
174-
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
188+
Autoscale: map[string]*api.Autoscale{
189+
"cmd": {
190+
Min: 3,
191+
Max: 8,
192+
CPUPercent: 40,
193+
},
194+
},
195+
Created: "2014-01-01T00:00:00UTC",
196+
Updated: "2014-01-01T00:00:00UTC",
197+
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
175198
}
176199

177200
appSettingsVars := api.AppSettings{
178201
Maintenance: &trueVar,
179202
Routable: api.NewRoutable(),
180203
Whitelist: []string{"1.2.3.4", "0.0.0.0/0"},
204+
Autoscale: map[string]*api.Autoscale{
205+
"cmd": {
206+
Min: 3,
207+
Max: 8,
208+
CPUPercent: 40,
209+
},
210+
},
181211
}
182212

183213
actual, err := Set(deis, "unset-test", appSettingsVars)
@@ -209,9 +239,16 @@ func TestAppSettingsList(t *testing.T) {
209239
Maintenance: &trueVar,
210240
Routable: api.NewRoutable(),
211241
Whitelist: []string{"1.2.3.4", "0.0.0.0/0"},
212-
Created: "2014-01-01T00:00:00UTC",
213-
Updated: "2014-01-01T00:00:00UTC",
214-
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
242+
Autoscale: map[string]*api.Autoscale{
243+
"cmd": {
244+
Min: 3,
245+
Max: 8,
246+
CPUPercent: 40,
247+
},
248+
},
249+
Created: "2014-01-01T00:00:00UTC",
250+
Updated: "2014-01-01T00:00:00UTC",
251+
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
215252
}
216253

217254
actual, err := List(deis, "example-go")

0 commit comments

Comments
 (0)