This repository has been archived by the owner on Sep 4, 2021. It is now read-only.
/
limit.go
136 lines (113 loc) · 3.22 KB
/
limit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package main
import (
"fmt"
"io"
"os"
"sort"
"strings"
"github.com/flynn/flynn/controller/client"
ct "github.com/flynn/flynn/controller/types"
"github.com/flynn/flynn/host/resource"
"github.com/flynn/go-docopt"
)
func init() {
register("limit", runLimit, `
usage: flynn limit [-t <proc>]
flynn limit set <proc> <var>=<val>...
Manage app resource limits.
Options:
-t, --process-type=<proc> set or read limits for specified process type
Commands:
With no arguments, shows a list of resource limits.
set sets value of one or more resource limits
Examples:
$ flynn limit
web: cpu=1000 temp_disk=100MB max_fd=10000 memory=1GB
worker: cpu=1000 temp_disk=100MB max_fd=10000 memory=1GB
$ flynn limit set web memory=512MB max_fd=12000 cpu=500 temp_disk=200MB
Created release 5058ae7964f74c399a240bdd6e7d1bcb
$ flynn limit
web: cpu=500 temp_disk=200MB max_fd=12000 memory=512MB
worker: cpu=1000 temp_disk=100MB max_fd=10000 memory=1GB
$ flynn limit set web memory=256MB
Created release b39fe25d0ea344b6b2af5cf4d6542a80
$ flynn limit
web: cpu=500 temp_disk=200MB max_fd=12000 memory=256MB
worker: cpu=1000 temp_disk=100MB max_fd=10000 memory=1GB
`)
}
func runLimit(args *docopt.Args, client controller.Client) error {
if args.Bool["set"] {
return runLimitSet(args, client)
}
release, err := client.GetAppRelease(mustApp())
if err == controller.ErrNotFound {
return nil
} else if err != nil {
return err
}
w := tabWriter()
defer w.Flush()
if procType := args.String["--process-type"]; procType != "" {
t, ok := release.Processes[procType]
if !ok {
return fmt.Errorf("unknown process type %q", procType)
}
formatLimits(w, procType, t.Resources)
return nil
}
for s, t := range release.Processes {
formatLimits(w, s, t.Resources)
}
return nil
}
func formatLimits(w io.Writer, s string, r resource.Resources) {
limits := make([]string, 0, len(r))
for typ, spec := range r {
if limit := spec.Limit; limit != nil {
limits = append(limits, fmt.Sprintf("%s=%s", typ, resource.FormatLimit(typ, *limit)))
}
}
sort.Strings(limits)
fmt.Fprintf(w, "%s:\t%s\n", s, strings.Join(limits, "\t"))
}
func runLimitSet(args *docopt.Args, client controller.Client) error {
proc := args.String["<proc>"]
app, err := client.GetApp(mustApp())
if err != nil {
return err
}
release, err := client.GetAppRelease(app.ID)
if err == controller.ErrNotFound {
release = &ct.Release{}
} else if err != nil {
return err
}
if release.Processes == nil {
release.Processes = make(map[string]ct.ProcessType)
}
t, ok := release.Processes[proc]
if !ok && proc != "slugbuilder" {
fmt.Fprintf(os.Stderr, "Warning: %q is not an existing process type, setting anyway\n", proc)
}
if t.Resources == nil {
t.Resources = resource.Defaults()
}
resources, err := resource.Parse(args.All["<var>=<val>"].([]string))
if err != nil {
return err
}
for typ, limit := range resources {
t.Resources[typ] = limit
}
release.Processes[proc] = t
release.ID = ""
if err := client.CreateRelease(app.ID, release); err != nil {
return err
}
if err := client.DeployAppRelease(app.ID, release.ID, nil); err != nil {
return err
}
fmt.Printf("Created release %s\n", release.ID)
return nil
}