... | ... |
@@ -1,9 +1,12 @@ |
1 | 1 |
package docker |
2 | 2 |
|
3 | 3 |
import ( |
4 |
+ "bufio" |
|
4 | 5 |
"fmt" |
5 | 6 |
"io" |
6 | 7 |
"io/ioutil" |
8 |
+ "math/rand" |
|
9 |
+ "os" |
|
7 | 10 |
"sort" |
8 | 11 |
"strings" |
9 | 12 |
"testing" |
... | ... |
@@ -561,6 +564,58 @@ func TestEnv(t *testing.T) { |
561 | 561 |
} |
562 | 562 |
} |
563 | 563 |
|
564 |
+func grepFile(t *testing.T, path string, pattern string) { |
|
565 |
+ f, err := os.Open(path) |
|
566 |
+ if err != nil { |
|
567 |
+ t.Fatal(err) |
|
568 |
+ } |
|
569 |
+ defer f.Close() |
|
570 |
+ r := bufio.NewReader(f) |
|
571 |
+ var ( |
|
572 |
+ line string |
|
573 |
+ ) |
|
574 |
+ err = nil |
|
575 |
+ for err == nil { |
|
576 |
+ line, err = r.ReadString('\n') |
|
577 |
+ if strings.Contains(line, pattern) == true { |
|
578 |
+ return |
|
579 |
+ } |
|
580 |
+ } |
|
581 |
+ t.Fatalf("grepFile: pattern \"%s\" not found in \"%s\"", pattern, path) |
|
582 |
+} |
|
583 |
+ |
|
584 |
+func TestLXCConfig(t *testing.T) { |
|
585 |
+ docker, err := newTestDocker() |
|
586 |
+ if err != nil { |
|
587 |
+ t.Fatal(err) |
|
588 |
+ } |
|
589 |
+ // Ram is allocated randomly for testing |
|
590 |
+ rand.Seed(time.Now().UTC().UnixNano()) |
|
591 |
+ ramMin := 33554432 |
|
592 |
+ ramMax := 536870912 |
|
593 |
+ ram := ramMin + rand.Intn(ramMax-ramMin) |
|
594 |
+ container, err := docker.Create( |
|
595 |
+ "config_test", |
|
596 |
+ "/bin/true", |
|
597 |
+ []string{}, |
|
598 |
+ []string{testLayerPath}, |
|
599 |
+ &Config{ |
|
600 |
+ Hostname: "foobar", |
|
601 |
+ Ram: int64(ram), |
|
602 |
+ }, |
|
603 |
+ ) |
|
604 |
+ if err != nil { |
|
605 |
+ t.Fatal(err) |
|
606 |
+ } |
|
607 |
+ defer docker.Destroy(container) |
|
608 |
+ container.generateLXCConfig() |
|
609 |
+ grepFile(t, container.lxcConfigPath, "lxc.utsname = foobar") |
|
610 |
+ grepFile(t, container.lxcConfigPath, |
|
611 |
+ fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", ram)) |
|
612 |
+ grepFile(t, container.lxcConfigPath, |
|
613 |
+ fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", ram*2)) |
|
614 |
+} |
|
615 |
+ |
|
564 | 616 |
func BenchmarkRunSequencial(b *testing.B) { |
565 | 617 |
docker, err := newTestDocker() |
566 | 618 |
if err != nil { |
... | ... |
@@ -1,13 +1,12 @@ |
1 | 1 |
package rcli |
2 | 2 |
|
3 | 3 |
import ( |
4 |
+ "fmt" |
|
4 | 5 |
"net/http" |
5 | 6 |
"net/url" |
6 | 7 |
"path" |
7 |
- "fmt" |
|
8 | 8 |
) |
9 | 9 |
|
10 |
- |
|
11 | 10 |
// Use this key to encode an RPC call into an URL, |
12 | 11 |
// eg. domain.tld/path/to/method?q=get_user&q=gordon |
13 | 12 |
const ARG_URL_KEY = "q" |
... | ... |
@@ -16,18 +15,16 @@ func URLToCall(u *url.URL) (method string, args []string) { |
16 | 16 |
return path.Base(u.Path), u.Query()[ARG_URL_KEY] |
17 | 17 |
} |
18 | 18 |
|
19 |
- |
|
20 | 19 |
func ListenAndServeHTTP(addr string, service Service) error { |
21 | 20 |
return http.ListenAndServe(addr, http.HandlerFunc( |
22 |
- func (w http.ResponseWriter, r *http.Request) { |
|
21 |
+ func(w http.ResponseWriter, r *http.Request) { |
|
23 | 22 |
cmd, args := URLToCall(r.URL) |
24 | 23 |
if err := call(service, r.Body, &AutoFlush{w}, append([]string{cmd}, args...)...); err != nil { |
25 |
- fmt.Fprintf(w, "Error: " + err.Error() + "\n") |
|
24 |
+ fmt.Fprintf(w, "Error: "+err.Error()+"\n") |
|
26 | 25 |
} |
27 | 26 |
})) |
28 | 27 |
} |
29 | 28 |
|
30 |
- |
|
31 | 29 |
type AutoFlush struct { |
32 | 30 |
http.ResponseWriter |
33 | 31 |
} |
... | ... |
@@ -1,13 +1,13 @@ |
1 | 1 |
package rcli |
2 | 2 |
|
3 | 3 |
import ( |
4 |
+ "bufio" |
|
5 |
+ "encoding/json" |
|
6 |
+ "fmt" |
|
4 | 7 |
"io" |
5 | 8 |
"io/ioutil" |
6 |
- "net" |
|
7 | 9 |
"log" |
8 |
- "fmt" |
|
9 |
- "encoding/json" |
|
10 |
- "bufio" |
|
10 |
+ "net" |
|
11 | 11 |
) |
12 | 12 |
|
13 | 13 |
// Connect to a remote endpoint using protocol `proto` and address `addr`, |
... | ... |
@@ -44,7 +44,7 @@ func ListenAndServe(proto, addr string, service Service) error { |
44 | 44 |
go func() { |
45 | 45 |
if err := Serve(conn, service); err != nil { |
46 | 46 |
log.Printf("Error: " + err.Error() + "\n") |
47 |
- fmt.Fprintf(conn, "Error: " + err.Error() + "\n") |
|
47 |
+ fmt.Fprintf(conn, "Error: "+err.Error()+"\n") |
|
48 | 48 |
} |
49 | 49 |
conn.Close() |
50 | 50 |
}() |
... | ... |
@@ -53,7 +53,6 @@ func ListenAndServe(proto, addr string, service Service) error { |
53 | 53 |
return nil |
54 | 54 |
} |
55 | 55 |
|
56 |
- |
|
57 | 56 |
// Parse an rcli call on a new connection, and pass it to `service` if it |
58 | 57 |
// is valid. |
59 | 58 |
func Serve(conn io.ReadWriter, service Service) error { |
... | ... |
@@ -68,4 +67,3 @@ func Serve(conn io.ReadWriter, service Service) error { |
68 | 68 |
} |
69 | 69 |
return nil |
70 | 70 |
} |
71 |
- |
... | ... |
@@ -8,13 +8,13 @@ package rcli |
8 | 8 |
// are the usual suspects. |
9 | 9 |
|
10 | 10 |
import ( |
11 |
+ "errors" |
|
12 |
+ "flag" |
|
11 | 13 |
"fmt" |
12 | 14 |
"io" |
13 |
- "reflect" |
|
14 |
- "flag" |
|
15 | 15 |
"log" |
16 |
+ "reflect" |
|
16 | 17 |
"strings" |
17 |
- "errors" |
|
18 | 18 |
) |
19 | 19 |
|
20 | 20 |
type Service interface { |
... | ... |
@@ -25,7 +25,6 @@ type Service interface { |
25 | 25 |
type Cmd func(io.ReadCloser, io.Writer, ...string) error |
26 | 26 |
type CmdMethod func(Service, io.ReadCloser, io.Writer, ...string) error |
27 | 27 |
|
28 |
- |
|
29 | 28 |
func call(service Service, stdin io.ReadCloser, stdout io.Writer, args ...string) error { |
30 | 29 |
if len(args) == 0 { |
31 | 30 |
args = []string{"help"} |
... | ... |
@@ -63,7 +62,7 @@ func getMethod(service Service, name string) Cmd { |
63 | 63 |
return nil |
64 | 64 |
} |
65 | 65 |
} |
66 |
- methodName := "Cmd"+strings.ToUpper(name[:1])+strings.ToLower(name[1:]) |
|
66 |
+ methodName := "Cmd" + strings.ToUpper(name[:1]) + strings.ToLower(name[1:]) |
|
67 | 67 |
method, exists := reflect.TypeOf(service).MethodByName(methodName) |
68 | 68 |
if !exists { |
69 | 69 |
return nil |
... | ... |
@@ -91,4 +90,3 @@ func Subcmd(output io.Writer, name, signature, description string) *flag.FlagSet |
91 | 91 |
} |
92 | 92 |
return flags |
93 | 93 |
} |
94 |
- |