| ... | ... |
@@ -139,7 +139,7 @@ func InitContainer(c *Command) *configs.Config {
|
| 139 | 139 |
|
| 140 | 140 |
container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env)
|
| 141 | 141 |
container.Cgroups.Name = c.ID |
| 142 |
- container.Cgroups.AllowedDevices = c.AllowedDevices |
|
| 142 |
+ container.Cgroups.Resources.AllowedDevices = c.AllowedDevices |
|
| 143 | 143 |
container.Devices = c.AutoCreatedDevices |
| 144 | 144 |
container.Rootfs = c.Rootfs |
| 145 | 145 |
container.Readonlyfs = c.ReadonlyRootfs |
| ... | ... |
@@ -170,23 +170,23 @@ func getEnv(key string, env []string) string {
|
| 170 | 170 |
// SetupCgroups setups cgroup resources for a container. |
| 171 | 171 |
func SetupCgroups(container *configs.Config, c *Command) error {
|
| 172 | 172 |
if c.Resources != nil {
|
| 173 |
- container.Cgroups.CpuShares = c.Resources.CPUShares |
|
| 174 |
- container.Cgroups.Memory = c.Resources.Memory |
|
| 175 |
- container.Cgroups.MemoryReservation = c.Resources.MemoryReservation |
|
| 176 |
- container.Cgroups.MemorySwap = c.Resources.MemorySwap |
|
| 177 |
- container.Cgroups.KernelMemory = c.Resources.KernelMemory |
|
| 178 |
- container.Cgroups.CpusetCpus = c.Resources.CpusetCpus |
|
| 179 |
- container.Cgroups.CpusetMems = c.Resources.CpusetMems |
|
| 180 |
- container.Cgroups.CpuPeriod = c.Resources.CPUPeriod |
|
| 181 |
- container.Cgroups.CpuQuota = c.Resources.CPUQuota |
|
| 182 |
- container.Cgroups.BlkioWeight = c.Resources.BlkioWeight |
|
| 183 |
- container.Cgroups.BlkioWeightDevice = c.Resources.BlkioWeightDevice |
|
| 184 |
- container.Cgroups.BlkioThrottleReadBpsDevice = c.Resources.BlkioThrottleReadBpsDevice |
|
| 185 |
- container.Cgroups.BlkioThrottleWriteBpsDevice = c.Resources.BlkioThrottleWriteBpsDevice |
|
| 186 |
- container.Cgroups.BlkioThrottleReadIOPSDevice = c.Resources.BlkioThrottleReadIOpsDevice |
|
| 187 |
- container.Cgroups.BlkioThrottleWriteIOPSDevice = c.Resources.BlkioThrottleWriteIOpsDevice |
|
| 188 |
- container.Cgroups.OomKillDisable = c.Resources.OomKillDisable |
|
| 189 |
- container.Cgroups.MemorySwappiness = c.Resources.MemorySwappiness |
|
| 173 |
+ container.Cgroups.Resources.CpuShares = c.Resources.CPUShares |
|
| 174 |
+ container.Cgroups.Resources.Memory = c.Resources.Memory |
|
| 175 |
+ container.Cgroups.Resources.MemoryReservation = c.Resources.MemoryReservation |
|
| 176 |
+ container.Cgroups.Resources.MemorySwap = c.Resources.MemorySwap |
|
| 177 |
+ container.Cgroups.Resources.KernelMemory = c.Resources.KernelMemory |
|
| 178 |
+ container.Cgroups.Resources.CpusetCpus = c.Resources.CpusetCpus |
|
| 179 |
+ container.Cgroups.Resources.CpusetMems = c.Resources.CpusetMems |
|
| 180 |
+ container.Cgroups.Resources.CpuPeriod = c.Resources.CPUPeriod |
|
| 181 |
+ container.Cgroups.Resources.CpuQuota = c.Resources.CPUQuota |
|
| 182 |
+ container.Cgroups.Resources.BlkioWeight = c.Resources.BlkioWeight |
|
| 183 |
+ container.Cgroups.Resources.BlkioWeightDevice = c.Resources.BlkioWeightDevice |
|
| 184 |
+ container.Cgroups.Resources.BlkioThrottleReadBpsDevice = c.Resources.BlkioThrottleReadBpsDevice |
|
| 185 |
+ container.Cgroups.Resources.BlkioThrottleWriteBpsDevice = c.Resources.BlkioThrottleWriteBpsDevice |
|
| 186 |
+ container.Cgroups.Resources.BlkioThrottleReadIOPSDevice = c.Resources.BlkioThrottleReadIOpsDevice |
|
| 187 |
+ container.Cgroups.Resources.BlkioThrottleWriteIOPSDevice = c.Resources.BlkioThrottleWriteIOpsDevice |
|
| 188 |
+ container.Cgroups.Resources.OomKillDisable = c.Resources.OomKillDisable |
|
| 189 |
+ container.Cgroups.Resources.MemorySwappiness = c.Resources.MemorySwappiness |
|
| 190 | 190 |
} |
| 191 | 191 |
|
| 192 | 192 |
return nil |
| ... | ... |
@@ -251,7 +251,7 @@ func (d *Driver) setupRemappedRoot(container *configs.Config, c *execdriver.Comm |
| 251 | 251 |
|
| 252 | 252 |
func (d *Driver) setPrivileged(container *configs.Config) (err error) {
|
| 253 | 253 |
container.Capabilities = execdriver.GetAllCapabilities() |
| 254 |
- container.Cgroups.AllowAllDevices = true |
|
| 254 |
+ container.Cgroups.Resources.AllowAllDevices = true |
|
| 255 | 255 |
|
| 256 | 256 |
hostDevices, err := devices.HostDevices() |
| 257 | 257 |
if err != nil {
|
| ... | ... |
@@ -385,7 +385,7 @@ func (d *Driver) Stats(id string) (*execdriver.ResourceStats, error) {
|
| 385 | 385 |
if err != nil {
|
| 386 | 386 |
return nil, err |
| 387 | 387 |
} |
| 388 |
- memoryLimit := c.Config().Cgroups.Memory |
|
| 388 |
+ memoryLimit := c.Config().Cgroups.Resources.Memory |
|
| 389 | 389 |
// if the container does not have any memory limit specified set the |
| 390 | 390 |
// limit to the machines memory |
| 391 | 391 |
if memoryLimit == 0 {
|
| ... | ... |
@@ -40,9 +40,11 @@ func New() *configs.Config {
|
| 40 | 40 |
{Type: "NEWUSER"},
|
| 41 | 41 |
}), |
| 42 | 42 |
Cgroups: &configs.Cgroup{
|
| 43 |
- Parent: "/docker", |
|
| 44 |
- AllowAllDevices: false, |
|
| 45 |
- MemorySwappiness: -1, |
|
| 43 |
+ Parent: "/docker", |
|
| 44 |
+ Resources: &configs.Resources{
|
|
| 45 |
+ AllowAllDevices: false, |
|
| 46 |
+ MemorySwappiness: -1, |
|
| 47 |
+ }, |
|
| 46 | 48 |
}, |
| 47 | 49 |
Mounts: []*configs.Mount{
|
| 48 | 50 |
{
|
| ... | ... |
@@ -51,7 +51,7 @@ clone git github.com/miekg/pkcs11 80f102b5cac759de406949c47f0928b99bd64cdf |
| 51 | 51 |
clone git github.com/jfrazelle/go v1.5.1-1 |
| 52 | 52 |
clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c |
| 53 | 53 |
|
| 54 |
-clone git github.com/opencontainers/runc ba1568de399395774ad84c2ace65937814c542ed # libcontainer |
|
| 54 |
+clone git github.com/opencontainers/runc d97d5e8b007e4657316eed76ea30bc0f690230cf # libcontainer |
|
| 55 | 55 |
clone git github.com/opencontainers/specs 46d949ea81080c5f60dfb72ee91468b1e9fb2998 # specs |
| 56 | 56 |
clone git github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c226cfc6a1 |
| 57 | 57 |
# libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json) |
| 58 | 58 |
deleted file mode 100644 |
| ... | ... |
@@ -1,55 +0,0 @@ |
| 1 |
-# Contributing to Docker |
|
| 2 |
- |
|
| 3 |
-### Sign your work |
|
| 4 |
- |
|
| 5 |
-The sign-off is a simple line at the end of the explanation for the patch. Your |
|
| 6 |
-signature certifies that you wrote the patch or otherwise have the right to pass |
|
| 7 |
-it on as an open-source patch. The rules are pretty simple: if you can certify |
|
| 8 |
-the below (from [developercertificate.org](http://developercertificate.org/)): |
|
| 9 |
- |
|
| 10 |
-``` |
|
| 11 |
-Developer Certificate of Origin |
|
| 12 |
-Version 1.1 |
|
| 13 |
- |
|
| 14 |
-Copyright (C) 2004, 2006 The Linux Foundation and its contributors. |
|
| 15 |
-660 York Street, Suite 102, |
|
| 16 |
-San Francisco, CA 94110 USA |
|
| 17 |
- |
|
| 18 |
-Everyone is permitted to copy and distribute verbatim copies of this |
|
| 19 |
-license document, but changing it is not allowed. |
|
| 20 |
- |
|
| 21 |
-Developer's Certificate of Origin 1.1 |
|
| 22 |
- |
|
| 23 |
-By making a contribution to this project, I certify that: |
|
| 24 |
- |
|
| 25 |
-(a) The contribution was created in whole or in part by me and I |
|
| 26 |
- have the right to submit it under the open source license |
|
| 27 |
- indicated in the file; or |
|
| 28 |
- |
|
| 29 |
-(b) The contribution is based upon previous work that, to the best |
|
| 30 |
- of my knowledge, is covered under an appropriate open source |
|
| 31 |
- license and I have the right under that license to submit that |
|
| 32 |
- work with modifications, whether created in whole or in part |
|
| 33 |
- by me, under the same open source license (unless I am |
|
| 34 |
- permitted to submit under a different license), as indicated |
|
| 35 |
- in the file; or |
|
| 36 |
- |
|
| 37 |
-(c) The contribution was provided directly to me by some other |
|
| 38 |
- person who certified (a), (b) or (c) and I have not modified |
|
| 39 |
- it. |
|
| 40 |
- |
|
| 41 |
-(d) I understand and agree that this project and the contribution |
|
| 42 |
- are public and that a record of the contribution (including all |
|
| 43 |
- personal information I submit with it, including my sign-off) is |
|
| 44 |
- maintained indefinitely and may be redistributed consistent with |
|
| 45 |
- this project or the open source license(s) involved. |
|
| 46 |
-``` |
|
| 47 |
- |
|
| 48 |
-Then you just add a line to every git commit message: |
|
| 49 |
- |
|
| 50 |
- Signed-off-by: Joe Smith <joe.smith@email.com> |
|
| 51 |
- |
|
| 52 |
-Use your real name (sorry, no pseudonyms or anonymous contributions.) |
|
| 53 |
- |
|
| 54 |
-If you set your `user.name` and `user.email` git configs, you can sign your |
|
| 55 |
-commit automatically with `git commit -s`. |
| 56 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,27 +0,0 @@ |
| 1 |
-# go-connections maintainers file |
|
| 2 |
-# |
|
| 3 |
-# This file describes who runs the docker/go-connections project and how. |
|
| 4 |
-# This is a living document - if you see something out of date or missing, speak up! |
|
| 5 |
-# |
|
| 6 |
-# It is structured to be consumable by both humans and programs. |
|
| 7 |
-# To extract its contents programmatically, use any TOML-compliant parser. |
|
| 8 |
-# |
|
| 9 |
-# This file is compiled into the MAINTAINERS file in docker/opensource. |
|
| 10 |
-# |
|
| 11 |
-[Org] |
|
| 12 |
- [Org."Core maintainers"] |
|
| 13 |
- people = [ |
|
| 14 |
- "calavera", |
|
| 15 |
- ] |
|
| 16 |
- |
|
| 17 |
-[people] |
|
| 18 |
- |
|
| 19 |
-# A reference list of all people associated with the project. |
|
| 20 |
-# All other sections should refer to people by their canonical key |
|
| 21 |
-# in the people section. |
|
| 22 |
- |
|
| 23 |
- # ADD YOURSELF HERE IN ALPHABETICAL ORDER |
|
| 24 |
- [people.calavera] |
|
| 25 |
- Name = "David Calavera" |
|
| 26 |
- Email = "david.calavera@gmail.com" |
|
| 27 |
- GitHub = "calavera" |
| 28 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,13 +0,0 @@ |
| 1 |
-[](https://godoc.org/github.com/docker/go-connections) |
|
| 2 |
- |
|
| 3 |
-# Introduction |
|
| 4 |
- |
|
| 5 |
-go-connections provides common package to work with network connections. |
|
| 6 |
- |
|
| 7 |
-## Usage |
|
| 8 |
- |
|
| 9 |
-See the [docs in godoc](https://godoc.org/github.com/docker/go-connections) for examples and documentation. |
|
| 10 |
- |
|
| 11 |
-## License |
|
| 12 |
- |
|
| 13 |
-go-connections is licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for the full license text. |
| 14 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,14 +0,0 @@ |
| 1 |
-dependencies: |
|
| 2 |
- pre: |
|
| 3 |
- # setup ipv6 |
|
| 4 |
- - sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=0 net.ipv6.conf.default.disable_ipv6=0 net.ipv6.conf.all.disable_ipv6=0 |
|
| 5 |
- post: |
|
| 6 |
- # install golint |
|
| 7 |
- - go get github.com/golang/lint/golint |
|
| 8 |
- |
|
| 9 |
-test: |
|
| 10 |
- pre: |
|
| 11 |
- # run analysis before tests |
|
| 12 |
- - go vet ./... |
|
| 13 |
- - test -z "$(golint ./... | tee /dev/stderr)" |
|
| 14 |
- - test -z "$(gofmt -s -l . | tee /dev/stderr)" |
| 4 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,525 +0,0 @@ |
| 1 |
-package nat |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "testing" |
|
| 5 |
-) |
|
| 6 |
- |
|
| 7 |
-func TestParsePort(t *testing.T) {
|
|
| 8 |
- var ( |
|
| 9 |
- p int |
|
| 10 |
- err error |
|
| 11 |
- ) |
|
| 12 |
- |
|
| 13 |
- p, err = ParsePort("1234")
|
|
| 14 |
- |
|
| 15 |
- if err != nil || p != 1234 {
|
|
| 16 |
- t.Fatal("Parsing '1234' did not succeed")
|
|
| 17 |
- } |
|
| 18 |
- |
|
| 19 |
- // FIXME currently this is a valid port. I don't think it should be. |
|
| 20 |
- // I'm leaving this test commented out until we make a decision. |
|
| 21 |
- // - erikh |
|
| 22 |
- |
|
| 23 |
- /* |
|
| 24 |
- p, err = ParsePort("0123")
|
|
| 25 |
- |
|
| 26 |
- if err != nil {
|
|
| 27 |
- t.Fatal("Successfully parsed port '0123' to '123'")
|
|
| 28 |
- } |
|
| 29 |
- */ |
|
| 30 |
- |
|
| 31 |
- p, err = ParsePort("asdf")
|
|
| 32 |
- |
|
| 33 |
- if err == nil || p != 0 {
|
|
| 34 |
- t.Fatal("Parsing port 'asdf' succeeded")
|
|
| 35 |
- } |
|
| 36 |
- |
|
| 37 |
- p, err = ParsePort("1asdf")
|
|
| 38 |
- |
|
| 39 |
- if err == nil || p != 0 {
|
|
| 40 |
- t.Fatal("Parsing port '1asdf' succeeded")
|
|
| 41 |
- } |
|
| 42 |
-} |
|
| 43 |
- |
|
| 44 |
-func TestParsePortRangeToInt(t *testing.T) {
|
|
| 45 |
- var ( |
|
| 46 |
- begin int |
|
| 47 |
- end int |
|
| 48 |
- err error |
|
| 49 |
- ) |
|
| 50 |
- |
|
| 51 |
- type TestRange struct {
|
|
| 52 |
- Range string |
|
| 53 |
- Begin int |
|
| 54 |
- End int |
|
| 55 |
- } |
|
| 56 |
- validRanges := []TestRange{
|
|
| 57 |
- {"1234", 1234, 1234},
|
|
| 58 |
- {"1234-1234", 1234, 1234},
|
|
| 59 |
- {"1234-1235", 1234, 1235},
|
|
| 60 |
- {"8000-9000", 8000, 9000},
|
|
| 61 |
- {"0", 0, 0},
|
|
| 62 |
- {"0-0", 0, 0},
|
|
| 63 |
- } |
|
| 64 |
- |
|
| 65 |
- for _, r := range validRanges {
|
|
| 66 |
- begin, end, err = ParsePortRangeToInt(r.Range) |
|
| 67 |
- |
|
| 68 |
- if err != nil || begin != r.Begin {
|
|
| 69 |
- t.Fatalf("Parsing port range '%s' did not succeed. Expected begin %d, got %d", r.Range, r.Begin, begin)
|
|
| 70 |
- } |
|
| 71 |
- if err != nil || end != r.End {
|
|
| 72 |
- t.Fatalf("Parsing port range '%s' did not succeed. Expected end %d, got %d", r.Range, r.End, end)
|
|
| 73 |
- } |
|
| 74 |
- } |
|
| 75 |
- |
|
| 76 |
- invalidRanges := []string{
|
|
| 77 |
- "asdf", |
|
| 78 |
- "1asdf", |
|
| 79 |
- "9000-8000", |
|
| 80 |
- "9000-", |
|
| 81 |
- "-8000", |
|
| 82 |
- "-8000-", |
|
| 83 |
- } |
|
| 84 |
- |
|
| 85 |
- for _, r := range invalidRanges {
|
|
| 86 |
- begin, end, err = ParsePortRangeToInt(r) |
|
| 87 |
- |
|
| 88 |
- if err == nil || begin != 0 || end != 0 {
|
|
| 89 |
- t.Fatalf("Parsing port range '%s' succeeded", r)
|
|
| 90 |
- } |
|
| 91 |
- } |
|
| 92 |
-} |
|
| 93 |
- |
|
| 94 |
-func TestPort(t *testing.T) {
|
|
| 95 |
- p, err := NewPort("tcp", "1234")
|
|
| 96 |
- |
|
| 97 |
- if err != nil {
|
|
| 98 |
- t.Fatalf("tcp, 1234 had a parsing issue: %v", err)
|
|
| 99 |
- } |
|
| 100 |
- |
|
| 101 |
- if string(p) != "1234/tcp" {
|
|
| 102 |
- t.Fatal("tcp, 1234 did not result in the string 1234/tcp")
|
|
| 103 |
- } |
|
| 104 |
- |
|
| 105 |
- if p.Proto() != "tcp" {
|
|
| 106 |
- t.Fatal("protocol was not tcp")
|
|
| 107 |
- } |
|
| 108 |
- |
|
| 109 |
- if p.Port() != "1234" {
|
|
| 110 |
- t.Fatal("port string value was not 1234")
|
|
| 111 |
- } |
|
| 112 |
- |
|
| 113 |
- if p.Int() != 1234 {
|
|
| 114 |
- t.Fatal("port int value was not 1234")
|
|
| 115 |
- } |
|
| 116 |
- |
|
| 117 |
- p, err = NewPort("tcp", "asd1234")
|
|
| 118 |
- if err == nil {
|
|
| 119 |
- t.Fatal("tcp, asd1234 was supposed to fail")
|
|
| 120 |
- } |
|
| 121 |
- |
|
| 122 |
- p, err = NewPort("tcp", "1234-1230")
|
|
| 123 |
- if err == nil {
|
|
| 124 |
- t.Fatal("tcp, 1234-1230 was supposed to fail")
|
|
| 125 |
- } |
|
| 126 |
- |
|
| 127 |
- p, err = NewPort("tcp", "1234-1242")
|
|
| 128 |
- if err != nil {
|
|
| 129 |
- t.Fatalf("tcp, 1234-1242 had a parsing issue: %v", err)
|
|
| 130 |
- } |
|
| 131 |
- |
|
| 132 |
- if string(p) != "1234-1242/tcp" {
|
|
| 133 |
- t.Fatal("tcp, 1234-1242 did not result in the string 1234-1242/tcp")
|
|
| 134 |
- } |
|
| 135 |
-} |
|
| 136 |
- |
|
| 137 |
-func TestSplitProtoPort(t *testing.T) {
|
|
| 138 |
- var ( |
|
| 139 |
- proto string |
|
| 140 |
- port string |
|
| 141 |
- ) |
|
| 142 |
- |
|
| 143 |
- proto, port = SplitProtoPort("1234/tcp")
|
|
| 144 |
- |
|
| 145 |
- if proto != "tcp" || port != "1234" {
|
|
| 146 |
- t.Fatal("Could not split 1234/tcp properly")
|
|
| 147 |
- } |
|
| 148 |
- |
|
| 149 |
- proto, port = SplitProtoPort("")
|
|
| 150 |
- |
|
| 151 |
- if proto != "" || port != "" {
|
|
| 152 |
- t.Fatal("parsing an empty string yielded surprising results", proto, port)
|
|
| 153 |
- } |
|
| 154 |
- |
|
| 155 |
- proto, port = SplitProtoPort("1234")
|
|
| 156 |
- |
|
| 157 |
- if proto != "tcp" || port != "1234" {
|
|
| 158 |
- t.Fatal("tcp is not the default protocol for portspec '1234'", proto, port)
|
|
| 159 |
- } |
|
| 160 |
- |
|
| 161 |
- proto, port = SplitProtoPort("1234/")
|
|
| 162 |
- |
|
| 163 |
- if proto != "tcp" || port != "1234" {
|
|
| 164 |
- t.Fatal("parsing '1234/' yielded:" + port + "/" + proto)
|
|
| 165 |
- } |
|
| 166 |
- |
|
| 167 |
- proto, port = SplitProtoPort("/tcp")
|
|
| 168 |
- |
|
| 169 |
- if proto != "" || port != "" {
|
|
| 170 |
- t.Fatal("parsing '/tcp' yielded:" + port + "/" + proto)
|
|
| 171 |
- } |
|
| 172 |
-} |
|
| 173 |
- |
|
| 174 |
-func TestParsePortSpecs(t *testing.T) {
|
|
| 175 |
- var ( |
|
| 176 |
- portMap map[Port]struct{}
|
|
| 177 |
- bindingMap map[Port][]PortBinding |
|
| 178 |
- err error |
|
| 179 |
- ) |
|
| 180 |
- |
|
| 181 |
- portMap, bindingMap, err = ParsePortSpecs([]string{"1234/tcp", "2345/udp"})
|
|
| 182 |
- |
|
| 183 |
- if err != nil {
|
|
| 184 |
- t.Fatalf("Error while processing ParsePortSpecs: %s", err)
|
|
| 185 |
- } |
|
| 186 |
- |
|
| 187 |
- if _, ok := portMap[Port("1234/tcp")]; !ok {
|
|
| 188 |
- t.Fatal("1234/tcp was not parsed properly")
|
|
| 189 |
- } |
|
| 190 |
- |
|
| 191 |
- if _, ok := portMap[Port("2345/udp")]; !ok {
|
|
| 192 |
- t.Fatal("2345/udp was not parsed properly")
|
|
| 193 |
- } |
|
| 194 |
- |
|
| 195 |
- for portspec, bindings := range bindingMap {
|
|
| 196 |
- if len(bindings) != 1 {
|
|
| 197 |
- t.Fatalf("%s should have exactly one binding", portspec)
|
|
| 198 |
- } |
|
| 199 |
- |
|
| 200 |
- if bindings[0].HostIP != "" {
|
|
| 201 |
- t.Fatalf("HostIP should not be set for %s", portspec)
|
|
| 202 |
- } |
|
| 203 |
- |
|
| 204 |
- if bindings[0].HostPort != "" {
|
|
| 205 |
- t.Fatalf("HostPort should not be set for %s", portspec)
|
|
| 206 |
- } |
|
| 207 |
- } |
|
| 208 |
- |
|
| 209 |
- portMap, bindingMap, err = ParsePortSpecs([]string{"1234:1234/tcp", "2345:2345/udp"})
|
|
| 210 |
- |
|
| 211 |
- if err != nil {
|
|
| 212 |
- t.Fatalf("Error while processing ParsePortSpecs: %s", err)
|
|
| 213 |
- } |
|
| 214 |
- |
|
| 215 |
- if _, ok := portMap[Port("1234/tcp")]; !ok {
|
|
| 216 |
- t.Fatal("1234/tcp was not parsed properly")
|
|
| 217 |
- } |
|
| 218 |
- |
|
| 219 |
- if _, ok := portMap[Port("2345/udp")]; !ok {
|
|
| 220 |
- t.Fatal("2345/udp was not parsed properly")
|
|
| 221 |
- } |
|
| 222 |
- |
|
| 223 |
- for portspec, bindings := range bindingMap {
|
|
| 224 |
- _, port := SplitProtoPort(string(portspec)) |
|
| 225 |
- |
|
| 226 |
- if len(bindings) != 1 {
|
|
| 227 |
- t.Fatalf("%s should have exactly one binding", portspec)
|
|
| 228 |
- } |
|
| 229 |
- |
|
| 230 |
- if bindings[0].HostIP != "" {
|
|
| 231 |
- t.Fatalf("HostIP should not be set for %s", portspec)
|
|
| 232 |
- } |
|
| 233 |
- |
|
| 234 |
- if bindings[0].HostPort != port {
|
|
| 235 |
- t.Fatalf("HostPort should be %s for %s", port, portspec)
|
|
| 236 |
- } |
|
| 237 |
- } |
|
| 238 |
- |
|
| 239 |
- portMap, bindingMap, err = ParsePortSpecs([]string{"0.0.0.0:1234:1234/tcp", "0.0.0.0:2345:2345/udp"})
|
|
| 240 |
- |
|
| 241 |
- if err != nil {
|
|
| 242 |
- t.Fatalf("Error while processing ParsePortSpecs: %s", err)
|
|
| 243 |
- } |
|
| 244 |
- |
|
| 245 |
- if _, ok := portMap[Port("1234/tcp")]; !ok {
|
|
| 246 |
- t.Fatal("1234/tcp was not parsed properly")
|
|
| 247 |
- } |
|
| 248 |
- |
|
| 249 |
- if _, ok := portMap[Port("2345/udp")]; !ok {
|
|
| 250 |
- t.Fatal("2345/udp was not parsed properly")
|
|
| 251 |
- } |
|
| 252 |
- |
|
| 253 |
- for portspec, bindings := range bindingMap {
|
|
| 254 |
- _, port := SplitProtoPort(string(portspec)) |
|
| 255 |
- |
|
| 256 |
- if len(bindings) != 1 {
|
|
| 257 |
- t.Fatalf("%s should have exactly one binding", portspec)
|
|
| 258 |
- } |
|
| 259 |
- |
|
| 260 |
- if bindings[0].HostIP != "0.0.0.0" {
|
|
| 261 |
- t.Fatalf("HostIP is not 0.0.0.0 for %s", portspec)
|
|
| 262 |
- } |
|
| 263 |
- |
|
| 264 |
- if bindings[0].HostPort != port {
|
|
| 265 |
- t.Fatalf("HostPort should be %s for %s", port, portspec)
|
|
| 266 |
- } |
|
| 267 |
- } |
|
| 268 |
- |
|
| 269 |
- _, _, err = ParsePortSpecs([]string{"localhost:1234:1234/tcp"})
|
|
| 270 |
- |
|
| 271 |
- if err == nil {
|
|
| 272 |
- t.Fatal("Received no error while trying to parse a hostname instead of ip")
|
|
| 273 |
- } |
|
| 274 |
-} |
|
| 275 |
- |
|
| 276 |
-func TestParsePortSpecsWithRange(t *testing.T) {
|
|
| 277 |
- var ( |
|
| 278 |
- portMap map[Port]struct{}
|
|
| 279 |
- bindingMap map[Port][]PortBinding |
|
| 280 |
- err error |
|
| 281 |
- ) |
|
| 282 |
- |
|
| 283 |
- portMap, bindingMap, err = ParsePortSpecs([]string{"1234-1236/tcp", "2345-2347/udp"})
|
|
| 284 |
- |
|
| 285 |
- if err != nil {
|
|
| 286 |
- t.Fatalf("Error while processing ParsePortSpecs: %s", err)
|
|
| 287 |
- } |
|
| 288 |
- |
|
| 289 |
- if _, ok := portMap[Port("1235/tcp")]; !ok {
|
|
| 290 |
- t.Fatal("1234/tcp was not parsed properly")
|
|
| 291 |
- } |
|
| 292 |
- |
|
| 293 |
- if _, ok := portMap[Port("2346/udp")]; !ok {
|
|
| 294 |
- t.Fatal("2345/udp was not parsed properly")
|
|
| 295 |
- } |
|
| 296 |
- |
|
| 297 |
- for portspec, bindings := range bindingMap {
|
|
| 298 |
- if len(bindings) != 1 {
|
|
| 299 |
- t.Fatalf("%s should have exactly one binding", portspec)
|
|
| 300 |
- } |
|
| 301 |
- |
|
| 302 |
- if bindings[0].HostIP != "" {
|
|
| 303 |
- t.Fatalf("HostIP should not be set for %s", portspec)
|
|
| 304 |
- } |
|
| 305 |
- |
|
| 306 |
- if bindings[0].HostPort != "" {
|
|
| 307 |
- t.Fatalf("HostPort should not be set for %s", portspec)
|
|
| 308 |
- } |
|
| 309 |
- } |
|
| 310 |
- |
|
| 311 |
- portMap, bindingMap, err = ParsePortSpecs([]string{"1234-1236:1234-1236/tcp", "2345-2347:2345-2347/udp"})
|
|
| 312 |
- |
|
| 313 |
- if err != nil {
|
|
| 314 |
- t.Fatalf("Error while processing ParsePortSpecs: %s", err)
|
|
| 315 |
- } |
|
| 316 |
- |
|
| 317 |
- if _, ok := portMap[Port("1235/tcp")]; !ok {
|
|
| 318 |
- t.Fatal("1234/tcp was not parsed properly")
|
|
| 319 |
- } |
|
| 320 |
- |
|
| 321 |
- if _, ok := portMap[Port("2346/udp")]; !ok {
|
|
| 322 |
- t.Fatal("2345/udp was not parsed properly")
|
|
| 323 |
- } |
|
| 324 |
- |
|
| 325 |
- for portspec, bindings := range bindingMap {
|
|
| 326 |
- _, port := SplitProtoPort(string(portspec)) |
|
| 327 |
- if len(bindings) != 1 {
|
|
| 328 |
- t.Fatalf("%s should have exactly one binding", portspec)
|
|
| 329 |
- } |
|
| 330 |
- |
|
| 331 |
- if bindings[0].HostIP != "" {
|
|
| 332 |
- t.Fatalf("HostIP should not be set for %s", portspec)
|
|
| 333 |
- } |
|
| 334 |
- |
|
| 335 |
- if bindings[0].HostPort != port {
|
|
| 336 |
- t.Fatalf("HostPort should be %s for %s", port, portspec)
|
|
| 337 |
- } |
|
| 338 |
- } |
|
| 339 |
- |
|
| 340 |
- portMap, bindingMap, err = ParsePortSpecs([]string{"0.0.0.0:1234-1236:1234-1236/tcp", "0.0.0.0:2345-2347:2345-2347/udp"})
|
|
| 341 |
- |
|
| 342 |
- if err != nil {
|
|
| 343 |
- t.Fatalf("Error while processing ParsePortSpecs: %s", err)
|
|
| 344 |
- } |
|
| 345 |
- |
|
| 346 |
- if _, ok := portMap[Port("1235/tcp")]; !ok {
|
|
| 347 |
- t.Fatal("1234/tcp was not parsed properly")
|
|
| 348 |
- } |
|
| 349 |
- |
|
| 350 |
- if _, ok := portMap[Port("2346/udp")]; !ok {
|
|
| 351 |
- t.Fatal("2345/udp was not parsed properly")
|
|
| 352 |
- } |
|
| 353 |
- |
|
| 354 |
- for portspec, bindings := range bindingMap {
|
|
| 355 |
- _, port := SplitProtoPort(string(portspec)) |
|
| 356 |
- if len(bindings) != 1 || bindings[0].HostIP != "0.0.0.0" || bindings[0].HostPort != port {
|
|
| 357 |
- t.Fatalf("Expect single binding to port %s but found %s", port, bindings)
|
|
| 358 |
- } |
|
| 359 |
- } |
|
| 360 |
- |
|
| 361 |
- _, _, err = ParsePortSpecs([]string{"localhost:1234-1236:1234-1236/tcp"})
|
|
| 362 |
- |
|
| 363 |
- if err == nil {
|
|
| 364 |
- t.Fatal("Received no error while trying to parse a hostname instead of ip")
|
|
| 365 |
- } |
|
| 366 |
-} |
|
| 367 |
- |
|
| 368 |
-func TestParseNetworkOptsPrivateOnly(t *testing.T) {
|
|
| 369 |
- ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100::80"})
|
|
| 370 |
- if err != nil {
|
|
| 371 |
- t.Fatal(err) |
|
| 372 |
- } |
|
| 373 |
- if len(ports) != 1 {
|
|
| 374 |
- t.Logf("Expected 1 got %d", len(ports))
|
|
| 375 |
- t.FailNow() |
|
| 376 |
- } |
|
| 377 |
- if len(bindings) != 1 {
|
|
| 378 |
- t.Logf("Expected 1 got %d", len(bindings))
|
|
| 379 |
- t.FailNow() |
|
| 380 |
- } |
|
| 381 |
- for k := range ports {
|
|
| 382 |
- if k.Proto() != "tcp" {
|
|
| 383 |
- t.Logf("Expected tcp got %s", k.Proto())
|
|
| 384 |
- t.Fail() |
|
| 385 |
- } |
|
| 386 |
- if k.Port() != "80" {
|
|
| 387 |
- t.Logf("Expected 80 got %s", k.Port())
|
|
| 388 |
- t.Fail() |
|
| 389 |
- } |
|
| 390 |
- b, exists := bindings[k] |
|
| 391 |
- if !exists {
|
|
| 392 |
- t.Log("Binding does not exist")
|
|
| 393 |
- t.FailNow() |
|
| 394 |
- } |
|
| 395 |
- if len(b) != 1 {
|
|
| 396 |
- t.Logf("Expected 1 got %d", len(b))
|
|
| 397 |
- t.FailNow() |
|
| 398 |
- } |
|
| 399 |
- s := b[0] |
|
| 400 |
- if s.HostPort != "" {
|
|
| 401 |
- t.Logf("Expected \"\" got %s", s.HostPort)
|
|
| 402 |
- t.Fail() |
|
| 403 |
- } |
|
| 404 |
- if s.HostIP != "192.168.1.100" {
|
|
| 405 |
- t.Fail() |
|
| 406 |
- } |
|
| 407 |
- } |
|
| 408 |
-} |
|
| 409 |
- |
|
| 410 |
-func TestParseNetworkOptsPublic(t *testing.T) {
|
|
| 411 |
- ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100:8080:80"})
|
|
| 412 |
- if err != nil {
|
|
| 413 |
- t.Fatal(err) |
|
| 414 |
- } |
|
| 415 |
- if len(ports) != 1 {
|
|
| 416 |
- t.Logf("Expected 1 got %d", len(ports))
|
|
| 417 |
- t.FailNow() |
|
| 418 |
- } |
|
| 419 |
- if len(bindings) != 1 {
|
|
| 420 |
- t.Logf("Expected 1 got %d", len(bindings))
|
|
| 421 |
- t.FailNow() |
|
| 422 |
- } |
|
| 423 |
- for k := range ports {
|
|
| 424 |
- if k.Proto() != "tcp" {
|
|
| 425 |
- t.Logf("Expected tcp got %s", k.Proto())
|
|
| 426 |
- t.Fail() |
|
| 427 |
- } |
|
| 428 |
- if k.Port() != "80" {
|
|
| 429 |
- t.Logf("Expected 80 got %s", k.Port())
|
|
| 430 |
- t.Fail() |
|
| 431 |
- } |
|
| 432 |
- b, exists := bindings[k] |
|
| 433 |
- if !exists {
|
|
| 434 |
- t.Log("Binding does not exist")
|
|
| 435 |
- t.FailNow() |
|
| 436 |
- } |
|
| 437 |
- if len(b) != 1 {
|
|
| 438 |
- t.Logf("Expected 1 got %d", len(b))
|
|
| 439 |
- t.FailNow() |
|
| 440 |
- } |
|
| 441 |
- s := b[0] |
|
| 442 |
- if s.HostPort != "8080" {
|
|
| 443 |
- t.Logf("Expected 8080 got %s", s.HostPort)
|
|
| 444 |
- t.Fail() |
|
| 445 |
- } |
|
| 446 |
- if s.HostIP != "192.168.1.100" {
|
|
| 447 |
- t.Fail() |
|
| 448 |
- } |
|
| 449 |
- } |
|
| 450 |
-} |
|
| 451 |
- |
|
| 452 |
-func TestParseNetworkOptsPublicNoPort(t *testing.T) {
|
|
| 453 |
- ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100"})
|
|
| 454 |
- |
|
| 455 |
- if err == nil {
|
|
| 456 |
- t.Logf("Expected error Invalid containerPort")
|
|
| 457 |
- t.Fail() |
|
| 458 |
- } |
|
| 459 |
- if ports != nil {
|
|
| 460 |
- t.Logf("Expected nil got %s", ports)
|
|
| 461 |
- t.Fail() |
|
| 462 |
- } |
|
| 463 |
- if bindings != nil {
|
|
| 464 |
- t.Logf("Expected nil got %s", bindings)
|
|
| 465 |
- t.Fail() |
|
| 466 |
- } |
|
| 467 |
-} |
|
| 468 |
- |
|
| 469 |
-func TestParseNetworkOptsNegativePorts(t *testing.T) {
|
|
| 470 |
- ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100:-1:-1"})
|
|
| 471 |
- |
|
| 472 |
- if err == nil {
|
|
| 473 |
- t.Fail() |
|
| 474 |
- } |
|
| 475 |
- if len(ports) != 0 {
|
|
| 476 |
- t.Logf("Expected nil got %d", len(ports))
|
|
| 477 |
- t.Fail() |
|
| 478 |
- } |
|
| 479 |
- if len(bindings) != 0 {
|
|
| 480 |
- t.Logf("Expected 0 got %d", len(bindings))
|
|
| 481 |
- t.Fail() |
|
| 482 |
- } |
|
| 483 |
-} |
|
| 484 |
- |
|
| 485 |
-func TestParseNetworkOptsUdp(t *testing.T) {
|
|
| 486 |
- ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100::6000/udp"})
|
|
| 487 |
- if err != nil {
|
|
| 488 |
- t.Fatal(err) |
|
| 489 |
- } |
|
| 490 |
- if len(ports) != 1 {
|
|
| 491 |
- t.Logf("Expected 1 got %d", len(ports))
|
|
| 492 |
- t.FailNow() |
|
| 493 |
- } |
|
| 494 |
- if len(bindings) != 1 {
|
|
| 495 |
- t.Logf("Expected 1 got %d", len(bindings))
|
|
| 496 |
- t.FailNow() |
|
| 497 |
- } |
|
| 498 |
- for k := range ports {
|
|
| 499 |
- if k.Proto() != "udp" {
|
|
| 500 |
- t.Logf("Expected udp got %s", k.Proto())
|
|
| 501 |
- t.Fail() |
|
| 502 |
- } |
|
| 503 |
- if k.Port() != "6000" {
|
|
| 504 |
- t.Logf("Expected 6000 got %s", k.Port())
|
|
| 505 |
- t.Fail() |
|
| 506 |
- } |
|
| 507 |
- b, exists := bindings[k] |
|
| 508 |
- if !exists {
|
|
| 509 |
- t.Log("Binding does not exist")
|
|
| 510 |
- t.FailNow() |
|
| 511 |
- } |
|
| 512 |
- if len(b) != 1 {
|
|
| 513 |
- t.Logf("Expected 1 got %d", len(b))
|
|
| 514 |
- t.FailNow() |
|
| 515 |
- } |
|
| 516 |
- s := b[0] |
|
| 517 |
- if s.HostPort != "" {
|
|
| 518 |
- t.Logf("Expected \"\" got %s", s.HostPort)
|
|
| 519 |
- t.Fail() |
|
| 520 |
- } |
|
| 521 |
- if s.HostIP != "192.168.1.100" {
|
|
| 522 |
- t.Fail() |
|
| 523 |
- } |
|
| 524 |
- } |
|
| 525 |
-} |
| 526 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,54 +0,0 @@ |
| 1 |
-package nat |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "strings" |
|
| 5 |
- "testing" |
|
| 6 |
-) |
|
| 7 |
- |
|
| 8 |
-func TestParsePortRange(t *testing.T) {
|
|
| 9 |
- if start, end, err := ParsePortRange("8000-8080"); err != nil || start != 8000 || end != 8080 {
|
|
| 10 |
- t.Fatalf("Error: %s or Expecting {start,end} values {8000,8080} but found {%d,%d}.", err, start, end)
|
|
| 11 |
- } |
|
| 12 |
-} |
|
| 13 |
- |
|
| 14 |
-func TestParsePortRangeEmpty(t *testing.T) {
|
|
| 15 |
- if _, _, err := ParsePortRange(""); err == nil || err.Error() != "Empty string specified for ports." {
|
|
| 16 |
- t.Fatalf("Expected error 'Empty string specified for ports.', got %v", err)
|
|
| 17 |
- } |
|
| 18 |
-} |
|
| 19 |
- |
|
| 20 |
-func TestParsePortRangeWithNoRange(t *testing.T) {
|
|
| 21 |
- start, end, err := ParsePortRange("8080")
|
|
| 22 |
- if err != nil {
|
|
| 23 |
- t.Fatal(err) |
|
| 24 |
- } |
|
| 25 |
- if start != 8080 || end != 8080 {
|
|
| 26 |
- t.Fatalf("Expected start and end to be the same and equal to 8080, but were %v and %v", start, end)
|
|
| 27 |
- } |
|
| 28 |
-} |
|
| 29 |
- |
|
| 30 |
-func TestParsePortRangeIncorrectRange(t *testing.T) {
|
|
| 31 |
- if _, _, err := ParsePortRange("9000-8080"); err == nil || !strings.Contains(err.Error(), "Invalid range specified for the Port") {
|
|
| 32 |
- t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
|
|
| 33 |
- } |
|
| 34 |
-} |
|
| 35 |
- |
|
| 36 |
-func TestParsePortRangeIncorrectEndRange(t *testing.T) {
|
|
| 37 |
- if _, _, err := ParsePortRange("8000-a"); err == nil || !strings.Contains(err.Error(), "invalid syntax") {
|
|
| 38 |
- t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
|
|
| 39 |
- } |
|
| 40 |
- |
|
| 41 |
- if _, _, err := ParsePortRange("8000-30a"); err == nil || !strings.Contains(err.Error(), "invalid syntax") {
|
|
| 42 |
- t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
|
|
| 43 |
- } |
|
| 44 |
-} |
|
| 45 |
- |
|
| 46 |
-func TestParsePortRangeIncorrectStartRange(t *testing.T) {
|
|
| 47 |
- if _, _, err := ParsePortRange("a-8000"); err == nil || !strings.Contains(err.Error(), "invalid syntax") {
|
|
| 48 |
- t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
|
|
| 49 |
- } |
|
| 50 |
- |
|
| 51 |
- if _, _, err := ParsePortRange("30a-8000"); err == nil || !strings.Contains(err.Error(), "invalid syntax") {
|
|
| 52 |
- t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err)
|
|
| 53 |
- } |
|
| 54 |
-} |
| 55 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,85 +0,0 @@ |
| 1 |
-package nat |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "reflect" |
|
| 6 |
- "testing" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-func TestSortUniquePorts(t *testing.T) {
|
|
| 10 |
- ports := []Port{
|
|
| 11 |
- Port("6379/tcp"),
|
|
| 12 |
- Port("22/tcp"),
|
|
| 13 |
- } |
|
| 14 |
- |
|
| 15 |
- Sort(ports, func(ip, jp Port) bool {
|
|
| 16 |
- return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp") |
|
| 17 |
- }) |
|
| 18 |
- |
|
| 19 |
- first := ports[0] |
|
| 20 |
- if fmt.Sprint(first) != "22/tcp" {
|
|
| 21 |
- t.Log(fmt.Sprint(first)) |
|
| 22 |
- t.Fail() |
|
| 23 |
- } |
|
| 24 |
-} |
|
| 25 |
- |
|
| 26 |
-func TestSortSamePortWithDifferentProto(t *testing.T) {
|
|
| 27 |
- ports := []Port{
|
|
| 28 |
- Port("8888/tcp"),
|
|
| 29 |
- Port("8888/udp"),
|
|
| 30 |
- Port("6379/tcp"),
|
|
| 31 |
- Port("6379/udp"),
|
|
| 32 |
- } |
|
| 33 |
- |
|
| 34 |
- Sort(ports, func(ip, jp Port) bool {
|
|
| 35 |
- return ip.Int() < jp.Int() || (ip.Int() == jp.Int() && ip.Proto() == "tcp") |
|
| 36 |
- }) |
|
| 37 |
- |
|
| 38 |
- first := ports[0] |
|
| 39 |
- if fmt.Sprint(first) != "6379/tcp" {
|
|
| 40 |
- t.Fail() |
|
| 41 |
- } |
|
| 42 |
-} |
|
| 43 |
- |
|
| 44 |
-func TestSortPortMap(t *testing.T) {
|
|
| 45 |
- ports := []Port{
|
|
| 46 |
- Port("22/tcp"),
|
|
| 47 |
- Port("22/udp"),
|
|
| 48 |
- Port("8000/tcp"),
|
|
| 49 |
- Port("6379/tcp"),
|
|
| 50 |
- Port("9999/tcp"),
|
|
| 51 |
- } |
|
| 52 |
- |
|
| 53 |
- portMap := PortMap{
|
|
| 54 |
- Port("22/tcp"): []PortBinding{
|
|
| 55 |
- {},
|
|
| 56 |
- }, |
|
| 57 |
- Port("8000/tcp"): []PortBinding{
|
|
| 58 |
- {},
|
|
| 59 |
- }, |
|
| 60 |
- Port("6379/tcp"): []PortBinding{
|
|
| 61 |
- {},
|
|
| 62 |
- {HostIP: "0.0.0.0", HostPort: "32749"},
|
|
| 63 |
- }, |
|
| 64 |
- Port("9999/tcp"): []PortBinding{
|
|
| 65 |
- {HostIP: "0.0.0.0", HostPort: "40000"},
|
|
| 66 |
- }, |
|
| 67 |
- } |
|
| 68 |
- |
|
| 69 |
- SortPortMap(ports, portMap) |
|
| 70 |
- if !reflect.DeepEqual(ports, []Port{
|
|
| 71 |
- Port("9999/tcp"),
|
|
| 72 |
- Port("6379/tcp"),
|
|
| 73 |
- Port("8000/tcp"),
|
|
| 74 |
- Port("22/tcp"),
|
|
| 75 |
- Port("22/udp"),
|
|
| 76 |
- }) {
|
|
| 77 |
- t.Errorf("failed to prioritize port with explicit mappings, got %v", ports)
|
|
| 78 |
- } |
|
| 79 |
- if pm := portMap[Port("6379/tcp")]; !reflect.DeepEqual(pm, []PortBinding{
|
|
| 80 |
- {HostIP: "0.0.0.0", HostPort: "32749"},
|
|
| 81 |
- {},
|
|
| 82 |
- }) {
|
|
| 83 |
- t.Errorf("failed to prioritize bindings with explicit mappings, got %v", pm)
|
|
| 84 |
- } |
|
| 85 |
-} |
| 86 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,216 +0,0 @@ |
| 1 |
-package proxy |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "bytes" |
|
| 5 |
- "fmt" |
|
| 6 |
- "io" |
|
| 7 |
- "net" |
|
| 8 |
- "strings" |
|
| 9 |
- "testing" |
|
| 10 |
- "time" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-var testBuf = []byte("Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo")
|
|
| 14 |
-var testBufSize = len(testBuf) |
|
| 15 |
- |
|
| 16 |
-type EchoServer interface {
|
|
| 17 |
- Run() |
|
| 18 |
- Close() |
|
| 19 |
- LocalAddr() net.Addr |
|
| 20 |
-} |
|
| 21 |
- |
|
| 22 |
-type TCPEchoServer struct {
|
|
| 23 |
- listener net.Listener |
|
| 24 |
- testCtx *testing.T |
|
| 25 |
-} |
|
| 26 |
- |
|
| 27 |
-type UDPEchoServer struct {
|
|
| 28 |
- conn net.PacketConn |
|
| 29 |
- testCtx *testing.T |
|
| 30 |
-} |
|
| 31 |
- |
|
| 32 |
-func NewEchoServer(t *testing.T, proto, address string) EchoServer {
|
|
| 33 |
- var server EchoServer |
|
| 34 |
- if strings.HasPrefix(proto, "tcp") {
|
|
| 35 |
- listener, err := net.Listen(proto, address) |
|
| 36 |
- if err != nil {
|
|
| 37 |
- t.Fatal(err) |
|
| 38 |
- } |
|
| 39 |
- server = &TCPEchoServer{listener: listener, testCtx: t}
|
|
| 40 |
- } else {
|
|
| 41 |
- socket, err := net.ListenPacket(proto, address) |
|
| 42 |
- if err != nil {
|
|
| 43 |
- t.Fatal(err) |
|
| 44 |
- } |
|
| 45 |
- server = &UDPEchoServer{conn: socket, testCtx: t}
|
|
| 46 |
- } |
|
| 47 |
- return server |
|
| 48 |
-} |
|
| 49 |
- |
|
| 50 |
-func (server *TCPEchoServer) Run() {
|
|
| 51 |
- go func() {
|
|
| 52 |
- for {
|
|
| 53 |
- client, err := server.listener.Accept() |
|
| 54 |
- if err != nil {
|
|
| 55 |
- return |
|
| 56 |
- } |
|
| 57 |
- go func(client net.Conn) {
|
|
| 58 |
- if _, err := io.Copy(client, client); err != nil {
|
|
| 59 |
- server.testCtx.Logf("can't echo to the client: %v\n", err.Error())
|
|
| 60 |
- } |
|
| 61 |
- client.Close() |
|
| 62 |
- }(client) |
|
| 63 |
- } |
|
| 64 |
- }() |
|
| 65 |
-} |
|
| 66 |
- |
|
| 67 |
-func (server *TCPEchoServer) LocalAddr() net.Addr { return server.listener.Addr() }
|
|
| 68 |
-func (server *TCPEchoServer) Close() { server.listener.Addr() }
|
|
| 69 |
- |
|
| 70 |
-func (server *UDPEchoServer) Run() {
|
|
| 71 |
- go func() {
|
|
| 72 |
- readBuf := make([]byte, 1024) |
|
| 73 |
- for {
|
|
| 74 |
- read, from, err := server.conn.ReadFrom(readBuf) |
|
| 75 |
- if err != nil {
|
|
| 76 |
- return |
|
| 77 |
- } |
|
| 78 |
- for i := 0; i != read; {
|
|
| 79 |
- written, err := server.conn.WriteTo(readBuf[i:read], from) |
|
| 80 |
- if err != nil {
|
|
| 81 |
- break |
|
| 82 |
- } |
|
| 83 |
- i += written |
|
| 84 |
- } |
|
| 85 |
- } |
|
| 86 |
- }() |
|
| 87 |
-} |
|
| 88 |
- |
|
| 89 |
-func (server *UDPEchoServer) LocalAddr() net.Addr { return server.conn.LocalAddr() }
|
|
| 90 |
-func (server *UDPEchoServer) Close() { server.conn.Close() }
|
|
| 91 |
- |
|
| 92 |
-func testProxyAt(t *testing.T, proto string, proxy Proxy, addr string) {
|
|
| 93 |
- defer proxy.Close() |
|
| 94 |
- go proxy.Run() |
|
| 95 |
- client, err := net.Dial(proto, addr) |
|
| 96 |
- if err != nil {
|
|
| 97 |
- t.Fatalf("Can't connect to the proxy: %v", err)
|
|
| 98 |
- } |
|
| 99 |
- defer client.Close() |
|
| 100 |
- client.SetDeadline(time.Now().Add(10 * time.Second)) |
|
| 101 |
- if _, err = client.Write(testBuf); err != nil {
|
|
| 102 |
- t.Fatal(err) |
|
| 103 |
- } |
|
| 104 |
- recvBuf := make([]byte, testBufSize) |
|
| 105 |
- if _, err = client.Read(recvBuf); err != nil {
|
|
| 106 |
- t.Fatal(err) |
|
| 107 |
- } |
|
| 108 |
- if !bytes.Equal(testBuf, recvBuf) {
|
|
| 109 |
- t.Fatal(fmt.Errorf("Expected [%v] but got [%v]", testBuf, recvBuf))
|
|
| 110 |
- } |
|
| 111 |
-} |
|
| 112 |
- |
|
| 113 |
-func testProxy(t *testing.T, proto string, proxy Proxy) {
|
|
| 114 |
- testProxyAt(t, proto, proxy, proxy.FrontendAddr().String()) |
|
| 115 |
-} |
|
| 116 |
- |
|
| 117 |
-func TestTCP4Proxy(t *testing.T) {
|
|
| 118 |
- backend := NewEchoServer(t, "tcp", "127.0.0.1:0") |
|
| 119 |
- defer backend.Close() |
|
| 120 |
- backend.Run() |
|
| 121 |
- frontendAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0}
|
|
| 122 |
- proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) |
|
| 123 |
- if err != nil {
|
|
| 124 |
- t.Fatal(err) |
|
| 125 |
- } |
|
| 126 |
- testProxy(t, "tcp", proxy) |
|
| 127 |
-} |
|
| 128 |
- |
|
| 129 |
-func TestTCP6Proxy(t *testing.T) {
|
|
| 130 |
- backend := NewEchoServer(t, "tcp", "[::1]:0") |
|
| 131 |
- defer backend.Close() |
|
| 132 |
- backend.Run() |
|
| 133 |
- frontendAddr := &net.TCPAddr{IP: net.IPv6loopback, Port: 0}
|
|
| 134 |
- proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) |
|
| 135 |
- if err != nil {
|
|
| 136 |
- t.Fatal(err) |
|
| 137 |
- } |
|
| 138 |
- testProxy(t, "tcp", proxy) |
|
| 139 |
-} |
|
| 140 |
- |
|
| 141 |
-func TestTCPDualStackProxy(t *testing.T) {
|
|
| 142 |
- // If I understand `godoc -src net favoriteAddrFamily` (used by the |
|
| 143 |
- // net.Listen* functions) correctly this should work, but it doesn't. |
|
| 144 |
- t.Skip("No support for dual stack yet")
|
|
| 145 |
- backend := NewEchoServer(t, "tcp", "[::1]:0") |
|
| 146 |
- defer backend.Close() |
|
| 147 |
- backend.Run() |
|
| 148 |
- frontendAddr := &net.TCPAddr{IP: net.IPv6loopback, Port: 0}
|
|
| 149 |
- proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) |
|
| 150 |
- if err != nil {
|
|
| 151 |
- t.Fatal(err) |
|
| 152 |
- } |
|
| 153 |
- ipv4ProxyAddr := &net.TCPAddr{
|
|
| 154 |
- IP: net.IPv4(127, 0, 0, 1), |
|
| 155 |
- Port: proxy.FrontendAddr().(*net.TCPAddr).Port, |
|
| 156 |
- } |
|
| 157 |
- testProxyAt(t, "tcp", proxy, ipv4ProxyAddr.String()) |
|
| 158 |
-} |
|
| 159 |
- |
|
| 160 |
-func TestUDP4Proxy(t *testing.T) {
|
|
| 161 |
- backend := NewEchoServer(t, "udp", "127.0.0.1:0") |
|
| 162 |
- defer backend.Close() |
|
| 163 |
- backend.Run() |
|
| 164 |
- frontendAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0}
|
|
| 165 |
- proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) |
|
| 166 |
- if err != nil {
|
|
| 167 |
- t.Fatal(err) |
|
| 168 |
- } |
|
| 169 |
- testProxy(t, "udp", proxy) |
|
| 170 |
-} |
|
| 171 |
- |
|
| 172 |
-func TestUDP6Proxy(t *testing.T) {
|
|
| 173 |
- backend := NewEchoServer(t, "udp", "[::1]:0") |
|
| 174 |
- defer backend.Close() |
|
| 175 |
- backend.Run() |
|
| 176 |
- frontendAddr := &net.UDPAddr{IP: net.IPv6loopback, Port: 0}
|
|
| 177 |
- proxy, err := NewProxy(frontendAddr, backend.LocalAddr()) |
|
| 178 |
- if err != nil {
|
|
| 179 |
- t.Fatal(err) |
|
| 180 |
- } |
|
| 181 |
- testProxy(t, "udp", proxy) |
|
| 182 |
-} |
|
| 183 |
- |
|
| 184 |
-func TestUDPWriteError(t *testing.T) {
|
|
| 185 |
- frontendAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0}
|
|
| 186 |
- // Hopefully, this port will be free: */ |
|
| 187 |
- backendAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 25587}
|
|
| 188 |
- proxy, err := NewProxy(frontendAddr, backendAddr) |
|
| 189 |
- if err != nil {
|
|
| 190 |
- t.Fatal(err) |
|
| 191 |
- } |
|
| 192 |
- defer proxy.Close() |
|
| 193 |
- go proxy.Run() |
|
| 194 |
- client, err := net.Dial("udp", "127.0.0.1:25587")
|
|
| 195 |
- if err != nil {
|
|
| 196 |
- t.Fatalf("Can't connect to the proxy: %v", err)
|
|
| 197 |
- } |
|
| 198 |
- defer client.Close() |
|
| 199 |
- // Make sure the proxy doesn't stop when there is no actual backend: |
|
| 200 |
- client.Write(testBuf) |
|
| 201 |
- client.Write(testBuf) |
|
| 202 |
- backend := NewEchoServer(t, "udp", "127.0.0.1:25587") |
|
| 203 |
- defer backend.Close() |
|
| 204 |
- backend.Run() |
|
| 205 |
- client.SetDeadline(time.Now().Add(10 * time.Second)) |
|
| 206 |
- if _, err = client.Write(testBuf); err != nil {
|
|
| 207 |
- t.Fatal(err) |
|
| 208 |
- } |
|
| 209 |
- recvBuf := make([]byte, testBufSize) |
|
| 210 |
- if _, err = client.Read(recvBuf); err != nil {
|
|
| 211 |
- t.Fatal(err) |
|
| 212 |
- } |
|
| 213 |
- if !bytes.Equal(testBuf, recvBuf) {
|
|
| 214 |
- t.Fatal(fmt.Errorf("Expected [%v] but got [%v]", testBuf, recvBuf))
|
|
| 215 |
- } |
|
| 216 |
-} |
| 217 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,36 +0,0 @@ |
| 1 |
-// Package proxy provides a network Proxy interface and implementations for TCP and UDP. |
|
| 2 |
-package proxy |
|
| 3 |
- |
|
| 4 |
-import ( |
|
| 5 |
- "fmt" |
|
| 6 |
- "net" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-// Proxy defines the behavior of a proxy. It forwards traffic back and forth |
|
| 10 |
-// between two endpoints : the frontend and the backend. |
|
| 11 |
-// It can be used to do software port-mapping between two addresses. |
|
| 12 |
-// e.g. forward all traffic between the frontend (host) 127.0.0.1:3000 |
|
| 13 |
-// to the backend (container) at 172.17.42.108:4000. |
|
| 14 |
-type Proxy interface {
|
|
| 15 |
- // Run starts forwarding traffic back and forth between the front |
|
| 16 |
- // and back-end addresses. |
|
| 17 |
- Run() |
|
| 18 |
- // Close stops forwarding traffic and close both ends of the Proxy. |
|
| 19 |
- Close() |
|
| 20 |
- // FrontendAddr returns the address on which the proxy is listening. |
|
| 21 |
- FrontendAddr() net.Addr |
|
| 22 |
- // BackendAddr returns the proxied address. |
|
| 23 |
- BackendAddr() net.Addr |
|
| 24 |
-} |
|
| 25 |
- |
|
| 26 |
-// NewProxy creates a Proxy according to the specified frontendAddr and backendAddr. |
|
| 27 |
-func NewProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) {
|
|
| 28 |
- switch frontendAddr.(type) {
|
|
| 29 |
- case *net.UDPAddr: |
|
| 30 |
- return NewUDPProxy(frontendAddr.(*net.UDPAddr), backendAddr.(*net.UDPAddr)) |
|
| 31 |
- case *net.TCPAddr: |
|
| 32 |
- return NewTCPProxy(frontendAddr.(*net.TCPAddr), backendAddr.(*net.TCPAddr)) |
|
| 33 |
- default: |
|
| 34 |
- panic(fmt.Errorf("Unsupported protocol"))
|
|
| 35 |
- } |
|
| 36 |
-} |
| 37 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,31 +0,0 @@ |
| 1 |
-package proxy |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "net" |
|
| 5 |
-) |
|
| 6 |
- |
|
| 7 |
-// StubProxy is a proxy that is a stub (does nothing). |
|
| 8 |
-type StubProxy struct {
|
|
| 9 |
- frontendAddr net.Addr |
|
| 10 |
- backendAddr net.Addr |
|
| 11 |
-} |
|
| 12 |
- |
|
| 13 |
-// Run does nothing. |
|
| 14 |
-func (p *StubProxy) Run() {}
|
|
| 15 |
- |
|
| 16 |
-// Close does nothing. |
|
| 17 |
-func (p *StubProxy) Close() {}
|
|
| 18 |
- |
|
| 19 |
-// FrontendAddr returns the frontend address. |
|
| 20 |
-func (p *StubProxy) FrontendAddr() net.Addr { return p.frontendAddr }
|
|
| 21 |
- |
|
| 22 |
-// BackendAddr returns the backend address. |
|
| 23 |
-func (p *StubProxy) BackendAddr() net.Addr { return p.backendAddr }
|
|
| 24 |
- |
|
| 25 |
-// NewStubProxy creates a new StubProxy |
|
| 26 |
-func NewStubProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) {
|
|
| 27 |
- return &StubProxy{
|
|
| 28 |
- frontendAddr: frontendAddr, |
|
| 29 |
- backendAddr: backendAddr, |
|
| 30 |
- }, nil |
|
| 31 |
-} |
| 32 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,99 +0,0 @@ |
| 1 |
-package proxy |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "io" |
|
| 5 |
- "net" |
|
| 6 |
- "syscall" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-// TCPProxy is a proxy for TCP connections. It implements the Proxy interface to |
|
| 12 |
-// handle TCP traffic forwarding between the frontend and backend addresses. |
|
| 13 |
-type TCPProxy struct {
|
|
| 14 |
- listener *net.TCPListener |
|
| 15 |
- frontendAddr *net.TCPAddr |
|
| 16 |
- backendAddr *net.TCPAddr |
|
| 17 |
-} |
|
| 18 |
- |
|
| 19 |
-// NewTCPProxy creates a new TCPProxy. |
|
| 20 |
-func NewTCPProxy(frontendAddr, backendAddr *net.TCPAddr) (*TCPProxy, error) {
|
|
| 21 |
- listener, err := net.ListenTCP("tcp", frontendAddr)
|
|
| 22 |
- if err != nil {
|
|
| 23 |
- return nil, err |
|
| 24 |
- } |
|
| 25 |
- // If the port in frontendAddr was 0 then ListenTCP will have a picked |
|
| 26 |
- // a port to listen on, hence the call to Addr to get that actual port: |
|
| 27 |
- return &TCPProxy{
|
|
| 28 |
- listener: listener, |
|
| 29 |
- frontendAddr: listener.Addr().(*net.TCPAddr), |
|
| 30 |
- backendAddr: backendAddr, |
|
| 31 |
- }, nil |
|
| 32 |
-} |
|
| 33 |
- |
|
| 34 |
-func (proxy *TCPProxy) clientLoop(client *net.TCPConn, quit chan bool) {
|
|
| 35 |
- backend, err := net.DialTCP("tcp", nil, proxy.backendAddr)
|
|
| 36 |
- if err != nil {
|
|
| 37 |
- logrus.Printf("Can't forward traffic to backend tcp/%v: %s\n", proxy.backendAddr, err)
|
|
| 38 |
- client.Close() |
|
| 39 |
- return |
|
| 40 |
- } |
|
| 41 |
- |
|
| 42 |
- event := make(chan int64) |
|
| 43 |
- var broker = func(to, from *net.TCPConn) {
|
|
| 44 |
- written, err := io.Copy(to, from) |
|
| 45 |
- if err != nil {
|
|
| 46 |
- // If the socket we are writing to is shutdown with |
|
| 47 |
- // SHUT_WR, forward it to the other end of the pipe: |
|
| 48 |
- if err, ok := err.(*net.OpError); ok && err.Err == syscall.EPIPE {
|
|
| 49 |
- from.CloseWrite() |
|
| 50 |
- } |
|
| 51 |
- } |
|
| 52 |
- to.CloseRead() |
|
| 53 |
- event <- written |
|
| 54 |
- } |
|
| 55 |
- |
|
| 56 |
- go broker(client, backend) |
|
| 57 |
- go broker(backend, client) |
|
| 58 |
- |
|
| 59 |
- var transferred int64 |
|
| 60 |
- for i := 0; i < 2; i++ {
|
|
| 61 |
- select {
|
|
| 62 |
- case written := <-event: |
|
| 63 |
- transferred += written |
|
| 64 |
- case <-quit: |
|
| 65 |
- // Interrupt the two brokers and "join" them. |
|
| 66 |
- client.Close() |
|
| 67 |
- backend.Close() |
|
| 68 |
- for ; i < 2; i++ {
|
|
| 69 |
- transferred += <-event |
|
| 70 |
- } |
|
| 71 |
- return |
|
| 72 |
- } |
|
| 73 |
- } |
|
| 74 |
- client.Close() |
|
| 75 |
- backend.Close() |
|
| 76 |
-} |
|
| 77 |
- |
|
| 78 |
-// Run starts forwarding the traffic using TCP. |
|
| 79 |
-func (proxy *TCPProxy) Run() {
|
|
| 80 |
- quit := make(chan bool) |
|
| 81 |
- defer close(quit) |
|
| 82 |
- for {
|
|
| 83 |
- client, err := proxy.listener.Accept() |
|
| 84 |
- if err != nil {
|
|
| 85 |
- logrus.Printf("Stopping proxy on tcp/%v for tcp/%v (%s)", proxy.frontendAddr, proxy.backendAddr, err)
|
|
| 86 |
- return |
|
| 87 |
- } |
|
| 88 |
- go proxy.clientLoop(client.(*net.TCPConn), quit) |
|
| 89 |
- } |
|
| 90 |
-} |
|
| 91 |
- |
|
| 92 |
-// Close stops forwarding the traffic. |
|
| 93 |
-func (proxy *TCPProxy) Close() { proxy.listener.Close() }
|
|
| 94 |
- |
|
| 95 |
-// FrontendAddr returns the TCP address on which the proxy is listening. |
|
| 96 |
-func (proxy *TCPProxy) FrontendAddr() net.Addr { return proxy.frontendAddr }
|
|
| 97 |
- |
|
| 98 |
-// BackendAddr returns the TCP proxied address. |
|
| 99 |
-func (proxy *TCPProxy) BackendAddr() net.Addr { return proxy.backendAddr }
|
| 100 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,169 +0,0 @@ |
| 1 |
-package proxy |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "encoding/binary" |
|
| 5 |
- "net" |
|
| 6 |
- "strings" |
|
| 7 |
- "sync" |
|
| 8 |
- "syscall" |
|
| 9 |
- "time" |
|
| 10 |
- |
|
| 11 |
- "github.com/Sirupsen/logrus" |
|
| 12 |
-) |
|
| 13 |
- |
|
| 14 |
-const ( |
|
| 15 |
- // UDPConnTrackTimeout is the timeout used for UDP connection tracking |
|
| 16 |
- UDPConnTrackTimeout = 90 * time.Second |
|
| 17 |
- // UDPBufSize is the buffer size for the UDP proxy |
|
| 18 |
- UDPBufSize = 65507 |
|
| 19 |
-) |
|
| 20 |
- |
|
| 21 |
-// A net.Addr where the IP is split into two fields so you can use it as a key |
|
| 22 |
-// in a map: |
|
| 23 |
-type connTrackKey struct {
|
|
| 24 |
- IPHigh uint64 |
|
| 25 |
- IPLow uint64 |
|
| 26 |
- Port int |
|
| 27 |
-} |
|
| 28 |
- |
|
| 29 |
-func newConnTrackKey(addr *net.UDPAddr) *connTrackKey {
|
|
| 30 |
- if len(addr.IP) == net.IPv4len {
|
|
| 31 |
- return &connTrackKey{
|
|
| 32 |
- IPHigh: 0, |
|
| 33 |
- IPLow: uint64(binary.BigEndian.Uint32(addr.IP)), |
|
| 34 |
- Port: addr.Port, |
|
| 35 |
- } |
|
| 36 |
- } |
|
| 37 |
- return &connTrackKey{
|
|
| 38 |
- IPHigh: binary.BigEndian.Uint64(addr.IP[:8]), |
|
| 39 |
- IPLow: binary.BigEndian.Uint64(addr.IP[8:]), |
|
| 40 |
- Port: addr.Port, |
|
| 41 |
- } |
|
| 42 |
-} |
|
| 43 |
- |
|
| 44 |
-type connTrackMap map[connTrackKey]*net.UDPConn |
|
| 45 |
- |
|
| 46 |
-// UDPProxy is proxy for which handles UDP datagrams. It implements the Proxy |
|
| 47 |
-// interface to handle UDP traffic forwarding between the frontend and backend |
|
| 48 |
-// addresses. |
|
| 49 |
-type UDPProxy struct {
|
|
| 50 |
- listener *net.UDPConn |
|
| 51 |
- frontendAddr *net.UDPAddr |
|
| 52 |
- backendAddr *net.UDPAddr |
|
| 53 |
- connTrackTable connTrackMap |
|
| 54 |
- connTrackLock sync.Mutex |
|
| 55 |
-} |
|
| 56 |
- |
|
| 57 |
-// NewUDPProxy creates a new UDPProxy. |
|
| 58 |
-func NewUDPProxy(frontendAddr, backendAddr *net.UDPAddr) (*UDPProxy, error) {
|
|
| 59 |
- listener, err := net.ListenUDP("udp", frontendAddr)
|
|
| 60 |
- if err != nil {
|
|
| 61 |
- return nil, err |
|
| 62 |
- } |
|
| 63 |
- return &UDPProxy{
|
|
| 64 |
- listener: listener, |
|
| 65 |
- frontendAddr: listener.LocalAddr().(*net.UDPAddr), |
|
| 66 |
- backendAddr: backendAddr, |
|
| 67 |
- connTrackTable: make(connTrackMap), |
|
| 68 |
- }, nil |
|
| 69 |
-} |
|
| 70 |
- |
|
| 71 |
-func (proxy *UDPProxy) replyLoop(proxyConn *net.UDPConn, clientAddr *net.UDPAddr, clientKey *connTrackKey) {
|
|
| 72 |
- defer func() {
|
|
| 73 |
- proxy.connTrackLock.Lock() |
|
| 74 |
- delete(proxy.connTrackTable, *clientKey) |
|
| 75 |
- proxy.connTrackLock.Unlock() |
|
| 76 |
- proxyConn.Close() |
|
| 77 |
- }() |
|
| 78 |
- |
|
| 79 |
- readBuf := make([]byte, UDPBufSize) |
|
| 80 |
- for {
|
|
| 81 |
- proxyConn.SetReadDeadline(time.Now().Add(UDPConnTrackTimeout)) |
|
| 82 |
- again: |
|
| 83 |
- read, err := proxyConn.Read(readBuf) |
|
| 84 |
- if err != nil {
|
|
| 85 |
- if err, ok := err.(*net.OpError); ok && err.Err == syscall.ECONNREFUSED {
|
|
| 86 |
- // This will happen if the last write failed |
|
| 87 |
- // (e.g: nothing is actually listening on the |
|
| 88 |
- // proxied port on the container), ignore it |
|
| 89 |
- // and continue until UDPConnTrackTimeout |
|
| 90 |
- // expires: |
|
| 91 |
- goto again |
|
| 92 |
- } |
|
| 93 |
- return |
|
| 94 |
- } |
|
| 95 |
- for i := 0; i != read; {
|
|
| 96 |
- written, err := proxy.listener.WriteToUDP(readBuf[i:read], clientAddr) |
|
| 97 |
- if err != nil {
|
|
| 98 |
- return |
|
| 99 |
- } |
|
| 100 |
- i += written |
|
| 101 |
- } |
|
| 102 |
- } |
|
| 103 |
-} |
|
| 104 |
- |
|
| 105 |
-// Run starts forwarding the traffic using UDP. |
|
| 106 |
-func (proxy *UDPProxy) Run() {
|
|
| 107 |
- readBuf := make([]byte, UDPBufSize) |
|
| 108 |
- for {
|
|
| 109 |
- read, from, err := proxy.listener.ReadFromUDP(readBuf) |
|
| 110 |
- if err != nil {
|
|
| 111 |
- // NOTE: Apparently ReadFrom doesn't return |
|
| 112 |
- // ECONNREFUSED like Read do (see comment in |
|
| 113 |
- // UDPProxy.replyLoop) |
|
| 114 |
- if !isClosedError(err) {
|
|
| 115 |
- logrus.Printf("Stopping proxy on udp/%v for udp/%v (%s)", proxy.frontendAddr, proxy.backendAddr, err)
|
|
| 116 |
- } |
|
| 117 |
- break |
|
| 118 |
- } |
|
| 119 |
- |
|
| 120 |
- fromKey := newConnTrackKey(from) |
|
| 121 |
- proxy.connTrackLock.Lock() |
|
| 122 |
- proxyConn, hit := proxy.connTrackTable[*fromKey] |
|
| 123 |
- if !hit {
|
|
| 124 |
- proxyConn, err = net.DialUDP("udp", nil, proxy.backendAddr)
|
|
| 125 |
- if err != nil {
|
|
| 126 |
- logrus.Printf("Can't proxy a datagram to udp/%s: %s\n", proxy.backendAddr, err)
|
|
| 127 |
- proxy.connTrackLock.Unlock() |
|
| 128 |
- continue |
|
| 129 |
- } |
|
| 130 |
- proxy.connTrackTable[*fromKey] = proxyConn |
|
| 131 |
- go proxy.replyLoop(proxyConn, from, fromKey) |
|
| 132 |
- } |
|
| 133 |
- proxy.connTrackLock.Unlock() |
|
| 134 |
- for i := 0; i != read; {
|
|
| 135 |
- written, err := proxyConn.Write(readBuf[i:read]) |
|
| 136 |
- if err != nil {
|
|
| 137 |
- logrus.Printf("Can't proxy a datagram to udp/%s: %s\n", proxy.backendAddr, err)
|
|
| 138 |
- break |
|
| 139 |
- } |
|
| 140 |
- i += written |
|
| 141 |
- } |
|
| 142 |
- } |
|
| 143 |
-} |
|
| 144 |
- |
|
| 145 |
-// Close stops forwarding the traffic. |
|
| 146 |
-func (proxy *UDPProxy) Close() {
|
|
| 147 |
- proxy.listener.Close() |
|
| 148 |
- proxy.connTrackLock.Lock() |
|
| 149 |
- defer proxy.connTrackLock.Unlock() |
|
| 150 |
- for _, conn := range proxy.connTrackTable {
|
|
| 151 |
- conn.Close() |
|
| 152 |
- } |
|
| 153 |
-} |
|
| 154 |
- |
|
| 155 |
-// FrontendAddr returns the UDP address on which the proxy is listening. |
|
| 156 |
-func (proxy *UDPProxy) FrontendAddr() net.Addr { return proxy.frontendAddr }
|
|
| 157 |
- |
|
| 158 |
-// BackendAddr returns the proxied UDP address. |
|
| 159 |
-func (proxy *UDPProxy) BackendAddr() net.Addr { return proxy.backendAddr }
|
|
| 160 |
- |
|
| 161 |
-func isClosedError(err error) bool {
|
|
| 162 |
- /* This comparison is ugly, but unfortunately, net.go doesn't export errClosing. |
|
| 163 |
- * See: |
|
| 164 |
- * http://golang.org/src/pkg/net/net.go |
|
| 165 |
- * https://code.google.com/p/go/issues/detail?id=4337 |
|
| 166 |
- * https://groups.google.com/forum/#!msg/golang-nuts/0_aaCvBmOcM/SptmDyX1XJMJ |
|
| 167 |
- */ |
|
| 168 |
- return strings.HasSuffix(err.Error(), "use of closed network connection") |
|
| 169 |
-} |
| ... | ... |
@@ -137,7 +137,7 @@ func (m *Manager) Apply(pid int) (err error) {
|
| 137 | 137 |
m.Paths = paths |
| 138 | 138 |
|
| 139 | 139 |
if paths["cpu"] != "" {
|
| 140 |
- if err := CheckCpushares(paths["cpu"], c.CpuShares); err != nil {
|
|
| 140 |
+ if err := CheckCpushares(paths["cpu"], c.Resources.CpuShares); err != nil {
|
|
| 141 | 141 |
return err |
| 142 | 142 |
} |
| 143 | 143 |
} |
| ... | ... |
@@ -202,15 +202,15 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
|
| 202 | 202 |
if err != nil {
|
| 203 | 203 |
return err |
| 204 | 204 |
} |
| 205 |
- prevState := m.Cgroups.Freezer |
|
| 206 |
- m.Cgroups.Freezer = state |
|
| 205 |
+ prevState := m.Cgroups.Resources.Freezer |
|
| 206 |
+ m.Cgroups.Resources.Freezer = state |
|
| 207 | 207 |
freezer, err := subsystems.Get("freezer")
|
| 208 | 208 |
if err != nil {
|
| 209 | 209 |
return err |
| 210 | 210 |
} |
| 211 | 211 |
err = freezer.Set(dir, m.Cgroups) |
| 212 | 212 |
if err != nil {
|
| 213 |
- m.Cgroups.Freezer = prevState |
|
| 213 |
+ m.Cgroups.Resources.Freezer = prevState |
|
| 214 | 214 |
return err |
| 215 | 215 |
} |
| 216 | 216 |
return nil |
| ... | ... |
@@ -35,18 +35,18 @@ func (s *BlkioGroup) Apply(d *cgroupData) error {
|
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 | 37 |
func (s *BlkioGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 38 |
- if cgroup.BlkioWeight != 0 {
|
|
| 39 |
- if err := writeFile(path, "blkio.weight", strconv.FormatUint(uint64(cgroup.BlkioWeight), 10)); err != nil {
|
|
| 38 |
+ if cgroup.Resources.BlkioWeight != 0 {
|
|
| 39 |
+ if err := writeFile(path, "blkio.weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioWeight), 10)); err != nil {
|
|
| 40 | 40 |
return err |
| 41 | 41 |
} |
| 42 | 42 |
} |
| 43 | 43 |
|
| 44 |
- if cgroup.BlkioLeafWeight != 0 {
|
|
| 45 |
- if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(cgroup.BlkioLeafWeight), 10)); err != nil {
|
|
| 44 |
+ if cgroup.Resources.BlkioLeafWeight != 0 {
|
|
| 45 |
+ if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioLeafWeight), 10)); err != nil {
|
|
| 46 | 46 |
return err |
| 47 | 47 |
} |
| 48 | 48 |
} |
| 49 |
- for _, wd := range cgroup.BlkioWeightDevice {
|
|
| 49 |
+ for _, wd := range cgroup.Resources.BlkioWeightDevice {
|
|
| 50 | 50 |
if err := writeFile(path, "blkio.weight_device", wd.WeightString()); err != nil {
|
| 51 | 51 |
return err |
| 52 | 52 |
} |
| ... | ... |
@@ -54,22 +54,22 @@ func (s *BlkioGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 54 | 54 |
return err |
| 55 | 55 |
} |
| 56 | 56 |
} |
| 57 |
- for _, td := range cgroup.BlkioThrottleReadBpsDevice {
|
|
| 57 |
+ for _, td := range cgroup.Resources.BlkioThrottleReadBpsDevice {
|
|
| 58 | 58 |
if err := writeFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil {
|
| 59 | 59 |
return err |
| 60 | 60 |
} |
| 61 | 61 |
} |
| 62 |
- for _, td := range cgroup.BlkioThrottleWriteBpsDevice {
|
|
| 62 |
+ for _, td := range cgroup.Resources.BlkioThrottleWriteBpsDevice {
|
|
| 63 | 63 |
if err := writeFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil {
|
| 64 | 64 |
return err |
| 65 | 65 |
} |
| 66 | 66 |
} |
| 67 |
- for _, td := range cgroup.BlkioThrottleReadIOPSDevice {
|
|
| 67 |
+ for _, td := range cgroup.Resources.BlkioThrottleReadIOPSDevice {
|
|
| 68 | 68 |
if err := writeFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil {
|
| 69 | 69 |
return err |
| 70 | 70 |
} |
| 71 | 71 |
} |
| 72 |
- for _, td := range cgroup.BlkioThrottleWriteIOPSDevice {
|
|
| 72 |
+ for _, td := range cgroup.Resources.BlkioThrottleWriteIOPSDevice {
|
|
| 73 | 73 |
if err := writeFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil {
|
| 74 | 74 |
return err |
| 75 | 75 |
} |
| ... | ... |
@@ -35,28 +35,28 @@ func (s *CpuGroup) Apply(d *cgroupData) error {
|
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 | 37 |
func (s *CpuGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 38 |
- if cgroup.CpuShares != 0 {
|
|
| 39 |
- if err := writeFile(path, "cpu.shares", strconv.FormatInt(cgroup.CpuShares, 10)); err != nil {
|
|
| 38 |
+ if cgroup.Resources.CpuShares != 0 {
|
|
| 39 |
+ if err := writeFile(path, "cpu.shares", strconv.FormatInt(cgroup.Resources.CpuShares, 10)); err != nil {
|
|
| 40 | 40 |
return err |
| 41 | 41 |
} |
| 42 | 42 |
} |
| 43 |
- if cgroup.CpuPeriod != 0 {
|
|
| 44 |
- if err := writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(cgroup.CpuPeriod, 10)); err != nil {
|
|
| 43 |
+ if cgroup.Resources.CpuPeriod != 0 {
|
|
| 44 |
+ if err := writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(cgroup.Resources.CpuPeriod, 10)); err != nil {
|
|
| 45 | 45 |
return err |
| 46 | 46 |
} |
| 47 | 47 |
} |
| 48 |
- if cgroup.CpuQuota != 0 {
|
|
| 49 |
- if err := writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(cgroup.CpuQuota, 10)); err != nil {
|
|
| 48 |
+ if cgroup.Resources.CpuQuota != 0 {
|
|
| 49 |
+ if err := writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(cgroup.Resources.CpuQuota, 10)); err != nil {
|
|
| 50 | 50 |
return err |
| 51 | 51 |
} |
| 52 | 52 |
} |
| 53 |
- if cgroup.CpuRtPeriod != 0 {
|
|
| 54 |
- if err := writeFile(path, "cpu.rt_period_us", strconv.FormatInt(cgroup.CpuRtPeriod, 10)); err != nil {
|
|
| 53 |
+ if cgroup.Resources.CpuRtPeriod != 0 {
|
|
| 54 |
+ if err := writeFile(path, "cpu.rt_period_us", strconv.FormatInt(cgroup.Resources.CpuRtPeriod, 10)); err != nil {
|
|
| 55 | 55 |
return err |
| 56 | 56 |
} |
| 57 | 57 |
} |
| 58 |
- if cgroup.CpuRtRuntime != 0 {
|
|
| 59 |
- if err := writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(cgroup.CpuRtRuntime, 10)); err != nil {
|
|
| 58 |
+ if cgroup.Resources.CpuRtRuntime != 0 {
|
|
| 59 |
+ if err := writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(cgroup.Resources.CpuRtRuntime, 10)); err != nil {
|
|
| 60 | 60 |
return err |
| 61 | 61 |
} |
| 62 | 62 |
} |
| ... | ... |
@@ -29,13 +29,13 @@ func (s *CpusetGroup) Apply(d *cgroupData) error {
|
| 29 | 29 |
} |
| 30 | 30 |
|
| 31 | 31 |
func (s *CpusetGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 32 |
- if cgroup.CpusetCpus != "" {
|
|
| 33 |
- if err := writeFile(path, "cpuset.cpus", cgroup.CpusetCpus); err != nil {
|
|
| 32 |
+ if cgroup.Resources.CpusetCpus != "" {
|
|
| 33 |
+ if err := writeFile(path, "cpuset.cpus", cgroup.Resources.CpusetCpus); err != nil {
|
|
| 34 | 34 |
return err |
| 35 | 35 |
} |
| 36 | 36 |
} |
| 37 |
- if cgroup.CpusetMems != "" {
|
|
| 38 |
- if err := writeFile(path, "cpuset.mems", cgroup.CpusetMems); err != nil {
|
|
| 37 |
+ if cgroup.Resources.CpusetMems != "" {
|
|
| 38 |
+ if err := writeFile(path, "cpuset.mems", cgroup.Resources.CpusetMems); err != nil {
|
|
| 39 | 39 |
return err |
| 40 | 40 |
} |
| 41 | 41 |
} |
| ... | ... |
@@ -30,12 +30,12 @@ func (s *DevicesGroup) Apply(d *cgroupData) error {
|
| 30 | 30 |
} |
| 31 | 31 |
|
| 32 | 32 |
func (s *DevicesGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 33 |
- if !cgroup.AllowAllDevices {
|
|
| 33 |
+ if !cgroup.Resources.AllowAllDevices {
|
|
| 34 | 34 |
if err := writeFile(path, "devices.deny", "a"); err != nil {
|
| 35 | 35 |
return err |
| 36 | 36 |
} |
| 37 | 37 |
|
| 38 |
- for _, dev := range cgroup.AllowedDevices {
|
|
| 38 |
+ for _, dev := range cgroup.Resources.AllowedDevices {
|
|
| 39 | 39 |
if err := writeFile(path, "devices.allow", dev.CgroupString()); err != nil {
|
| 40 | 40 |
return err |
| 41 | 41 |
} |
| ... | ... |
@@ -47,7 +47,7 @@ func (s *DevicesGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 47 | 47 |
return err |
| 48 | 48 |
} |
| 49 | 49 |
|
| 50 |
- for _, dev := range cgroup.DeniedDevices {
|
|
| 50 |
+ for _, dev := range cgroup.Resources.DeniedDevices {
|
|
| 51 | 51 |
if err := writeFile(path, "devices.deny", dev.CgroupString()); err != nil {
|
| 52 | 52 |
return err |
| 53 | 53 |
} |
| ... | ... |
@@ -32,9 +32,9 @@ func (s *FreezerGroup) Apply(d *cgroupData) error {
|
| 32 | 32 |
} |
| 33 | 33 |
|
| 34 | 34 |
func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 35 |
- switch cgroup.Freezer {
|
|
| 35 |
+ switch cgroup.Resources.Freezer {
|
|
| 36 | 36 |
case configs.Frozen, configs.Thawed: |
| 37 |
- if err := writeFile(path, "freezer.state", string(cgroup.Freezer)); err != nil {
|
|
| 37 |
+ if err := writeFile(path, "freezer.state", string(cgroup.Resources.Freezer)); err != nil {
|
|
| 38 | 38 |
return err |
| 39 | 39 |
} |
| 40 | 40 |
|
| ... | ... |
@@ -43,7 +43,7 @@ func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 43 | 43 |
if err != nil {
|
| 44 | 44 |
return err |
| 45 | 45 |
} |
| 46 |
- if strings.TrimSpace(state) == string(cgroup.Freezer) {
|
|
| 46 |
+ if strings.TrimSpace(state) == string(cgroup.Resources.Freezer) {
|
|
| 47 | 47 |
break |
| 48 | 48 |
} |
| 49 | 49 |
time.Sleep(1 * time.Millisecond) |
| ... | ... |
@@ -51,7 +51,7 @@ func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 51 | 51 |
case configs.Undefined: |
| 52 | 52 |
return nil |
| 53 | 53 |
default: |
| 54 |
- return fmt.Errorf("Invalid argument '%s' to freezer.state", string(cgroup.Freezer))
|
|
| 54 |
+ return fmt.Errorf("Invalid argument '%s' to freezer.state", string(cgroup.Resources.Freezer))
|
|
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 | 57 |
return nil |
| ... | ... |
@@ -32,7 +32,7 @@ func (s *HugetlbGroup) Apply(d *cgroupData) error {
|
| 32 | 32 |
} |
| 33 | 33 |
|
| 34 | 34 |
func (s *HugetlbGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 35 |
- for _, hugetlb := range cgroup.HugetlbLimit {
|
|
| 35 |
+ for _, hugetlb := range cgroup.Resources.HugetlbLimit {
|
|
| 36 | 36 |
if err := writeFile(path, strings.Join([]string{"hugetlb", hugetlb.Pagesize, "limit_in_bytes"}, "."), strconv.FormatUint(hugetlb.Limit, 10)); err != nil {
|
| 37 | 37 |
return err |
| 38 | 38 |
} |
| ... | ... |
@@ -55,40 +55,40 @@ func (s *MemoryGroup) Apply(d *cgroupData) (err error) {
|
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 | 57 |
func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 58 |
- if cgroup.Memory != 0 {
|
|
| 59 |
- if err := writeFile(path, "memory.limit_in_bytes", strconv.FormatInt(cgroup.Memory, 10)); err != nil {
|
|
| 58 |
+ if cgroup.Resources.Memory != 0 {
|
|
| 59 |
+ if err := writeFile(path, "memory.limit_in_bytes", strconv.FormatInt(cgroup.Resources.Memory, 10)); err != nil {
|
|
| 60 | 60 |
return err |
| 61 | 61 |
} |
| 62 | 62 |
} |
| 63 |
- if cgroup.MemoryReservation != 0 {
|
|
| 64 |
- if err := writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(cgroup.MemoryReservation, 10)); err != nil {
|
|
| 63 |
+ if cgroup.Resources.MemoryReservation != 0 {
|
|
| 64 |
+ if err := writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(cgroup.Resources.MemoryReservation, 10)); err != nil {
|
|
| 65 | 65 |
return err |
| 66 | 66 |
} |
| 67 | 67 |
} |
| 68 |
- if cgroup.MemorySwap > 0 {
|
|
| 69 |
- if err := writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(cgroup.MemorySwap, 10)); err != nil {
|
|
| 68 |
+ if cgroup.Resources.MemorySwap > 0 {
|
|
| 69 |
+ if err := writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(cgroup.Resources.MemorySwap, 10)); err != nil {
|
|
| 70 | 70 |
return err |
| 71 | 71 |
} |
| 72 | 72 |
} |
| 73 |
- if cgroup.KernelMemory > 0 {
|
|
| 74 |
- if err := writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(cgroup.KernelMemory, 10)); err != nil {
|
|
| 73 |
+ if cgroup.Resources.KernelMemory > 0 {
|
|
| 74 |
+ if err := writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(cgroup.Resources.KernelMemory, 10)); err != nil {
|
|
| 75 | 75 |
return err |
| 76 | 76 |
} |
| 77 | 77 |
} |
| 78 | 78 |
|
| 79 |
- if cgroup.OomKillDisable {
|
|
| 79 |
+ if cgroup.Resources.OomKillDisable {
|
|
| 80 | 80 |
if err := writeFile(path, "memory.oom_control", "1"); err != nil {
|
| 81 | 81 |
return err |
| 82 | 82 |
} |
| 83 | 83 |
} |
| 84 |
- if cgroup.MemorySwappiness >= 0 && cgroup.MemorySwappiness <= 100 {
|
|
| 85 |
- if err := writeFile(path, "memory.swappiness", strconv.FormatInt(cgroup.MemorySwappiness, 10)); err != nil {
|
|
| 84 |
+ if cgroup.Resources.MemorySwappiness >= 0 && cgroup.Resources.MemorySwappiness <= 100 {
|
|
| 85 |
+ if err := writeFile(path, "memory.swappiness", strconv.FormatInt(cgroup.Resources.MemorySwappiness, 10)); err != nil {
|
|
| 86 | 86 |
return err |
| 87 | 87 |
} |
| 88 |
- } else if cgroup.MemorySwappiness == -1 {
|
|
| 88 |
+ } else if cgroup.Resources.MemorySwappiness == -1 {
|
|
| 89 | 89 |
return nil |
| 90 | 90 |
} else {
|
| 91 |
- return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", cgroup.MemorySwappiness)
|
|
| 91 |
+ return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", cgroup.Resources.MemorySwappiness)
|
|
| 92 | 92 |
} |
| 93 | 93 |
|
| 94 | 94 |
return nil |
| ... | ... |
@@ -139,12 +139,12 @@ func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error {
|
| 139 | 139 |
} |
| 140 | 140 |
|
| 141 | 141 |
func memoryAssigned(cgroup *configs.Cgroup) bool {
|
| 142 |
- return cgroup.Memory != 0 || |
|
| 143 |
- cgroup.MemoryReservation != 0 || |
|
| 144 |
- cgroup.MemorySwap > 0 || |
|
| 145 |
- cgroup.KernelMemory > 0 || |
|
| 146 |
- cgroup.OomKillDisable || |
|
| 147 |
- cgroup.MemorySwappiness != -1 |
|
| 142 |
+ return cgroup.Resources.Memory != 0 || |
|
| 143 |
+ cgroup.Resources.MemoryReservation != 0 || |
|
| 144 |
+ cgroup.Resources.MemorySwap > 0 || |
|
| 145 |
+ cgroup.Resources.KernelMemory > 0 || |
|
| 146 |
+ cgroup.Resources.OomKillDisable || |
|
| 147 |
+ cgroup.Resources.MemorySwappiness != -1 |
|
| 148 | 148 |
} |
| 149 | 149 |
|
| 150 | 150 |
func getMemoryData(path, name string) (cgroups.MemoryData, error) {
|
| ... | ... |
@@ -28,8 +28,8 @@ func (s *NetClsGroup) Apply(d *cgroupData) error {
|
| 28 | 28 |
} |
| 29 | 29 |
|
| 30 | 30 |
func (s *NetClsGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 31 |
- if cgroup.NetClsClassid != "" {
|
|
| 32 |
- if err := writeFile(path, "net_cls.classid", cgroup.NetClsClassid); err != nil {
|
|
| 31 |
+ if cgroup.Resources.NetClsClassid != "" {
|
|
| 32 |
+ if err := writeFile(path, "net_cls.classid", cgroup.Resources.NetClsClassid); err != nil {
|
|
| 33 | 33 |
return err |
| 34 | 34 |
} |
| 35 | 35 |
} |
| ... | ... |
@@ -28,7 +28,7 @@ func (s *NetPrioGroup) Apply(d *cgroupData) error {
|
| 28 | 28 |
} |
| 29 | 29 |
|
| 30 | 30 |
func (s *NetPrioGroup) Set(path string, cgroup *configs.Cgroup) error {
|
| 31 |
- for _, prioMap := range cgroup.NetPrioIfpriomap {
|
|
| 31 |
+ for _, prioMap := range cgroup.Resources.NetPrioIfpriomap {
|
|
| 32 | 32 |
if err := writeFile(path, "net_prio.ifpriomap", prioMap.CgroupString()); err != nil {
|
| 33 | 33 |
return err |
| 34 | 34 |
} |
| ... | ... |
@@ -189,26 +189,26 @@ func (m *Manager) Apply(pid int) error {
|
| 189 | 189 |
newProp("DefaultDependencies", false))
|
| 190 | 190 |
} |
| 191 | 191 |
|
| 192 |
- if c.Memory != 0 {
|
|
| 192 |
+ if c.Resources.Memory != 0 {
|
|
| 193 | 193 |
properties = append(properties, |
| 194 |
- newProp("MemoryLimit", uint64(c.Memory)))
|
|
| 194 |
+ newProp("MemoryLimit", uint64(c.Resources.Memory)))
|
|
| 195 | 195 |
} |
| 196 | 196 |
|
| 197 |
- if c.CpuShares != 0 {
|
|
| 197 |
+ if c.Resources.CpuShares != 0 {
|
|
| 198 | 198 |
properties = append(properties, |
| 199 |
- newProp("CPUShares", uint64(c.CpuShares)))
|
|
| 199 |
+ newProp("CPUShares", uint64(c.Resources.CpuShares)))
|
|
| 200 | 200 |
} |
| 201 | 201 |
|
| 202 |
- if c.BlkioWeight != 0 {
|
|
| 202 |
+ if c.Resources.BlkioWeight != 0 {
|
|
| 203 | 203 |
properties = append(properties, |
| 204 |
- newProp("BlockIOWeight", uint64(c.BlkioWeight)))
|
|
| 204 |
+ newProp("BlockIOWeight", uint64(c.Resources.BlkioWeight)))
|
|
| 205 | 205 |
} |
| 206 | 206 |
|
| 207 | 207 |
// We need to set kernel memory before processes join cgroup because |
| 208 | 208 |
// kmem.limit_in_bytes can only be set when the cgroup is empty. |
| 209 | 209 |
// And swap memory limit needs to be set after memory limit, only |
| 210 | 210 |
// memory limit is handled by systemd, so it's kind of ugly here. |
| 211 |
- if c.KernelMemory > 0 {
|
|
| 211 |
+ if c.Resources.KernelMemory > 0 {
|
|
| 212 | 212 |
if err := setKernelMemory(c); err != nil {
|
| 213 | 213 |
return err |
| 214 | 214 |
} |
| ... | ... |
@@ -279,7 +279,7 @@ func (m *Manager) Apply(pid int) error {
|
| 279 | 279 |
m.Paths = paths |
| 280 | 280 |
|
| 281 | 281 |
if paths["cpu"] != "" {
|
| 282 |
- if err := fs.CheckCpushares(paths["cpu"], c.CpuShares); err != nil {
|
|
| 282 |
+ if err := fs.CheckCpushares(paths["cpu"], c.Resources.CpuShares); err != nil {
|
|
| 283 | 283 |
return err |
| 284 | 284 |
} |
| 285 | 285 |
} |
| ... | ... |
@@ -334,23 +334,23 @@ func joinCpu(c *configs.Cgroup, pid int) error {
|
| 334 | 334 |
if err != nil && !cgroups.IsNotFound(err) {
|
| 335 | 335 |
return err |
| 336 | 336 |
} |
| 337 |
- if c.CpuQuota != 0 {
|
|
| 338 |
- if err = writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(c.CpuQuota, 10)); err != nil {
|
|
| 337 |
+ if c.Resources.CpuQuota != 0 {
|
|
| 338 |
+ if err = writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(c.Resources.CpuQuota, 10)); err != nil {
|
|
| 339 | 339 |
return err |
| 340 | 340 |
} |
| 341 | 341 |
} |
| 342 |
- if c.CpuPeriod != 0 {
|
|
| 343 |
- if err = writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(c.CpuPeriod, 10)); err != nil {
|
|
| 342 |
+ if c.Resources.CpuPeriod != 0 {
|
|
| 343 |
+ if err = writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(c.Resources.CpuPeriod, 10)); err != nil {
|
|
| 344 | 344 |
return err |
| 345 | 345 |
} |
| 346 | 346 |
} |
| 347 |
- if c.CpuRtPeriod != 0 {
|
|
| 348 |
- if err = writeFile(path, "cpu.rt_period_us", strconv.FormatInt(c.CpuRtPeriod, 10)); err != nil {
|
|
| 347 |
+ if c.Resources.CpuRtPeriod != 0 {
|
|
| 348 |
+ if err = writeFile(path, "cpu.rt_period_us", strconv.FormatInt(c.Resources.CpuRtPeriod, 10)); err != nil {
|
|
| 349 | 349 |
return err |
| 350 | 350 |
} |
| 351 | 351 |
} |
| 352 |
- if c.CpuRtRuntime != 0 {
|
|
| 353 |
- if err = writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(c.CpuRtRuntime, 10)); err != nil {
|
|
| 352 |
+ if c.Resources.CpuRtRuntime != 0 {
|
|
| 353 |
+ if err = writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(c.Resources.CpuRtRuntime, 10)); err != nil {
|
|
| 354 | 354 |
return err |
| 355 | 355 |
} |
| 356 | 356 |
} |
| ... | ... |
@@ -418,15 +418,15 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
|
| 418 | 418 |
if err != nil {
|
| 419 | 419 |
return err |
| 420 | 420 |
} |
| 421 |
- prevState := m.Cgroups.Freezer |
|
| 422 |
- m.Cgroups.Freezer = state |
|
| 421 |
+ prevState := m.Cgroups.Resources.Freezer |
|
| 422 |
+ m.Cgroups.Resources.Freezer = state |
|
| 423 | 423 |
freezer, err := subsystems.Get("freezer")
|
| 424 | 424 |
if err != nil {
|
| 425 | 425 |
return err |
| 426 | 426 |
} |
| 427 | 427 |
err = freezer.Set(path, m.Cgroups) |
| 428 | 428 |
if err != nil {
|
| 429 |
- m.Cgroups.Freezer = prevState |
|
| 429 |
+ m.Cgroups.Resources.Freezer = prevState |
|
| 430 | 430 |
return err |
| 431 | 431 |
} |
| 432 | 432 |
return nil |
| ... | ... |
@@ -510,8 +510,8 @@ func setKernelMemory(c *configs.Cgroup) error {
|
| 510 | 510 |
return err |
| 511 | 511 |
} |
| 512 | 512 |
|
| 513 |
- if c.KernelMemory > 0 {
|
|
| 514 |
- err = writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(c.KernelMemory, 10)) |
|
| 513 |
+ if c.Resources.KernelMemory > 0 {
|
|
| 514 |
+ err = writeFile(path, "memory.kmem.limit_in_bytes", strconv.FormatInt(c.Resources.KernelMemory, 10)) |
|
| 515 | 515 |
if err != nil {
|
| 516 | 516 |
return err |
| 517 | 517 |
} |
| ... | ... |
@@ -527,33 +527,33 @@ func joinMemory(c *configs.Cgroup, pid int) error {
|
| 527 | 527 |
} |
| 528 | 528 |
|
| 529 | 529 |
// -1 disables memoryswap |
| 530 |
- if c.MemorySwap > 0 {
|
|
| 531 |
- err = writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(c.MemorySwap, 10)) |
|
| 530 |
+ if c.Resources.MemorySwap > 0 {
|
|
| 531 |
+ err = writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(c.Resources.MemorySwap, 10)) |
|
| 532 | 532 |
if err != nil {
|
| 533 | 533 |
return err |
| 534 | 534 |
} |
| 535 | 535 |
} |
| 536 |
- if c.MemoryReservation > 0 {
|
|
| 537 |
- err = writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(c.MemoryReservation, 10)) |
|
| 536 |
+ if c.Resources.MemoryReservation > 0 {
|
|
| 537 |
+ err = writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(c.Resources.MemoryReservation, 10)) |
|
| 538 | 538 |
if err != nil {
|
| 539 | 539 |
return err |
| 540 | 540 |
} |
| 541 | 541 |
} |
| 542 |
- if c.OomKillDisable {
|
|
| 542 |
+ if c.Resources.OomKillDisable {
|
|
| 543 | 543 |
if err := writeFile(path, "memory.oom_control", "1"); err != nil {
|
| 544 | 544 |
return err |
| 545 | 545 |
} |
| 546 | 546 |
} |
| 547 | 547 |
|
| 548 |
- if c.MemorySwappiness >= 0 && c.MemorySwappiness <= 100 {
|
|
| 549 |
- err = writeFile(path, "memory.swappiness", strconv.FormatInt(c.MemorySwappiness, 10)) |
|
| 548 |
+ if c.Resources.MemorySwappiness >= 0 && c.Resources.MemorySwappiness <= 100 {
|
|
| 549 |
+ err = writeFile(path, "memory.swappiness", strconv.FormatInt(c.Resources.MemorySwappiness, 10)) |
|
| 550 | 550 |
if err != nil {
|
| 551 | 551 |
return err |
| 552 | 552 |
} |
| 553 |
- } else if c.MemorySwappiness == -1 {
|
|
| 553 |
+ } else if c.Resources.MemorySwappiness == -1 {
|
|
| 554 | 554 |
return nil |
| 555 | 555 |
} else {
|
| 556 |
- return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", c.MemorySwappiness)
|
|
| 556 |
+ return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", c.Resources.MemorySwappiness)
|
|
| 557 | 557 |
} |
| 558 | 558 |
|
| 559 | 559 |
return nil |
| ... | ... |
@@ -582,12 +582,12 @@ func joinBlkio(c *configs.Cgroup, pid int) error {
|
| 582 | 582 |
return err |
| 583 | 583 |
} |
| 584 | 584 |
// systemd doesn't directly support this in the dbus properties |
| 585 |
- if c.BlkioLeafWeight != 0 {
|
|
| 586 |
- if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(c.BlkioLeafWeight), 10)); err != nil {
|
|
| 585 |
+ if c.Resources.BlkioLeafWeight != 0 {
|
|
| 586 |
+ if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(c.Resources.BlkioLeafWeight), 10)); err != nil {
|
|
| 587 | 587 |
return err |
| 588 | 588 |
} |
| 589 | 589 |
} |
| 590 |
- for _, wd := range c.BlkioWeightDevice {
|
|
| 590 |
+ for _, wd := range c.Resources.BlkioWeightDevice {
|
|
| 591 | 591 |
if err := writeFile(path, "blkio.weight_device", wd.WeightString()); err != nil {
|
| 592 | 592 |
return err |
| 593 | 593 |
} |
| ... | ... |
@@ -595,22 +595,22 @@ func joinBlkio(c *configs.Cgroup, pid int) error {
|
| 595 | 595 |
return err |
| 596 | 596 |
} |
| 597 | 597 |
} |
| 598 |
- for _, td := range c.BlkioThrottleReadBpsDevice {
|
|
| 598 |
+ for _, td := range c.Resources.BlkioThrottleReadBpsDevice {
|
|
| 599 | 599 |
if err := writeFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil {
|
| 600 | 600 |
return err |
| 601 | 601 |
} |
| 602 | 602 |
} |
| 603 |
- for _, td := range c.BlkioThrottleWriteBpsDevice {
|
|
| 603 |
+ for _, td := range c.Resources.BlkioThrottleWriteBpsDevice {
|
|
| 604 | 604 |
if err := writeFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil {
|
| 605 | 605 |
return err |
| 606 | 606 |
} |
| 607 | 607 |
} |
| 608 |
- for _, td := range c.BlkioThrottleReadIOPSDevice {
|
|
| 608 |
+ for _, td := range c.Resources.BlkioThrottleReadIOPSDevice {
|
|
| 609 | 609 |
if err := writeFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil {
|
| 610 | 610 |
return err |
| 611 | 611 |
} |
| 612 | 612 |
} |
| 613 |
- for _, td := range c.BlkioThrottleWriteIOPSDevice {
|
|
| 613 |
+ for _, td := range c.Resources.BlkioThrottleWriteIOPSDevice {
|
|
| 614 | 614 |
if err := writeFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil {
|
| 615 | 615 |
return err |
| 616 | 616 |
} |
| ... | ... |
@@ -16,6 +16,14 @@ type Cgroup struct {
|
| 16 | 16 |
// name of parent cgroup or slice |
| 17 | 17 |
Parent string `json:"parent"` |
| 18 | 18 |
|
| 19 |
+ // ScopePrefix decribes prefix for the scope name |
|
| 20 |
+ ScopePrefix string `json:"scope_prefix"` |
|
| 21 |
+ |
|
| 22 |
+ // Resources contains various cgroups settings to apply |
|
| 23 |
+ Resources *Resources `json:"resources"` |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+type Resources struct {
|
|
| 19 | 27 |
// If this is true allow access to any kind of device within the container. If false, allow access only to devices explicitly listed in the allowed_devices list. |
| 20 | 28 |
AllowAllDevices bool `json:"allow_all_devices"` |
| 21 | 29 |
|
| ... | ... |
@@ -83,9 +91,6 @@ type Cgroup struct {
|
| 83 | 83 |
// Hugetlb limit (in bytes) |
| 84 | 84 |
HugetlbLimit []*HugepageLimit `json:"hugetlb_limit"` |
| 85 | 85 |
|
| 86 |
- // ScopePrefix decribes prefix for the scope name |
|
| 87 |
- ScopePrefix string `json:"scope_prefix"` |
|
| 88 |
- |
|
| 89 | 86 |
// Whether to disable OOM Killer |
| 90 | 87 |
OomKillDisable bool `json:"oom_kill_disable"` |
| 91 | 88 |
|
| ... | ... |
@@ -985,7 +985,7 @@ func (c *linuxContainer) currentStatus() (Status, error) {
|
| 985 | 985 |
} |
| 986 | 986 |
return 0, newSystemError(err) |
| 987 | 987 |
} |
| 988 |
- if c.config.Cgroups != nil && c.config.Cgroups.Freezer == configs.Frozen {
|
|
| 988 |
+ if c.config.Cgroups != nil && c.config.Cgroups.Resources != nil && c.config.Cgroups.Resources.Freezer == configs.Frozen {
|
|
| 989 | 989 |
return Paused, nil |
| 990 | 990 |
} |
| 991 | 991 |
return Running, nil |
| ... | ... |
@@ -14,6 +14,8 @@ const ( |
| 14 | 14 |
InitMsg uint16 = 62000 |
| 15 | 15 |
PidAttr uint16 = 27281 |
| 16 | 16 |
ConsolePathAttr uint16 = 27282 |
| 17 |
+ // When syscall.NLA_HDRLEN is in gccgo, take this out. |
|
| 18 |
+ syscall_NLA_HDRLEN = (syscall.SizeofNlAttr + syscall.NLA_ALIGNTO - 1) & ^(syscall.NLA_ALIGNTO - 1) |
|
| 17 | 19 |
) |
| 18 | 20 |
|
| 19 | 21 |
type Int32msg struct {
|
| ... | ... |
@@ -34,7 +36,7 @@ func (msg *Int32msg) Serialize() []byte {
|
| 34 | 34 |
} |
| 35 | 35 |
|
| 36 | 36 |
func (msg *Int32msg) Len() int {
|
| 37 |
- return syscall.NLA_HDRLEN + 4 |
|
| 37 |
+ return syscall_NLA_HDRLEN + 4 |
|
| 38 | 38 |
} |
| 39 | 39 |
|
| 40 | 40 |
// bytemsg has the following representation |
| ... | ... |
@@ -56,5 +58,5 @@ func (msg *Bytemsg) Serialize() []byte {
|
| 56 | 56 |
} |
| 57 | 57 |
|
| 58 | 58 |
func (msg *Bytemsg) Len() int {
|
| 59 |
- return syscall.NLA_HDRLEN + len(msg.Value) + 1 // null-terminated |
|
| 59 |
+ return syscall_NLA_HDRLEN + len(msg.Value) + 1 // null-terminated |
|
| 60 | 60 |
} |