Merge remote-tracking branch 'upstream/master' into dev/static-args
This commit is contained in:
commit
321467bf1b
@ -26,9 +26,14 @@ are very busy and read the mailing lists.
|
|||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
- Fork the repository on GitHub
|
- Fork the repository on GitHub
|
||||||
- Read the [README](README.md) for build and test instructions
|
|
||||||
- Play with the project, submit bugs, submit pull requests!
|
- Play with the project, submit bugs, submit pull requests!
|
||||||
|
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Each plugin is compiled simply with `go build`. A script, `build.sh`,
|
||||||
|
is supplied which will build all the plugins in the repo.
|
||||||
|
|
||||||
## Contribution workflow
|
## Contribution workflow
|
||||||
|
|
||||||
This is a rough outline of how to prepare a contribution:
|
This is a rough outline of how to prepare a contribution:
|
||||||
|
32
Godeps/Godeps.json
generated
32
Godeps/Godeps.json
generated
@ -12,38 +12,38 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/containernetworking/cni/libcni",
|
"ImportPath": "github.com/containernetworking/cni/libcni",
|
||||||
"Comment": "v0.6.0-rc1",
|
"Comment": "v0.7.0-alpha1",
|
||||||
"Rev": "a2da8f8d7fd8e6dc25f336408a8ac86f050fbd88"
|
"Rev": "07c1a6da47b7fbf8b357f4949ecce2113e598491"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/containernetworking/cni/pkg/invoke",
|
"ImportPath": "github.com/containernetworking/cni/pkg/invoke",
|
||||||
"Comment": "v0.6.0-rc1",
|
"Comment": "v0.7.0-alpha1",
|
||||||
"Rev": "a2da8f8d7fd8e6dc25f336408a8ac86f050fbd88"
|
"Rev": "07c1a6da47b7fbf8b357f4949ecce2113e598491"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/containernetworking/cni/pkg/skel",
|
"ImportPath": "github.com/containernetworking/cni/pkg/skel",
|
||||||
"Comment": "v0.6.0-rc1",
|
"Comment": "v0.7.0-alpha1",
|
||||||
"Rev": "a2da8f8d7fd8e6dc25f336408a8ac86f050fbd88"
|
"Rev": "07c1a6da47b7fbf8b357f4949ecce2113e598491"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/containernetworking/cni/pkg/types",
|
"ImportPath": "github.com/containernetworking/cni/pkg/types",
|
||||||
"Comment": "v0.6.0-rc1",
|
"Comment": "v0.7.0-alpha1",
|
||||||
"Rev": "a2da8f8d7fd8e6dc25f336408a8ac86f050fbd88"
|
"Rev": "07c1a6da47b7fbf8b357f4949ecce2113e598491"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/containernetworking/cni/pkg/types/020",
|
"ImportPath": "github.com/containernetworking/cni/pkg/types/020",
|
||||||
"Comment": "v0.6.0-rc1",
|
"Comment": "v0.7.0-alpha1",
|
||||||
"Rev": "a2da8f8d7fd8e6dc25f336408a8ac86f050fbd88"
|
"Rev": "07c1a6da47b7fbf8b357f4949ecce2113e598491"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/containernetworking/cni/pkg/types/current",
|
"ImportPath": "github.com/containernetworking/cni/pkg/types/current",
|
||||||
"Comment": "v0.6.0-rc1",
|
"Comment": "v0.7.0-alpha1",
|
||||||
"Rev": "a2da8f8d7fd8e6dc25f336408a8ac86f050fbd88"
|
"Rev": "07c1a6da47b7fbf8b357f4949ecce2113e598491"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/containernetworking/cni/pkg/version",
|
"ImportPath": "github.com/containernetworking/cni/pkg/version",
|
||||||
"Comment": "v0.6.0-rc1",
|
"Comment": "v0.7.0-alpha1",
|
||||||
"Rev": "a2da8f8d7fd8e6dc25f336408a8ac86f050fbd88"
|
"Rev": "07c1a6da47b7fbf8b357f4949ecce2113e598491"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-iptables/iptables",
|
"ImportPath": "github.com/coreos/go-iptables/iptables",
|
||||||
@ -52,8 +52,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/coreos/go-systemd/activation",
|
"ImportPath": "github.com/coreos/go-systemd/activation",
|
||||||
"Comment": "v2-53-g2688e91",
|
"Comment": "v17",
|
||||||
"Rev": "2688e91251d9d8e404e86dd8f096e23b2f086958"
|
"Rev": "39ca1b05acc7ad1220e09f133283b8859a8b71ab"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/d2g/dhcp4",
|
"ImportPath": "github.com/d2g/dhcp4",
|
||||||
|
@ -4,12 +4,14 @@
|
|||||||
# plugins
|
# plugins
|
||||||
Some CNI network plugins, maintained by the containernetworking team. For more information, see the individual READMEs.
|
Some CNI network plugins, maintained by the containernetworking team. For more information, see the individual READMEs.
|
||||||
|
|
||||||
|
Read [CONTRIBUTING](CONTRIBUTING.md) for build and test instructions.
|
||||||
|
|
||||||
## Plugins supplied:
|
## Plugins supplied:
|
||||||
### Main: interface-creating
|
### Main: interface-creating
|
||||||
* `bridge`: Creates a bridge, adds the host and the container to it.
|
* `bridge`: Creates a bridge, adds the host and the container to it.
|
||||||
* `ipvlan`: Adds an [ipvlan](https://www.kernel.org/doc/Documentation/networking/ipvlan.txt) interface in the container
|
* `ipvlan`: Adds an [ipvlan](https://www.kernel.org/doc/Documentation/networking/ipvlan.txt) interface in the container.
|
||||||
* `loopback`: Creates a loopback interface
|
* `loopback`: Set the state of loopback interface to up.
|
||||||
* `macvlan`: Creates a new MAC address, forwards all traffic to that to the container
|
* `macvlan`: Creates a new MAC address, forwards all traffic to that to the container.
|
||||||
* `ptp`: Creates a veth pair.
|
* `ptp`: Creates a veth pair.
|
||||||
* `vlan`: Allocates a vlan device.
|
* `vlan`: Allocates a vlan device.
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func ExecAdd(plugin string, netconf []byte) (types.Result, error) {
|
func ExecAdd(plugin string, netconf []byte) (types.Result, error) {
|
||||||
return invoke.DelegateAdd(plugin, netconf)
|
return invoke.DelegateAdd(plugin, netconf, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExecDel(plugin string, netconf []byte) error {
|
func ExecDel(plugin string, netconf []byte) error {
|
||||||
return invoke.DelegateDel(plugin, netconf)
|
return invoke.DelegateDel(plugin, netconf, nil)
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ func (d *DHCP) clearLease(contID, netName string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getListener() (net.Listener, error) {
|
func getListener() (net.Listener, error) {
|
||||||
l, err := activation.Listeners(true)
|
l, err := activation.Listeners()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,8 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,6 +73,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
func rpcCall(method string, args *skel.CmdArgs, result interface{}) error {
|
func rpcCall(method string, args *skel.CmdArgs, result interface{}) error {
|
||||||
client, err := rpc.DialHTTP("unix", socketPath)
|
client, err := rpc.DialHTTP("unix", socketPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -372,7 +372,7 @@ var _ = Describe("IPAM config", func() {
|
|||||||
"type": "host-local",
|
"type": "host-local",
|
||||||
"ranges": [
|
"ranges": [
|
||||||
[{"subnet": "10.1.2.0/24"}],
|
[{"subnet": "10.1.2.0/24"}],
|
||||||
[{"subnet": "2001:db8:1::/24"}]
|
[{"subnet": "2001:db8:1::/48"}]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
@ -40,6 +40,12 @@ func (r *Range) Canonicalize() error {
|
|||||||
return fmt.Errorf("IPNet IP and Mask version mismatch")
|
return fmt.Errorf("IPNet IP and Mask version mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure Subnet IP is the network address, not some other address
|
||||||
|
networkIP := r.Subnet.IP.Mask(r.Subnet.Mask)
|
||||||
|
if !r.Subnet.IP.Equal(networkIP) {
|
||||||
|
return fmt.Errorf("Network has host bits set. For a subnet mask of length %d the network address is %s", ones, networkIP.String())
|
||||||
|
}
|
||||||
|
|
||||||
// If the gateway is nil, claim .1
|
// If the gateway is nil, claim .1
|
||||||
if r.Gateway == nil {
|
if r.Gateway == nil {
|
||||||
r.Gateway = ip.NextIP(r.Subnet.IP)
|
r.Gateway = ip.NextIP(r.Subnet.IP)
|
||||||
|
@ -25,7 +25,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("IP ranges", func() {
|
var _ = Describe("IP ranges", func() {
|
||||||
It("should generate sane defaults for ipv4", func() {
|
It("should generate sane defaults for ipv4 with a clean prefix", func() {
|
||||||
snstr := "192.0.2.0/24"
|
snstr := "192.0.2.0/24"
|
||||||
r := Range{Subnet: mustSubnet(snstr)}
|
r := Range{Subnet: mustSubnet(snstr)}
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ var _ = Describe("IP ranges", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
Expect(r).To(Equal(Range{
|
Expect(r).To(Equal(Range{
|
||||||
Subnet: mustSubnet(snstr),
|
Subnet: networkSubnet(snstr),
|
||||||
RangeStart: net.IP{192, 0, 2, 1},
|
RangeStart: net.IP{192, 0, 2, 1},
|
||||||
RangeEnd: net.IP{192, 0, 2, 254},
|
RangeEnd: net.IP{192, 0, 2, 254},
|
||||||
Gateway: net.IP{192, 0, 2, 1},
|
Gateway: net.IP{192, 0, 2, 1},
|
||||||
@ -47,13 +47,41 @@ var _ = Describe("IP ranges", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
Expect(r).To(Equal(Range{
|
Expect(r).To(Equal(Range{
|
||||||
Subnet: mustSubnet(snstr),
|
Subnet: networkSubnet(snstr),
|
||||||
RangeStart: net.IP{192, 0, 2, 1},
|
RangeStart: net.IP{192, 0, 2, 1},
|
||||||
RangeEnd: net.IP{192, 0, 2, 126},
|
RangeEnd: net.IP{192, 0, 2, 126},
|
||||||
Gateway: net.IP{192, 0, 2, 1},
|
Gateway: net.IP{192, 0, 2, 1},
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
It("should generate sane defaults for ipv6", func() {
|
It("should reject ipv4 subnet using a masked address", func() {
|
||||||
|
snstr := "192.0.2.12/24"
|
||||||
|
r := Range{Subnet: mustSubnet(snstr)}
|
||||||
|
|
||||||
|
err := r.Canonicalize()
|
||||||
|
Expect(err).Should(MatchError("Network has host bits set. For a subnet mask of length 24 the network address is 192.0.2.0"))
|
||||||
|
})
|
||||||
|
It("should reject ipv6 subnet using a masked address", func() {
|
||||||
|
snstr := "2001:DB8:1::24:19ff:fee1:c44a/64"
|
||||||
|
r := Range{Subnet: mustSubnet(snstr)}
|
||||||
|
|
||||||
|
err := r.Canonicalize()
|
||||||
|
Expect(err).Should(MatchError("Network has host bits set. For a subnet mask of length 64 the network address is 2001:db8:1::"))
|
||||||
|
})
|
||||||
|
It("should reject ipv6 prefix with host bit set", func() {
|
||||||
|
snstr := "2001:DB8:24:19ff::/63"
|
||||||
|
r := Range{Subnet: mustSubnet(snstr)}
|
||||||
|
|
||||||
|
err := r.Canonicalize()
|
||||||
|
Expect(err).Should(MatchError("Network has host bits set. For a subnet mask of length 63 the network address is 2001:db8:24:19fe::"))
|
||||||
|
})
|
||||||
|
It("should reject ipv4 network with host bit set", func() {
|
||||||
|
snstr := "192.168.127.0/23"
|
||||||
|
r := Range{Subnet: mustSubnet(snstr)}
|
||||||
|
|
||||||
|
err := r.Canonicalize()
|
||||||
|
Expect(err).Should(MatchError("Network has host bits set. For a subnet mask of length 23 the network address is 192.168.126.0"))
|
||||||
|
})
|
||||||
|
It("should generate sane defaults for ipv6 with a clean prefix", func() {
|
||||||
snstr := "2001:DB8:1::/64"
|
snstr := "2001:DB8:1::/64"
|
||||||
r := Range{Subnet: mustSubnet(snstr)}
|
r := Range{Subnet: mustSubnet(snstr)}
|
||||||
|
|
||||||
@ -61,7 +89,7 @@ var _ = Describe("IP ranges", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
Expect(r).To(Equal(Range{
|
Expect(r).To(Equal(Range{
|
||||||
Subnet: mustSubnet(snstr),
|
Subnet: networkSubnet(snstr),
|
||||||
RangeStart: net.ParseIP("2001:DB8:1::1"),
|
RangeStart: net.ParseIP("2001:DB8:1::1"),
|
||||||
RangeEnd: net.ParseIP("2001:DB8:1::ffff:ffff:ffff:ffff"),
|
RangeEnd: net.ParseIP("2001:DB8:1::ffff:ffff:ffff:ffff"),
|
||||||
Gateway: net.ParseIP("2001:DB8:1::1"),
|
Gateway: net.ParseIP("2001:DB8:1::1"),
|
||||||
@ -75,16 +103,17 @@ var _ = Describe("IP ranges", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should reject invalid RangeStart and RangeEnd specifications", func() {
|
It("should reject invalid RangeStart and RangeEnd specifications", func() {
|
||||||
r := Range{Subnet: mustSubnet("192.0.2.0/24"), RangeStart: net.ParseIP("192.0.3.0")}
|
snstr := "192.0.2.0/24"
|
||||||
|
r := Range{Subnet: mustSubnet(snstr), RangeStart: net.ParseIP("192.0.3.0")}
|
||||||
err := r.Canonicalize()
|
err := r.Canonicalize()
|
||||||
Expect(err).Should(MatchError("RangeStart 192.0.3.0 not in network 192.0.2.0/24"))
|
Expect(err).Should(MatchError("RangeStart 192.0.3.0 not in network 192.0.2.0/24"))
|
||||||
|
|
||||||
r = Range{Subnet: mustSubnet("192.0.2.0/24"), RangeEnd: net.ParseIP("192.0.4.0")}
|
r = Range{Subnet: mustSubnet(snstr), RangeEnd: net.ParseIP("192.0.4.0")}
|
||||||
err = r.Canonicalize()
|
err = r.Canonicalize()
|
||||||
Expect(err).Should(MatchError("RangeEnd 192.0.4.0 not in network 192.0.2.0/24"))
|
Expect(err).Should(MatchError("RangeEnd 192.0.4.0 not in network 192.0.2.0/24"))
|
||||||
|
|
||||||
r = Range{
|
r = Range{
|
||||||
Subnet: mustSubnet("192.0.2.0/24"),
|
Subnet: networkSubnet(snstr),
|
||||||
RangeStart: net.ParseIP("192.0.2.50"),
|
RangeStart: net.ParseIP("192.0.2.50"),
|
||||||
RangeEnd: net.ParseIP("192.0.2.40"),
|
RangeEnd: net.ParseIP("192.0.2.40"),
|
||||||
}
|
}
|
||||||
@ -99,8 +128,9 @@ var _ = Describe("IP ranges", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should parse all fields correctly", func() {
|
It("should parse all fields correctly", func() {
|
||||||
|
snstr := "192.0.2.0/24"
|
||||||
r := Range{
|
r := Range{
|
||||||
Subnet: mustSubnet("192.0.2.0/24"),
|
Subnet: mustSubnet(snstr),
|
||||||
RangeStart: net.ParseIP("192.0.2.40"),
|
RangeStart: net.ParseIP("192.0.2.40"),
|
||||||
RangeEnd: net.ParseIP("192.0.2.50"),
|
RangeEnd: net.ParseIP("192.0.2.50"),
|
||||||
Gateway: net.ParseIP("192.0.2.254"),
|
Gateway: net.ParseIP("192.0.2.254"),
|
||||||
@ -109,7 +139,7 @@ var _ = Describe("IP ranges", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
Expect(r).To(Equal(Range{
|
Expect(r).To(Equal(Range{
|
||||||
Subnet: mustSubnet("192.0.2.0/24"),
|
Subnet: networkSubnet(snstr),
|
||||||
RangeStart: net.IP{192, 0, 2, 40},
|
RangeStart: net.IP{192, 0, 2, 40},
|
||||||
RangeEnd: net.IP{192, 0, 2, 50},
|
RangeEnd: net.IP{192, 0, 2, 50},
|
||||||
Gateway: net.IP{192, 0, 2, 254},
|
Gateway: net.IP{192, 0, 2, 254},
|
||||||
@ -207,3 +237,9 @@ func mustSubnet(s string) types.IPNet {
|
|||||||
canonicalizeIP(&n.IP)
|
canonicalizeIP(&n.IP)
|
||||||
return types.IPNet(*n)
|
return types.IPNet(*n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func networkSubnet(s string) types.IPNet {
|
||||||
|
net := mustSubnet(s)
|
||||||
|
net.IP = net.IP.Mask(net.Mask)
|
||||||
|
return net
|
||||||
|
}
|
||||||
|
@ -444,7 +444,7 @@ var _ = Describe("host-local Operations", func() {
|
|||||||
"dataDir": "%s",
|
"dataDir": "%s",
|
||||||
"ranges": [
|
"ranges": [
|
||||||
[{"subnet":"172.16.1.0/24"}, { "subnet": "10.1.2.0/24" }],
|
[{"subnet":"172.16.1.0/24"}, { "subnet": "10.1.2.0/24" }],
|
||||||
[{ "subnet": "2001:db8:1::/24" }]
|
[{ "subnet": "2001:db8:1::/48" }]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"args": {
|
"args": {
|
||||||
|
@ -29,7 +29,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdAdd(args *skel.CmdArgs) error {
|
func cmdAdd(args *skel.CmdArgs) error {
|
||||||
|
@ -57,7 +57,13 @@ type Address struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// canonicalizeIP makes sure a provided ip is in standard form
|
// canonicalizeIP makes sure a provided ip is in standard form
|
||||||
@ -72,7 +78,9 @@ func canonicalizeIP(ip *net.IP) error {
|
|||||||
return fmt.Errorf("IP %s not v4 nor v6", *ip)
|
return fmt.Errorf("IP %s not v4 nor v6", *ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIPAMConfig creates a NetworkConfig from the given network name.
|
// LoadIPAMConfig creates IPAMConfig using json encoded configuration provided
|
||||||
|
// as `bytes`. At the moment values provided in envArgs are ignored so there
|
||||||
|
// is no possibility to overload the json configuration using envArgs
|
||||||
func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
|
func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
|
||||||
n := Net{}
|
n := Net{}
|
||||||
if err := json.Unmarshal(bytes, &n); err != nil {
|
if err := json.Unmarshal(bytes, &n); err != nil {
|
||||||
@ -167,7 +175,6 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
Gateway: v.Gateway})
|
Gateway: v.Gateway})
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Routes = ipamConf.Routes
|
|
||||||
return types.PrintResult(result, confVersion)
|
return types.PrintResult(result, confVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
@ -36,6 +37,9 @@ import (
|
|||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// For testcases to force an error after IPAM has been performed
|
||||||
|
var debugPostIPAMError error
|
||||||
|
|
||||||
const defaultBrName = "cni0"
|
const defaultBrName = "cni0"
|
||||||
|
|
||||||
type NetConf struct {
|
type NetConf struct {
|
||||||
@ -323,6 +327,8 @@ func enableIPForward(family int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cmdAdd(args *skel.CmdArgs) error {
|
func cmdAdd(args *skel.CmdArgs) error {
|
||||||
|
var success bool = false
|
||||||
|
|
||||||
n, cniVersion, err := loadNetConf(args.StdinData)
|
n, cniVersion, err := loadNetConf(args.StdinData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -358,6 +364,15 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// release IP in case of failure
|
||||||
|
defer func() {
|
||||||
|
if !success {
|
||||||
|
os.Setenv("CNI_COMMAND", "DEL")
|
||||||
|
ipam.ExecDel(n.IPAM.Type, args.StdinData)
|
||||||
|
os.Setenv("CNI_COMMAND", "ADD")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// Convert whatever the IPAM result was into the current Result type
|
// Convert whatever the IPAM result was into the current Result type
|
||||||
result, err := current.NewResultFromResult(r)
|
result, err := current.NewResultFromResult(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -454,6 +469,13 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
|
|
||||||
result.DNS = n.DNS
|
result.DNS = n.DNS
|
||||||
|
|
||||||
|
// Return an error requested by testcases, if any
|
||||||
|
if debugPostIPAMError != nil {
|
||||||
|
return debugPostIPAMError
|
||||||
|
}
|
||||||
|
|
||||||
|
success = true
|
||||||
|
|
||||||
return types.PrintResult(result, cniVersion)
|
return types.PrintResult(result, cniVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,5 +524,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
"github.com/containernetworking/cni/pkg/skel"
|
||||||
@ -83,6 +85,9 @@ const (
|
|||||||
"ipam": {
|
"ipam": {
|
||||||
"type": "host-local"`
|
"type": "host-local"`
|
||||||
|
|
||||||
|
ipamDataDirStr = `,
|
||||||
|
"dataDir": "%s"`
|
||||||
|
|
||||||
// Single subnet configuration (legacy)
|
// Single subnet configuration (legacy)
|
||||||
subnetConfStr = `,
|
subnetConfStr = `,
|
||||||
"subnet": "%s"`
|
"subnet": "%s"`
|
||||||
@ -110,10 +115,13 @@ const (
|
|||||||
|
|
||||||
// netConfJSON() generates a JSON network configuration string
|
// netConfJSON() generates a JSON network configuration string
|
||||||
// for a test case.
|
// for a test case.
|
||||||
func (tc testCase) netConfJSON() string {
|
func (tc testCase) netConfJSON(dataDir string) string {
|
||||||
conf := fmt.Sprintf(netConfStr, tc.cniVersion, BRNAME)
|
conf := fmt.Sprintf(netConfStr, tc.cniVersion, BRNAME)
|
||||||
if tc.subnet != "" || tc.ranges != nil {
|
if tc.subnet != "" || tc.ranges != nil {
|
||||||
conf += ipamStartStr
|
conf += ipamStartStr
|
||||||
|
if dataDir != "" {
|
||||||
|
conf += fmt.Sprintf(ipamDataDirStr, dataDir)
|
||||||
|
}
|
||||||
if tc.subnet != "" {
|
if tc.subnet != "" {
|
||||||
conf += tc.subnetConfig()
|
conf += tc.subnetConfig()
|
||||||
}
|
}
|
||||||
@ -152,8 +160,8 @@ var counter uint
|
|||||||
|
|
||||||
// createCmdArgs generates network configuration and creates command
|
// createCmdArgs generates network configuration and creates command
|
||||||
// arguments for a test case.
|
// arguments for a test case.
|
||||||
func (tc testCase) createCmdArgs(targetNS ns.NetNS) *skel.CmdArgs {
|
func (tc testCase) createCmdArgs(targetNS ns.NetNS, dataDir string) *skel.CmdArgs {
|
||||||
conf := tc.netConfJSON()
|
conf := tc.netConfJSON(dataDir)
|
||||||
defer func() { counter += 1 }()
|
defer func() { counter += 1 }()
|
||||||
return &skel.CmdArgs{
|
return &skel.CmdArgs{
|
||||||
ContainerID: fmt.Sprintf("dummy-%d", counter),
|
ContainerID: fmt.Sprintf("dummy-%d", counter),
|
||||||
@ -213,9 +221,27 @@ func ipVersion(ip net.IP) string {
|
|||||||
return "6"
|
return "6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func countIPAMIPs(path string) (int, error) {
|
||||||
|
count := 0
|
||||||
|
files, err := ioutil.ReadDir(path)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
for _, file := range files {
|
||||||
|
if file.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if net.ParseIP(file.Name()) != nil {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
type cmdAddDelTester interface {
|
type cmdAddDelTester interface {
|
||||||
setNS(testNS ns.NetNS, targetNS ns.NetNS)
|
setNS(testNS ns.NetNS, targetNS ns.NetNS)
|
||||||
cmdAddTest(tc testCase)
|
cmdAddTest(tc testCase, dataDir string)
|
||||||
cmdDelTest(tc testCase)
|
cmdDelTest(tc testCase)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,9 +266,9 @@ func (tester *testerV03x) setNS(testNS ns.NetNS, targetNS ns.NetNS) {
|
|||||||
tester.targetNS = targetNS
|
tester.targetNS = targetNS
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tester *testerV03x) cmdAddTest(tc testCase) {
|
func (tester *testerV03x) cmdAddTest(tc testCase, dataDir string) {
|
||||||
// Generate network config and command arguments
|
// Generate network config and command arguments
|
||||||
tester.args = tc.createCmdArgs(tester.targetNS)
|
tester.args = tc.createCmdArgs(tester.targetNS, dataDir)
|
||||||
|
|
||||||
// Execute cmdADD on the plugin
|
// Execute cmdADD on the plugin
|
||||||
var result *current.Result
|
var result *current.Result
|
||||||
@ -419,9 +445,9 @@ func (tester *testerV01xOr02x) setNS(testNS ns.NetNS, targetNS ns.NetNS) {
|
|||||||
tester.targetNS = targetNS
|
tester.targetNS = targetNS
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tester *testerV01xOr02x) cmdAddTest(tc testCase) {
|
func (tester *testerV01xOr02x) cmdAddTest(tc testCase, dataDir string) {
|
||||||
// Generate network config and calculate gateway addresses
|
// Generate network config and calculate gateway addresses
|
||||||
tester.args = tc.createCmdArgs(tester.targetNS)
|
tester.args = tc.createCmdArgs(tester.targetNS, dataDir)
|
||||||
|
|
||||||
// Execute cmdADD on the plugin
|
// Execute cmdADD on the plugin
|
||||||
err := tester.testNS.Do(func(ns.NetNS) error {
|
err := tester.testNS.Do(func(ns.NetNS) error {
|
||||||
@ -537,7 +563,7 @@ func (tester *testerV01xOr02x) cmdDelTest(tc testCase) {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdAddDelTest(testNS ns.NetNS, tc testCase) {
|
func cmdAddDelTest(testNS ns.NetNS, tc testCase, dataDir string) {
|
||||||
// Get a Add/Del tester based on test case version
|
// Get a Add/Del tester based on test case version
|
||||||
tester := testerByVersion(tc.cniVersion)
|
tester := testerByVersion(tc.cniVersion)
|
||||||
|
|
||||||
@ -547,7 +573,7 @@ func cmdAddDelTest(testNS ns.NetNS, tc testCase) {
|
|||||||
tester.setNS(testNS, targetNS)
|
tester.setNS(testNS, targetNS)
|
||||||
|
|
||||||
// Test IP allocation
|
// Test IP allocation
|
||||||
tester.cmdAddTest(tc)
|
tester.cmdAddTest(tc, dataDir)
|
||||||
|
|
||||||
// Test IP Release
|
// Test IP Release
|
||||||
tester.cmdDelTest(tc)
|
tester.cmdDelTest(tc)
|
||||||
@ -558,15 +584,23 @@ func cmdAddDelTest(testNS ns.NetNS, tc testCase) {
|
|||||||
|
|
||||||
var _ = Describe("bridge Operations", func() {
|
var _ = Describe("bridge Operations", func() {
|
||||||
var originalNS ns.NetNS
|
var originalNS ns.NetNS
|
||||||
|
var dataDir string
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
// Create a new NetNS so we don't modify the host
|
// Create a new NetNS so we don't modify the host
|
||||||
var err error
|
var err error
|
||||||
originalNS, err = testutils.NewNS()
|
originalNS, err = testutils.NewNS()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
dataDir, err = ioutil.TempDir("", "bridge_test")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
// Do not emulate an error, each test will set this if needed
|
||||||
|
debugPostIPAMError = nil
|
||||||
})
|
})
|
||||||
|
|
||||||
AfterEach(func() {
|
AfterEach(func() {
|
||||||
|
Expect(os.RemoveAll(dataDir)).To(Succeed())
|
||||||
Expect(originalNS.Close()).To(Succeed())
|
Expect(originalNS.Close()).To(Succeed())
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -661,7 +695,7 @@ var _ = Describe("bridge Operations", func() {
|
|||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc.cniVersion = "0.3.0"
|
tc.cniVersion = "0.3.0"
|
||||||
cmdAddDelTest(originalNS, tc)
|
cmdAddDelTest(originalNS, tc, dataDir)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -691,7 +725,7 @@ var _ = Describe("bridge Operations", func() {
|
|||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc.cniVersion = "0.3.1"
|
tc.cniVersion = "0.3.1"
|
||||||
cmdAddDelTest(originalNS, tc)
|
cmdAddDelTest(originalNS, tc, dataDir)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -707,7 +741,7 @@ var _ = Describe("bridge Operations", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
defer targetNS.Close()
|
defer targetNS.Close()
|
||||||
tester.setNS(originalNS, targetNS)
|
tester.setNS(originalNS, targetNS)
|
||||||
tester.args = tc.createCmdArgs(targetNS)
|
tester.args = tc.createCmdArgs(targetNS, dataDir)
|
||||||
|
|
||||||
// Execute cmdDEL on the plugin, expect no errors
|
// Execute cmdDEL on the plugin, expect no errors
|
||||||
tester.cmdDelTest(tc)
|
tester.cmdDelTest(tc)
|
||||||
@ -739,7 +773,7 @@ var _ = Describe("bridge Operations", func() {
|
|||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc.cniVersion = "0.1.0"
|
tc.cniVersion = "0.1.0"
|
||||||
cmdAddDelTest(originalNS, tc)
|
cmdAddDelTest(originalNS, tc, dataDir)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -909,11 +943,44 @@ var _ = Describe("bridge Operations", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
origMac := link.Attrs().HardwareAddr
|
origMac := link.Attrs().HardwareAddr
|
||||||
|
|
||||||
cmdAddDelTest(originalNS, tc)
|
cmdAddDelTest(originalNS, tc, dataDir)
|
||||||
|
|
||||||
link, err = netlink.LinkByName(BRNAME)
|
link, err = netlink.LinkByName(BRNAME)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(link.Attrs().HardwareAddr).To(Equal(origMac))
|
Expect(link.Attrs().HardwareAddr).To(Equal(origMac))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("checks ip release in case of error", func() {
|
||||||
|
err := originalNS.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
tc := testCase{
|
||||||
|
cniVersion: "0.3.1",
|
||||||
|
subnet: "10.1.2.0/24",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err := setupBridge(tc.netConf())
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
args := tc.createCmdArgs(originalNS, dataDir)
|
||||||
|
|
||||||
|
// get number of allocated IPs before asking for a new one
|
||||||
|
before, err := countIPAMIPs(dataDir)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
debugPostIPAMError = fmt.Errorf("debugPostIPAMError")
|
||||||
|
_, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||||
|
return cmdAdd(args)
|
||||||
|
})
|
||||||
|
Expect(err).To(MatchError("debugPostIPAMError"))
|
||||||
|
|
||||||
|
// get number of allocated IPs after failure
|
||||||
|
after, err := countIPAMIPs(dataDir)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(before).To(Equal(after))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -217,5 +217,11 @@ func getLink(devname, hwaddr, kernelpath string) (netlink.Link, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -245,5 +245,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
"github.com/containernetworking/cni/pkg/skel"
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
"github.com/containernetworking/cni/pkg/types/current"
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
"github.com/containernetworking/cni/pkg/version"
|
||||||
@ -68,5 +70,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,8 @@ var _ = Describe("Loopback", func() {
|
|||||||
|
|
||||||
Context("when given a network namespace", func() {
|
Context("when given a network namespace", func() {
|
||||||
It("sets the lo device to UP", func() {
|
It("sets the lo device to UP", func() {
|
||||||
|
|
||||||
|
Skip("TODO: add network name")
|
||||||
command.Env = append(environ, fmt.Sprintf("CNI_COMMAND=%s", "ADD"))
|
command.Env = append(environ, fmt.Sprintf("CNI_COMMAND=%s", "ADD"))
|
||||||
|
|
||||||
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
|
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
|
||||||
@ -78,6 +80,8 @@ var _ = Describe("Loopback", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("sets the lo device to DOWN", func() {
|
It("sets the lo device to DOWN", func() {
|
||||||
|
|
||||||
|
Skip("TODO: add network name")
|
||||||
command.Env = append(environ, fmt.Sprintf("CNI_COMMAND=%s", "DEL"))
|
command.Env = append(environ, fmt.Sprintf("CNI_COMMAND=%s", "DEL"))
|
||||||
|
|
||||||
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
|
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
|
||||||
|
@ -255,5 +255,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -285,5 +285,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -192,5 +192,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -48,10 +48,10 @@ The following is an example [json configuration list](https://github.com/contain
|
|||||||
The result is an `ifb` device in the host namespace redirecting to the `host-interface`, with `tc tbf` applied on the `ifb` device and the `container-interface`
|
The result is an `ifb` device in the host namespace redirecting to the `host-interface`, with `tc tbf` applied on the `ifb` device and the `container-interface`
|
||||||
|
|
||||||
## Network configuration reference
|
## Network configuration reference
|
||||||
* ingressRate: is the rate in Kbps at which traffic can enter an interface. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
* ingressRate: is the rate in bps at which traffic can enter an interface. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
||||||
* ingressBurst: is the maximum amount in Kb that tokens can be made available for instantaneously. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
* ingressBurst: is the maximum amount in bits that tokens can be made available for instantaneously. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
||||||
* egressRate: is the rate in Kbps at which traffic can leave an interface. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
* egressRate: is the rate in bps at which traffic can leave an interface. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
||||||
* egressBurst: is the maximum amount in Kb that tokens can be made available for instantaneously. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
* egressBurst: is the maximum amount in bits that tokens can be made available for instantaneously. (See http://man7.org/linux/man-pages/man8/tbf.8.html)
|
||||||
|
|
||||||
Both ingressRate and ingressBurst must be set in order to limit ingress bandwidth. If neither one is set, then ingress bandwidth is not limited.
|
Both ingressRate and ingressBurst must be set in order to limit ingress bandwidth. If neither one is set, then ingress bandwidth is not limited.
|
||||||
Both egressRate and egressBurst must be set in order to limit egress bandwidth. If neither one is set, then egress bandwidth is not limited.
|
Both egressRate and egressBurst must be set in order to limit egress bandwidth. If neither one is set, then egress bandwidth is not limited.
|
||||||
|
@ -80,7 +80,7 @@ var _ = Describe("bandwidth test", func() {
|
|||||||
"ingressRate": 8,
|
"ingressRate": 8,
|
||||||
"ingressBurst": 8,
|
"ingressBurst": 8,
|
||||||
"egressRate": 16,
|
"egressRate": 16,
|
||||||
"egressBurst": 9,
|
"egressBurst": 8,
|
||||||
"prevResult": {
|
"prevResult": {
|
||||||
"interfaces": [
|
"interfaces": [
|
||||||
{
|
{
|
||||||
@ -135,7 +135,7 @@ var _ = Describe("bandwidth test", func() {
|
|||||||
|
|
||||||
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
||||||
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(2)))
|
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(2)))
|
||||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(9)))
|
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1)))
|
||||||
|
|
||||||
hostVethLink, err := netlink.LinkByName(hostIfname)
|
hostVethLink, err := netlink.LinkByName(hostIfname)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -163,7 +163,7 @@ var _ = Describe("bandwidth test", func() {
|
|||||||
|
|
||||||
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
||||||
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1)))
|
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1)))
|
||||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(8)))
|
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1)))
|
||||||
return nil
|
return nil
|
||||||
})).To(Succeed())
|
})).To(Succeed())
|
||||||
|
|
||||||
@ -176,8 +176,8 @@ var _ = Describe("bandwidth test", func() {
|
|||||||
"type": "bandwidth",
|
"type": "bandwidth",
|
||||||
"ingressRate": 0,
|
"ingressRate": 0,
|
||||||
"ingressBurst": 0,
|
"ingressBurst": 0,
|
||||||
"egressRate": 8,
|
"egressRate": 8000,
|
||||||
"egressBurst": 1,
|
"egressBurst": 80,
|
||||||
"prevResult": {
|
"prevResult": {
|
||||||
"interfaces": [
|
"interfaces": [
|
||||||
{
|
{
|
||||||
@ -245,8 +245,8 @@ var _ = Describe("bandwidth test", func() {
|
|||||||
"type": "bandwidth",
|
"type": "bandwidth",
|
||||||
"egressRate": 0,
|
"egressRate": 0,
|
||||||
"egressBurst": 0,
|
"egressBurst": 0,
|
||||||
"ingressRate": 8,
|
"ingressRate": 8000,
|
||||||
"ingressBurst": 1,
|
"ingressBurst": 80,
|
||||||
"prevResult": {
|
"prevResult": {
|
||||||
"interfaces": [
|
"interfaces": [
|
||||||
{
|
{
|
||||||
@ -302,8 +302,8 @@ var _ = Describe("bandwidth test", func() {
|
|||||||
Expect(qdiscs[0].Attrs().LinkIndex).To(Equal(containerIfLink.Attrs().Index))
|
Expect(qdiscs[0].Attrs().LinkIndex).To(Equal(containerIfLink.Attrs().Index))
|
||||||
|
|
||||||
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
||||||
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1)))
|
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1000)))
|
||||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1)))
|
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(35)))
|
||||||
return nil
|
return nil
|
||||||
})).To(Succeed())
|
})).To(Succeed())
|
||||||
|
|
||||||
@ -426,7 +426,7 @@ var _ = Describe("bandwidth test", func() {
|
|||||||
|
|
||||||
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
||||||
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(2)))
|
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(2)))
|
||||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(9)))
|
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1)))
|
||||||
|
|
||||||
hostVethLink, err := netlink.LinkByName(hostIfname)
|
hostVethLink, err := netlink.LinkByName(hostIfname)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -454,7 +454,7 @@ var _ = Describe("bandwidth test", func() {
|
|||||||
|
|
||||||
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
Expect(qdiscs[0]).To(BeAssignableToTypeOf(&netlink.Tbf{}))
|
||||||
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1)))
|
Expect(qdiscs[0].(*netlink.Tbf).Rate).To(Equal(uint64(1)))
|
||||||
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(8)))
|
Expect(qdiscs[0].(*netlink.Tbf).Limit).To(Equal(uint32(1)))
|
||||||
return nil
|
return nil
|
||||||
})).To(Succeed())
|
})).To(Succeed())
|
||||||
|
|
||||||
@ -625,7 +625,7 @@ var _ = Describe("bandwidth test", func() {
|
|||||||
defer GinkgoRecover()
|
defer GinkgoRecover()
|
||||||
|
|
||||||
containerWithTbfRes, _, err = testutils.CmdAdd(containerWithTbfNS.Path(), "dummy", containerWithTbfIFName, []byte(ptpConf), func() error {
|
containerWithTbfRes, _, err = testutils.CmdAdd(containerWithTbfNS.Path(), "dummy", containerWithTbfIFName, []byte(ptpConf), func() error {
|
||||||
r, err := invoke.DelegateAdd("ptp", []byte(ptpConf))
|
r, err := invoke.DelegateAdd("ptp", []byte(ptpConf), nil)
|
||||||
Expect(r.Print()).To(Succeed())
|
Expect(r.Print()).To(Succeed())
|
||||||
|
|
||||||
return err
|
return err
|
||||||
@ -633,7 +633,7 @@ var _ = Describe("bandwidth test", func() {
|
|||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
containerWithoutTbfRes, _, err = testutils.CmdAdd(containerWithoutTbfNS.Path(), "dummy2", containerWithoutTbfIFName, []byte(ptpConf), func() error {
|
containerWithoutTbfRes, _, err = testutils.CmdAdd(containerWithoutTbfNS.Path(), "dummy2", containerWithoutTbfIFName, []byte(ptpConf), func() error {
|
||||||
r, err := invoke.DelegateAdd("ptp", []byte(ptpConf))
|
r, err := invoke.DelegateAdd("ptp", []byte(ptpConf), nil)
|
||||||
Expect(r.Print()).To(Succeed())
|
Expect(r.Print()).To(Succeed())
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -125,9 +125,10 @@ func createTBF(rateInBits, burstInBits, linkIndex int) error {
|
|||||||
return fmt.Errorf("invalid burst: %d", burstInBits)
|
return fmt.Errorf("invalid burst: %d", burstInBits)
|
||||||
}
|
}
|
||||||
rateInBytes := rateInBits / 8
|
rateInBytes := rateInBits / 8
|
||||||
bufferInBytes := buffer(uint64(rateInBytes), uint32(burstInBits))
|
burstInBytes := burstInBits / 8
|
||||||
|
bufferInBytes := buffer(uint64(rateInBytes), uint32(burstInBytes))
|
||||||
latency := latencyInUsec(latencyInMillis)
|
latency := latencyInUsec(latencyInMillis)
|
||||||
limitInBytes := limit(uint64(rateInBytes), latency, uint32(bufferInBytes))
|
limitInBytes := limit(uint64(rateInBytes), latency, uint32(burstInBytes))
|
||||||
|
|
||||||
qdisc := &netlink.Tbf{
|
qdisc := &netlink.Tbf{
|
||||||
QdiscAttrs: netlink.QdiscAttrs{
|
QdiscAttrs: netlink.QdiscAttrs{
|
||||||
@ -159,7 +160,7 @@ func buffer(rate uint64, burst uint32) uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func limit(rate uint64, latency float64, buffer uint32) uint32 {
|
func limit(rate uint64, latency float64, buffer uint32) uint32 {
|
||||||
return uint32(float64(rate) / float64(netlink.TIME_UNITS_PER_SEC) * (latency + float64(tick2Time(buffer))))
|
return uint32(float64(rate)*latency/float64(netlink.TIME_UNITS_PER_SEC)) + buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
func latencyInUsec(latencyInMillis float64) float64 {
|
func latencyInUsec(latencyInMillis float64) float64 {
|
||||||
|
@ -32,11 +32,11 @@ import (
|
|||||||
// BandwidthEntry corresponds to a single entry in the bandwidth argument,
|
// BandwidthEntry corresponds to a single entry in the bandwidth argument,
|
||||||
// see CONVENTIONS.md
|
// see CONVENTIONS.md
|
||||||
type BandwidthEntry struct {
|
type BandwidthEntry struct {
|
||||||
IngressRate int `json:"ingressRate"` //Bandwidth rate in Kbps for traffic through container. 0 for no limit. If ingressRate is set, ingressBurst must also be set
|
IngressRate int `json:"ingressRate"` //Bandwidth rate in bps for traffic through container. 0 for no limit. If ingressRate is set, ingressBurst must also be set
|
||||||
IngressBurst int `json:"ingressBurst"` //Bandwidth burst in Kb for traffic through container. 0 for no limit. If ingressBurst is set, ingressRate must also be set
|
IngressBurst int `json:"ingressBurst"` //Bandwidth burst in bits for traffic through container. 0 for no limit. If ingressBurst is set, ingressRate must also be set
|
||||||
|
|
||||||
EgressRate int `json:"egressRate"` //Bandwidth rate in Kbps for traffic through container. 0 for no limit. If egressRate is set, egressBurst must also be set
|
EgressRate int `json:"egressRate"` //Bandwidth rate in bps for traffic through container. 0 for no limit. If egressRate is set, egressBurst must also be set
|
||||||
EgressBurst int `json:"egressBurst"` //Bandwidth burst in Kb for traffic through container. 0 for no limit. If egressBurst is set, egressRate must also be set
|
EgressBurst int `json:"egressBurst"` //Bandwidth burst in bits for traffic through container. 0 for no limit. If egressBurst is set, egressRate must also be set
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bw *BandwidthEntry) isZero() bool {
|
func (bw *BandwidthEntry) isZero() bool {
|
||||||
@ -232,5 +232,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.PluginSupports("0.3.0", "0.3.1", version.Current()))
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.PluginSupports("0.3.0", "0.3.1", version.Current()), "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ func delegateAdd(cid, dataDir string, netconf map[string]interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := invoke.DelegateAdd(netconf["type"].(string), netconfBytes)
|
result, err := invoke.DelegateAdd(netconf["type"].(string), netconfBytes, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -261,9 +261,15 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
return fmt.Errorf("failed to parse netconf: %v", err)
|
return fmt.Errorf("failed to parse netconf: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return invoke.DelegateDel(n.Type, netconfBytes)
|
return invoke.DelegateDel(n.Type, netconfBytes, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,13 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.PluginSupports("", "0.1.0", "0.2.0", "0.3.0", version.Current()))
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseConfig parses the supplied configuration (and prevResult) from stdin.
|
// parseConfig parses the supplied configuration (and prevResult) from stdin.
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -29,6 +30,7 @@ import (
|
|||||||
"github.com/containernetworking/cni/pkg/types/current"
|
"github.com/containernetworking/cni/pkg/types/current"
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
"github.com/containernetworking/cni/pkg/version"
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
|
"github.com/vishvananda/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TuningConf represents the network tuning configuration.
|
// TuningConf represents the network tuning configuration.
|
||||||
@ -37,14 +39,35 @@ type TuningConf struct {
|
|||||||
SysCtl map[string]string `json:"sysctl"`
|
SysCtl map[string]string `json:"sysctl"`
|
||||||
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
||||||
PrevResult *current.Result `json:"-"`
|
PrevResult *current.Result `json:"-"`
|
||||||
|
Mac string `json:"mac,omitempty"`
|
||||||
|
Promisc bool `json:"promisc,omitempty"`
|
||||||
|
Mtu int `json:"mtu,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseConf(data []byte) (*TuningConf, error) {
|
type MACEnvArgs struct {
|
||||||
conf := TuningConf{}
|
types.CommonArgs
|
||||||
|
MAC types.UnmarshallableString `json:"mac,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseConf(data []byte, envArgs string) (*TuningConf, error) {
|
||||||
|
conf := TuningConf{Promisc: false}
|
||||||
if err := json.Unmarshal(data, &conf); err != nil {
|
if err := json.Unmarshal(data, &conf); err != nil {
|
||||||
return nil, fmt.Errorf("failed to load netconf: %v", err)
|
return nil, fmt.Errorf("failed to load netconf: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse custom MAC from both env args
|
||||||
|
if envArgs != "" {
|
||||||
|
e := MACEnvArgs{}
|
||||||
|
err := types.LoadArgs(envArgs, &e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.MAC != "" {
|
||||||
|
conf.Mac = string(e.MAC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse previous result.
|
// Parse previous result.
|
||||||
if conf.RawPrevResult != nil {
|
if conf.RawPrevResult != nil {
|
||||||
resultBytes, err := json.Marshal(conf.RawPrevResult)
|
resultBytes, err := json.Marshal(conf.RawPrevResult)
|
||||||
@ -65,8 +88,58 @@ func parseConf(data []byte) (*TuningConf, error) {
|
|||||||
return &conf, nil
|
return &conf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func changeMacAddr(ifName string, newMacAddr string) error {
|
||||||
|
addr, err := net.ParseMAC(newMacAddr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid args %v for MAC addr: %v", newMacAddr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
link, err := netlink.LinkByName(ifName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get %q: %v", ifName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = netlink.LinkSetDown(link)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to set %q down: %v", ifName, err)
|
||||||
|
}
|
||||||
|
err = netlink.LinkSetHardwareAddr(link, addr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to set %q address to %q: %v", ifName, newMacAddr, err)
|
||||||
|
}
|
||||||
|
return netlink.LinkSetUp(link)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateResultsMacAddr(config TuningConf, ifName string, newMacAddr string) {
|
||||||
|
for _, i := range config.PrevResult.Interfaces {
|
||||||
|
if i.Name == ifName {
|
||||||
|
i.Mac = newMacAddr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func changePromisc(ifName string, val bool) error {
|
||||||
|
link, err := netlink.LinkByName(ifName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get %q: %v", ifName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if val {
|
||||||
|
return netlink.SetPromiscOn(link)
|
||||||
|
}
|
||||||
|
return netlink.SetPromiscOff(link)
|
||||||
|
}
|
||||||
|
|
||||||
|
func changeMtu(ifName string, mtu int) error {
|
||||||
|
link, err := netlink.LinkByName(ifName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get %q: %v", ifName, err)
|
||||||
|
}
|
||||||
|
return netlink.LinkSetMTU(link, mtu)
|
||||||
|
}
|
||||||
|
|
||||||
func cmdAdd(args *skel.CmdArgs) error {
|
func cmdAdd(args *skel.CmdArgs) error {
|
||||||
tuningConf, err := parseConf(args.StdinData)
|
tuningConf, err := parseConf(args.StdinData, args.Args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -90,6 +163,25 @@ func cmdAdd(args *skel.CmdArgs) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tuningConf.Mac != "" {
|
||||||
|
if err = changeMacAddr(args.IfName, tuningConf.Mac); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
updateResultsMacAddr(*tuningConf, args.IfName, tuningConf.Mac)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tuningConf.Promisc != false {
|
||||||
|
if err = changePromisc(args.IfName, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tuningConf.Mtu != 0 {
|
||||||
|
if err = changeMtu(args.IfName, tuningConf.Mtu); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -107,5 +199,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/containernetworking/cni/pkg/types/current"
|
"github.com/containernetworking/cni/pkg/types/current"
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
"github.com/containernetworking/plugins/pkg/testutils"
|
"github.com/containernetworking/plugins/pkg/testutils"
|
||||||
|
"net"
|
||||||
|
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
|
|
||||||
@ -109,4 +110,236 @@ var _ = Describe("tuning plugin", func() {
|
|||||||
})
|
})
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("configures and deconfigures promiscas mode with ADD/DEL", func() {
|
||||||
|
conf := []byte(`{
|
||||||
|
"name": "test",
|
||||||
|
"type": "iplink",
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"promisc": true,
|
||||||
|
"prevResult": {
|
||||||
|
"interfaces": [
|
||||||
|
{"name": "dummy0", "sandbox":"netns"}
|
||||||
|
],
|
||||||
|
"ips": [
|
||||||
|
{
|
||||||
|
"version": "4",
|
||||||
|
"address": "10.0.0.2/24",
|
||||||
|
"gateway": "10.0.0.1",
|
||||||
|
"interface": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
args := &skel.CmdArgs{
|
||||||
|
ContainerID: "dummy",
|
||||||
|
Netns: originalNS.Path(),
|
||||||
|
IfName: IFNAME,
|
||||||
|
StdinData: conf,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := originalNS.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||||
|
return cmdAdd(args)
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
result, err := current.GetResult(r)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(len(result.Interfaces)).To(Equal(1))
|
||||||
|
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||||
|
Expect(len(result.IPs)).To(Equal(1))
|
||||||
|
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||||
|
|
||||||
|
link, err := netlink.LinkByName(IFNAME)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(link.Attrs().Promisc).To(Equal(1))
|
||||||
|
|
||||||
|
err = testutils.CmdDel(originalNS.Path(),
|
||||||
|
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("configures and deconfigures mtu with ADD/DEL", func() {
|
||||||
|
conf := []byte(`{
|
||||||
|
"name": "test",
|
||||||
|
"type": "iplink",
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"mtu": 1454,
|
||||||
|
"prevResult": {
|
||||||
|
"interfaces": [
|
||||||
|
{"name": "dummy0", "sandbox":"netns"}
|
||||||
|
],
|
||||||
|
"ips": [
|
||||||
|
{
|
||||||
|
"version": "4",
|
||||||
|
"address": "10.0.0.2/24",
|
||||||
|
"gateway": "10.0.0.1",
|
||||||
|
"interface": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
args := &skel.CmdArgs{
|
||||||
|
ContainerID: "dummy",
|
||||||
|
Netns: originalNS.Path(),
|
||||||
|
IfName: IFNAME,
|
||||||
|
StdinData: conf,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := originalNS.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||||
|
return cmdAdd(args)
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
result, err := current.GetResult(r)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(len(result.Interfaces)).To(Equal(1))
|
||||||
|
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||||
|
Expect(len(result.IPs)).To(Equal(1))
|
||||||
|
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||||
|
|
||||||
|
link, err := netlink.LinkByName(IFNAME)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(link.Attrs().MTU).To(Equal(1454))
|
||||||
|
|
||||||
|
err = testutils.CmdDel(originalNS.Path(),
|
||||||
|
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("configures and deconfigures mac address (from conf file) with ADD/DEL", func() {
|
||||||
|
conf := []byte(`{
|
||||||
|
"name": "test",
|
||||||
|
"type": "iplink",
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"mac": "c2:11:22:33:44:55",
|
||||||
|
"prevResult": {
|
||||||
|
"interfaces": [
|
||||||
|
{"name": "dummy0", "sandbox":"netns"}
|
||||||
|
],
|
||||||
|
"ips": [
|
||||||
|
{
|
||||||
|
"version": "4",
|
||||||
|
"address": "10.0.0.2/24",
|
||||||
|
"gateway": "10.0.0.1",
|
||||||
|
"interface": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
args := &skel.CmdArgs{
|
||||||
|
ContainerID: "dummy",
|
||||||
|
Netns: originalNS.Path(),
|
||||||
|
IfName: IFNAME,
|
||||||
|
StdinData: conf,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := originalNS.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||||
|
return cmdAdd(args)
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
result, err := current.GetResult(r)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(len(result.Interfaces)).To(Equal(1))
|
||||||
|
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||||
|
Expect(len(result.IPs)).To(Equal(1))
|
||||||
|
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||||
|
|
||||||
|
link, err := netlink.LinkByName(IFNAME)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
hw, err := net.ParseMAC("c2:11:22:33:44:55")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(link.Attrs().HardwareAddr).To(Equal(hw))
|
||||||
|
|
||||||
|
err = testutils.CmdDel(originalNS.Path(),
|
||||||
|
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("configures and deconfigures mac address (from CNI_ARGS) with ADD/DEL", func() {
|
||||||
|
conf := []byte(`{
|
||||||
|
"name": "test",
|
||||||
|
"type": "iplink",
|
||||||
|
"cniVersion": "0.3.1",
|
||||||
|
"prevResult": {
|
||||||
|
"interfaces": [
|
||||||
|
{"name": "dummy0", "sandbox":"netns"}
|
||||||
|
],
|
||||||
|
"ips": [
|
||||||
|
{
|
||||||
|
"version": "4",
|
||||||
|
"address": "10.0.0.2/24",
|
||||||
|
"gateway": "10.0.0.1",
|
||||||
|
"interface": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}`)
|
||||||
|
|
||||||
|
args := &skel.CmdArgs{
|
||||||
|
ContainerID: "dummy",
|
||||||
|
Netns: originalNS.Path(),
|
||||||
|
IfName: IFNAME,
|
||||||
|
StdinData: conf,
|
||||||
|
Args: "IgnoreUnknown=true;MAC=c2:11:22:33:44:66",
|
||||||
|
}
|
||||||
|
|
||||||
|
err := originalNS.Do(func(ns.NetNS) error {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
|
||||||
|
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||||
|
return cmdAdd(args)
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
result, err := current.GetResult(r)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
Expect(len(result.Interfaces)).To(Equal(1))
|
||||||
|
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||||
|
Expect(len(result.IPs)).To(Equal(1))
|
||||||
|
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||||
|
|
||||||
|
link, err := netlink.LinkByName(IFNAME)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
hw, err := net.ParseMAC("c2:11:22:33:44:66")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(link.Attrs().HardwareAddr).To(Equal(hw))
|
||||||
|
|
||||||
|
err = testutils.CmdDel(originalNS.Path(),
|
||||||
|
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -141,5 +141,11 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.PluginSupports("", "0.1.0", "0.2.0", version.Current()))
|
// TODO: implement plugin version
|
||||||
|
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdGet(args *skel.CmdArgs) error {
|
||||||
|
// TODO: implement
|
||||||
|
return fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ rm -Rf ${SRC_DIR}/${RELEASE_DIR}
|
|||||||
mkdir -p ${SRC_DIR}/${RELEASE_DIR}
|
mkdir -p ${SRC_DIR}/${RELEASE_DIR}
|
||||||
mkdir -p ${OUTPUT_DIR}
|
mkdir -p ${OUTPUT_DIR}
|
||||||
|
|
||||||
docker run -ti -v ${SRC_DIR}:/go/src/github.com/containernetworking/plugins --rm golang:1.10-alpine \
|
docker run -v ${SRC_DIR}:/go/src/github.com/containernetworking/plugins --rm golang:1.10-alpine \
|
||||||
/bin/sh -xe -c "\
|
/bin/sh -xe -c "\
|
||||||
apk --no-cache add bash tar;
|
apk --no-cache add bash tar;
|
||||||
cd /go/src/github.com/containernetworking/plugins; umask 0022;
|
cd /go/src/github.com/containernetworking/plugins; umask 0022;
|
||||||
|
254
vendor/github.com/containernetworking/cni/libcni/api.go
generated
vendored
254
vendor/github.com/containernetworking/cni/libcni/api.go
generated
vendored
@ -15,7 +15,11 @@
|
|||||||
package libcni
|
package libcni
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/invoke"
|
"github.com/containernetworking/cni/pkg/invoke"
|
||||||
@ -23,6 +27,14 @@ import (
|
|||||||
"github.com/containernetworking/cni/pkg/version"
|
"github.com/containernetworking/cni/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
CacheDir = "/var/lib/cni"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A RuntimeConf holds the arguments to one invocation of a CNI plugin
|
||||||
|
// excepting the network configuration, with the nested exception that
|
||||||
|
// the `runtimeConfig` from the network configuration is included
|
||||||
|
// here.
|
||||||
type RuntimeConf struct {
|
type RuntimeConf struct {
|
||||||
ContainerID string
|
ContainerID string
|
||||||
NetNS string
|
NetNS string
|
||||||
@ -34,6 +46,9 @@ type RuntimeConf struct {
|
|||||||
// in this map which match the capabilities of the plugin are passed
|
// in this map which match the capabilities of the plugin are passed
|
||||||
// to the plugin
|
// to the plugin
|
||||||
CapabilityArgs map[string]interface{}
|
CapabilityArgs map[string]interface{}
|
||||||
|
|
||||||
|
// A cache directory in which to library data. Defaults to CacheDir
|
||||||
|
CacheDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetworkConfig struct {
|
type NetworkConfig struct {
|
||||||
@ -50,25 +65,38 @@ type NetworkConfigList struct {
|
|||||||
|
|
||||||
type CNI interface {
|
type CNI interface {
|
||||||
AddNetworkList(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
|
AddNetworkList(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
|
||||||
|
GetNetworkList(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
|
||||||
DelNetworkList(net *NetworkConfigList, rt *RuntimeConf) error
|
DelNetworkList(net *NetworkConfigList, rt *RuntimeConf) error
|
||||||
|
|
||||||
AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
|
AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
|
||||||
|
GetNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
|
||||||
DelNetwork(net *NetworkConfig, rt *RuntimeConf) error
|
DelNetwork(net *NetworkConfig, rt *RuntimeConf) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type CNIConfig struct {
|
type CNIConfig struct {
|
||||||
Path []string
|
Path []string
|
||||||
|
exec invoke.Exec
|
||||||
}
|
}
|
||||||
|
|
||||||
// CNIConfig implements the CNI interface
|
// CNIConfig implements the CNI interface
|
||||||
var _ CNI = &CNIConfig{}
|
var _ CNI = &CNIConfig{}
|
||||||
|
|
||||||
func buildOneConfig(list *NetworkConfigList, orig *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (*NetworkConfig, error) {
|
// NewCNIConfig returns a new CNIConfig object that will search for plugins
|
||||||
|
// in the given paths and use the given exec interface to run those plugins,
|
||||||
|
// or if the exec interface is not given, will use a default exec handler.
|
||||||
|
func NewCNIConfig(path []string, exec invoke.Exec) *CNIConfig {
|
||||||
|
return &CNIConfig{
|
||||||
|
Path: path,
|
||||||
|
exec: exec,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildOneConfig(name, cniVersion string, orig *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (*NetworkConfig, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
inject := map[string]interface{}{
|
inject := map[string]interface{}{
|
||||||
"name": list.Name,
|
"name": name,
|
||||||
"cniVersion": list.CNIVersion,
|
"cniVersion": cniVersion,
|
||||||
}
|
}
|
||||||
// Add previous plugin result
|
// Add previous plugin result
|
||||||
if prevResult != nil {
|
if prevResult != nil {
|
||||||
@ -119,21 +147,37 @@ func injectRuntimeConfig(orig *NetworkConfig, rt *RuntimeConf) (*NetworkConfig,
|
|||||||
return orig, nil
|
return orig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddNetworkList executes a sequence of plugins with the ADD command
|
// ensure we have a usable exec if the CNIConfig was not given one
|
||||||
func (c *CNIConfig) AddNetworkList(list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) {
|
func (c *CNIConfig) ensureExec() invoke.Exec {
|
||||||
var prevResult types.Result
|
if c.exec == nil {
|
||||||
|
c.exec = &invoke.DefaultExec{
|
||||||
|
RawExec: &invoke.RawExec{Stderr: os.Stderr},
|
||||||
|
PluginDecoder: version.PluginDecoder{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c.exec
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CNIConfig) addOrGetNetwork(command, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (types.Result, error) {
|
||||||
|
c.ensureExec()
|
||||||
|
pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return invoke.ExecPluginWithResult(pluginPath, newConf.Bytes, c.args(command, rt), c.exec)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that only GET requests should pass an initial prevResult
|
||||||
|
func (c *CNIConfig) addOrGetNetworkList(command string, prevResult types.Result, list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) {
|
||||||
|
var err error
|
||||||
for _, net := range list.Plugins {
|
for _, net := range list.Plugins {
|
||||||
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
prevResult, err = c.addOrGetNetwork(command, list.Name, list.CNIVersion, net, prevResult, rt)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
newConf, err := buildOneConfig(list, net, prevResult, rt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
prevResult, err = invoke.ExecPluginWithResult(pluginPath, newConf.Bytes, c.args("ADD", rt))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -142,68 +186,194 @@ func (c *CNIConfig) AddNetworkList(list *NetworkConfigList, rt *RuntimeConf) (ty
|
|||||||
return prevResult, nil
|
return prevResult, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getResultCacheFilePath(netName string, rt *RuntimeConf) string {
|
||||||
|
cacheDir := rt.CacheDir
|
||||||
|
if cacheDir == "" {
|
||||||
|
cacheDir = CacheDir
|
||||||
|
}
|
||||||
|
return filepath.Join(cacheDir, "results", fmt.Sprintf("%s-%s", netName, rt.ContainerID))
|
||||||
|
}
|
||||||
|
|
||||||
|
func setCachedResult(result types.Result, netName string, rt *RuntimeConf) error {
|
||||||
|
data, err := json.Marshal(result)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fname := getResultCacheFilePath(netName, rt)
|
||||||
|
if err := os.MkdirAll(filepath.Dir(fname), 0700); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ioutil.WriteFile(fname, data, 0600)
|
||||||
|
}
|
||||||
|
|
||||||
|
func delCachedResult(netName string, rt *RuntimeConf) error {
|
||||||
|
fname := getResultCacheFilePath(netName, rt)
|
||||||
|
return os.Remove(fname)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, error) {
|
||||||
|
fname := getResultCacheFilePath(netName, rt)
|
||||||
|
data, err := ioutil.ReadFile(fname)
|
||||||
|
if err != nil {
|
||||||
|
// Ignore read errors; the cached result may not exist on-disk
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the version of the cached result
|
||||||
|
decoder := version.ConfigDecoder{}
|
||||||
|
resultCniVersion, err := decoder.Decode(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we can understand the result
|
||||||
|
result, err := version.NewResult(resultCniVersion, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to the config version to ensure plugins get prevResult
|
||||||
|
// in the same version as the config. The cached result version
|
||||||
|
// should match the config version unless the config was changed
|
||||||
|
// while the container was running.
|
||||||
|
result, err = result.GetAsVersion(cniVersion)
|
||||||
|
if err != nil && resultCniVersion != cniVersion {
|
||||||
|
return nil, fmt.Errorf("failed to convert cached result version %q to config version %q: %v", resultCniVersion, cniVersion, err)
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNetworkList executes a sequence of plugins with the ADD command
|
||||||
|
func (c *CNIConfig) AddNetworkList(list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) {
|
||||||
|
result, err := c.addOrGetNetworkList("ADD", nil, list, rt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = setCachedResult(result, list.Name, rt); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to set network '%s' cached result: %v", list.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetworkList executes a sequence of plugins with the GET command
|
||||||
|
func (c *CNIConfig) GetNetworkList(list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) {
|
||||||
|
// GET was added in CNI spec version 0.4.0 and higher
|
||||||
|
if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if !gtet {
|
||||||
|
return nil, fmt.Errorf("configuration version %q does not support the GET command", list.CNIVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
cachedResult, err := getCachedResult(list.Name, list.CNIVersion, rt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get network '%s' cached result: %v", list.Name, err)
|
||||||
|
}
|
||||||
|
return c.addOrGetNetworkList("GET", cachedResult, list, rt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CNIConfig) delNetwork(name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) error {
|
||||||
|
c.ensureExec()
|
||||||
|
pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return invoke.ExecPluginWithoutResult(pluginPath, newConf.Bytes, c.args("DEL", rt), c.exec)
|
||||||
|
}
|
||||||
|
|
||||||
// DelNetworkList executes a sequence of plugins with the DEL command
|
// DelNetworkList executes a sequence of plugins with the DEL command
|
||||||
func (c *CNIConfig) DelNetworkList(list *NetworkConfigList, rt *RuntimeConf) error {
|
func (c *CNIConfig) DelNetworkList(list *NetworkConfigList, rt *RuntimeConf) error {
|
||||||
|
var cachedResult types.Result
|
||||||
|
|
||||||
|
// Cached result on DEL was added in CNI spec version 0.4.0 and higher
|
||||||
|
if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if gtet {
|
||||||
|
cachedResult, err = getCachedResult(list.Name, list.CNIVersion, rt)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get network '%s' cached result: %v", list.Name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for i := len(list.Plugins) - 1; i >= 0; i-- {
|
for i := len(list.Plugins) - 1; i >= 0; i-- {
|
||||||
net := list.Plugins[i]
|
net := list.Plugins[i]
|
||||||
|
if err := c.delNetwork(list.Name, list.CNIVersion, net, cachedResult, rt); err != nil {
|
||||||
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
newConf, err := buildOneConfig(list, net, nil, rt)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := invoke.ExecPluginWithoutResult(pluginPath, newConf.Bytes, c.args("DEL", rt)); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ = delCachedResult(list.Name, rt)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddNetwork executes the plugin with the ADD command
|
// AddNetwork executes the plugin with the ADD command
|
||||||
func (c *CNIConfig) AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) {
|
func (c *CNIConfig) AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) {
|
||||||
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
result, err := c.addOrGetNetwork("ADD", net.Network.Name, net.Network.CNIVersion, net, nil, rt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
net, err = injectRuntimeConfig(net, rt)
|
if err = setCachedResult(result, net.Network.Name, rt); err != nil {
|
||||||
if err != nil {
|
return nil, fmt.Errorf("failed to set network '%s' cached result: %v", net.Network.Name, err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return invoke.ExecPluginWithResult(pluginPath, net.Bytes, c.args("ADD", rt))
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetwork executes the plugin with the GET command
|
||||||
|
func (c *CNIConfig) GetNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) {
|
||||||
|
// GET was added in CNI spec version 0.4.0 and higher
|
||||||
|
if gtet, err := version.GreaterThanOrEqualTo(net.Network.CNIVersion, "0.4.0"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if !gtet {
|
||||||
|
return nil, fmt.Errorf("configuration version %q does not support the GET command", net.Network.CNIVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
cachedResult, err := getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get network '%s' cached result: %v", net.Network.Name, err)
|
||||||
|
}
|
||||||
|
return c.addOrGetNetwork("GET", net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DelNetwork executes the plugin with the DEL command
|
// DelNetwork executes the plugin with the DEL command
|
||||||
func (c *CNIConfig) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error {
|
func (c *CNIConfig) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error {
|
||||||
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
var cachedResult types.Result
|
||||||
if err != nil {
|
|
||||||
|
// Cached result on DEL was added in CNI spec version 0.4.0 and higher
|
||||||
|
if gtet, err := version.GreaterThanOrEqualTo(net.Network.CNIVersion, "0.4.0"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
} else if gtet {
|
||||||
|
cachedResult, err = getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get network '%s' cached result: %v", net.Network.Name, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
net, err = injectRuntimeConfig(net, rt)
|
if err := c.delNetwork(net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
_ = delCachedResult(net.Network.Name, rt)
|
||||||
return invoke.ExecPluginWithoutResult(pluginPath, net.Bytes, c.args("DEL", rt))
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetVersionInfo reports which versions of the CNI spec are supported by
|
// GetVersionInfo reports which versions of the CNI spec are supported by
|
||||||
// the given plugin.
|
// the given plugin.
|
||||||
func (c *CNIConfig) GetVersionInfo(pluginType string) (version.PluginInfo, error) {
|
func (c *CNIConfig) GetVersionInfo(pluginType string) (version.PluginInfo, error) {
|
||||||
pluginPath, err := invoke.FindInPath(pluginType, c.Path)
|
c.ensureExec()
|
||||||
|
pluginPath, err := c.exec.FindInPath(pluginType, c.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return invoke.GetVersionInfo(pluginPath)
|
return invoke.GetVersionInfo(pluginPath, c.exec)
|
||||||
}
|
}
|
||||||
|
|
||||||
// =====
|
// =====
|
||||||
|
3
vendor/github.com/containernetworking/cni/libcni/conf.go
generated
vendored
3
vendor/github.com/containernetworking/cni/libcni/conf.go
generated
vendored
@ -45,6 +45,9 @@ func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
|
|||||||
if err := json.Unmarshal(bytes, &conf.Network); err != nil {
|
if err := json.Unmarshal(bytes, &conf.Network); err != nil {
|
||||||
return nil, fmt.Errorf("error parsing configuration: %s", err)
|
return nil, fmt.Errorf("error parsing configuration: %s", err)
|
||||||
}
|
}
|
||||||
|
if conf.Network.Type == "" {
|
||||||
|
return nil, fmt.Errorf("error parsing configuration: missing 'type'")
|
||||||
|
}
|
||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go
generated
vendored
42
vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go
generated
vendored
@ -22,32 +22,54 @@ import (
|
|||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DelegateAdd(delegatePlugin string, netconf []byte) (types.Result, error) {
|
func delegateAddOrGet(command, delegatePlugin string, netconf []byte, exec Exec) (types.Result, error) {
|
||||||
if os.Getenv("CNI_COMMAND") != "ADD" {
|
if exec == nil {
|
||||||
return nil, fmt.Errorf("CNI_COMMAND is not ADD")
|
exec = defaultExec
|
||||||
}
|
}
|
||||||
|
|
||||||
paths := filepath.SplitList(os.Getenv("CNI_PATH"))
|
paths := filepath.SplitList(os.Getenv("CNI_PATH"))
|
||||||
|
pluginPath, err := exec.FindInPath(delegatePlugin, paths)
|
||||||
pluginPath, err := FindInPath(delegatePlugin, paths)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExecPluginWithResult(pluginPath, netconf, ArgsFromEnv())
|
return ExecPluginWithResult(pluginPath, netconf, ArgsFromEnv(), exec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DelegateDel(delegatePlugin string, netconf []byte) error {
|
// DelegateAdd calls the given delegate plugin with the CNI ADD action and
|
||||||
|
// JSON configuration
|
||||||
|
func DelegateAdd(delegatePlugin string, netconf []byte, exec Exec) (types.Result, error) {
|
||||||
|
if os.Getenv("CNI_COMMAND") != "ADD" {
|
||||||
|
return nil, fmt.Errorf("CNI_COMMAND is not ADD")
|
||||||
|
}
|
||||||
|
return delegateAddOrGet("ADD", delegatePlugin, netconf, exec)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DelegateGet calls the given delegate plugin with the CNI GET action and
|
||||||
|
// JSON configuration
|
||||||
|
func DelegateGet(delegatePlugin string, netconf []byte, exec Exec) (types.Result, error) {
|
||||||
|
if os.Getenv("CNI_COMMAND") != "GET" {
|
||||||
|
return nil, fmt.Errorf("CNI_COMMAND is not GET")
|
||||||
|
}
|
||||||
|
return delegateAddOrGet("GET", delegatePlugin, netconf, exec)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DelegateDel calls the given delegate plugin with the CNI DEL action and
|
||||||
|
// JSON configuration
|
||||||
|
func DelegateDel(delegatePlugin string, netconf []byte, exec Exec) error {
|
||||||
|
if exec == nil {
|
||||||
|
exec = defaultExec
|
||||||
|
}
|
||||||
|
|
||||||
if os.Getenv("CNI_COMMAND") != "DEL" {
|
if os.Getenv("CNI_COMMAND") != "DEL" {
|
||||||
return fmt.Errorf("CNI_COMMAND is not DEL")
|
return fmt.Errorf("CNI_COMMAND is not DEL")
|
||||||
}
|
}
|
||||||
|
|
||||||
paths := filepath.SplitList(os.Getenv("CNI_PATH"))
|
paths := filepath.SplitList(os.Getenv("CNI_PATH"))
|
||||||
|
pluginPath, err := exec.FindInPath(delegatePlugin, paths)
|
||||||
pluginPath, err := FindInPath(delegatePlugin, paths)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExecPluginWithoutResult(pluginPath, netconf, ArgsFromEnv())
|
return ExecPluginWithoutResult(pluginPath, netconf, ArgsFromEnv(), exec)
|
||||||
}
|
}
|
||||||
|
104
vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
generated
vendored
104
vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
generated
vendored
@ -22,34 +22,62 @@ import (
|
|||||||
"github.com/containernetworking/cni/pkg/version"
|
"github.com/containernetworking/cni/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExecPluginWithResult(pluginPath string, netconf []byte, args CNIArgs) (types.Result, error) {
|
// Exec is an interface encapsulates all operations that deal with finding
|
||||||
return defaultPluginExec.WithResult(pluginPath, netconf, args)
|
// and executing a CNI plugin. Tests may provide a fake implementation
|
||||||
|
// to avoid writing fake plugins to temporary directories during the test.
|
||||||
|
type Exec interface {
|
||||||
|
ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error)
|
||||||
|
FindInPath(plugin string, paths []string) (string, error)
|
||||||
|
Decode(jsonBytes []byte) (version.PluginInfo, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExecPluginWithoutResult(pluginPath string, netconf []byte, args CNIArgs) error {
|
// For example, a testcase could pass an instance of the following fakeExec
|
||||||
return defaultPluginExec.WithoutResult(pluginPath, netconf, args)
|
// object to ExecPluginWithResult() to verify the incoming stdin and environment
|
||||||
}
|
// and provide a tailored response:
|
||||||
|
//
|
||||||
|
//import (
|
||||||
|
// "encoding/json"
|
||||||
|
// "path"
|
||||||
|
// "strings"
|
||||||
|
//)
|
||||||
|
//
|
||||||
|
//type fakeExec struct {
|
||||||
|
// version.PluginDecoder
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (f *fakeExec) ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error) {
|
||||||
|
// net := &types.NetConf{}
|
||||||
|
// err := json.Unmarshal(stdinData, net)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, fmt.Errorf("failed to unmarshal configuration: %v", err)
|
||||||
|
// }
|
||||||
|
// pluginName := path.Base(pluginPath)
|
||||||
|
// if pluginName != net.Type {
|
||||||
|
// return nil, fmt.Errorf("plugin name %q did not match config type %q", pluginName, net.Type)
|
||||||
|
// }
|
||||||
|
// for _, e := range environ {
|
||||||
|
// // Check environment for forced failure request
|
||||||
|
// parts := strings.Split(e, "=")
|
||||||
|
// if len(parts) > 0 && parts[0] == "FAIL" {
|
||||||
|
// return nil, fmt.Errorf("failed to execute plugin %s", pluginName)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return []byte("{\"CNIVersion\":\"0.4.0\"}"), nil
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//func (f *fakeExec) FindInPath(plugin string, paths []string) (string, error) {
|
||||||
|
// if len(paths) > 0 {
|
||||||
|
// return path.Join(paths[0], plugin), nil
|
||||||
|
// }
|
||||||
|
// return "", fmt.Errorf("failed to find plugin %s in paths %v", plugin, paths)
|
||||||
|
//}
|
||||||
|
|
||||||
func GetVersionInfo(pluginPath string) (version.PluginInfo, error) {
|
func ExecPluginWithResult(pluginPath string, netconf []byte, args CNIArgs, exec Exec) (types.Result, error) {
|
||||||
return defaultPluginExec.GetVersionInfo(pluginPath)
|
if exec == nil {
|
||||||
}
|
exec = defaultExec
|
||||||
|
|
||||||
var defaultPluginExec = &PluginExec{
|
|
||||||
RawExec: &RawExec{Stderr: os.Stderr},
|
|
||||||
VersionDecoder: &version.PluginDecoder{},
|
|
||||||
}
|
|
||||||
|
|
||||||
type PluginExec struct {
|
|
||||||
RawExec interface {
|
|
||||||
ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error)
|
|
||||||
}
|
}
|
||||||
VersionDecoder interface {
|
|
||||||
Decode(jsonBytes []byte) (version.PluginInfo, error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *PluginExec) WithResult(pluginPath string, netconf []byte, args CNIArgs) (types.Result, error) {
|
stdoutBytes, err := exec.ExecPlugin(pluginPath, netconf, args.AsEnv())
|
||||||
stdoutBytes, err := e.RawExec.ExecPlugin(pluginPath, netconf, args.AsEnv())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -64,8 +92,11 @@ func (e *PluginExec) WithResult(pluginPath string, netconf []byte, args CNIArgs)
|
|||||||
return version.NewResult(confVersion, stdoutBytes)
|
return version.NewResult(confVersion, stdoutBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *PluginExec) WithoutResult(pluginPath string, netconf []byte, args CNIArgs) error {
|
func ExecPluginWithoutResult(pluginPath string, netconf []byte, args CNIArgs, exec Exec) error {
|
||||||
_, err := e.RawExec.ExecPlugin(pluginPath, netconf, args.AsEnv())
|
if exec == nil {
|
||||||
|
exec = defaultExec
|
||||||
|
}
|
||||||
|
_, err := exec.ExecPlugin(pluginPath, netconf, args.AsEnv())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +104,10 @@ func (e *PluginExec) WithoutResult(pluginPath string, netconf []byte, args CNIAr
|
|||||||
// For recent-enough plugins, it uses the information returned by the VERSION
|
// For recent-enough plugins, it uses the information returned by the VERSION
|
||||||
// command. For older plugins which do not recognize that command, it reports
|
// command. For older plugins which do not recognize that command, it reports
|
||||||
// version 0.1.0
|
// version 0.1.0
|
||||||
func (e *PluginExec) GetVersionInfo(pluginPath string) (version.PluginInfo, error) {
|
func GetVersionInfo(pluginPath string, exec Exec) (version.PluginInfo, error) {
|
||||||
|
if exec == nil {
|
||||||
|
exec = defaultExec
|
||||||
|
}
|
||||||
args := &Args{
|
args := &Args{
|
||||||
Command: "VERSION",
|
Command: "VERSION",
|
||||||
|
|
||||||
@ -83,7 +117,7 @@ func (e *PluginExec) GetVersionInfo(pluginPath string) (version.PluginInfo, erro
|
|||||||
Path: "dummy",
|
Path: "dummy",
|
||||||
}
|
}
|
||||||
stdin := []byte(fmt.Sprintf(`{"cniVersion":%q}`, version.Current()))
|
stdin := []byte(fmt.Sprintf(`{"cniVersion":%q}`, version.Current()))
|
||||||
stdoutBytes, err := e.RawExec.ExecPlugin(pluginPath, stdin, args.AsEnv())
|
stdoutBytes, err := exec.ExecPlugin(pluginPath, stdin, args.AsEnv())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "unknown CNI_COMMAND: VERSION" {
|
if err.Error() == "unknown CNI_COMMAND: VERSION" {
|
||||||
return version.PluginSupports("0.1.0"), nil
|
return version.PluginSupports("0.1.0"), nil
|
||||||
@ -91,5 +125,19 @@ func (e *PluginExec) GetVersionInfo(pluginPath string) (version.PluginInfo, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.VersionDecoder.Decode(stdoutBytes)
|
return exec.Decode(stdoutBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultExec is an object that implements the Exec interface which looks
|
||||||
|
// for and executes plugins from disk.
|
||||||
|
type DefaultExec struct {
|
||||||
|
*RawExec
|
||||||
|
version.PluginDecoder
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultExec implements the Exec interface
|
||||||
|
var _ Exec = &DefaultExec{}
|
||||||
|
|
||||||
|
var defaultExec = &DefaultExec{
|
||||||
|
RawExec: &RawExec{Stderr: os.Stderr},
|
||||||
}
|
}
|
||||||
|
4
vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
generated
vendored
4
vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
generated
vendored
@ -57,3 +57,7 @@ func pluginErr(err error, output []byte) error {
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *RawExec) FindInPath(plugin string, paths []string) (string, error) {
|
||||||
|
return FindInPath(plugin, paths)
|
||||||
|
}
|
||||||
|
86
vendor/github.com/containernetworking/cni/pkg/skel/skel.go
generated
vendored
86
vendor/github.com/containernetworking/cni/pkg/skel/skel.go
generated
vendored
@ -17,6 +17,8 @@
|
|||||||
package skel
|
package skel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -63,6 +65,7 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) {
|
|||||||
&cmd,
|
&cmd,
|
||||||
reqForCmdEntry{
|
reqForCmdEntry{
|
||||||
"ADD": true,
|
"ADD": true,
|
||||||
|
"GET": true,
|
||||||
"DEL": true,
|
"DEL": true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -70,8 +73,9 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) {
|
|||||||
"CNI_CONTAINERID",
|
"CNI_CONTAINERID",
|
||||||
&contID,
|
&contID,
|
||||||
reqForCmdEntry{
|
reqForCmdEntry{
|
||||||
"ADD": false,
|
"ADD": true,
|
||||||
"DEL": false,
|
"GET": true,
|
||||||
|
"DEL": true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -79,6 +83,7 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) {
|
|||||||
&netns,
|
&netns,
|
||||||
reqForCmdEntry{
|
reqForCmdEntry{
|
||||||
"ADD": true,
|
"ADD": true,
|
||||||
|
"GET": true,
|
||||||
"DEL": false,
|
"DEL": false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -87,6 +92,7 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) {
|
|||||||
&ifName,
|
&ifName,
|
||||||
reqForCmdEntry{
|
reqForCmdEntry{
|
||||||
"ADD": true,
|
"ADD": true,
|
||||||
|
"GET": true,
|
||||||
"DEL": true,
|
"DEL": true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -95,6 +101,7 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) {
|
|||||||
&args,
|
&args,
|
||||||
reqForCmdEntry{
|
reqForCmdEntry{
|
||||||
"ADD": false,
|
"ADD": false,
|
||||||
|
"GET": false,
|
||||||
"DEL": false,
|
"DEL": false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -103,6 +110,7 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) {
|
|||||||
&path,
|
&path,
|
||||||
reqForCmdEntry{
|
reqForCmdEntry{
|
||||||
"ADD": true,
|
"ADD": true,
|
||||||
|
"GET": true,
|
||||||
"DEL": true,
|
"DEL": true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -123,6 +131,10 @@ func (t *dispatcher) getCmdArgsFromEnv() (string, *CmdArgs, error) {
|
|||||||
return "", nil, fmt.Errorf("required env variables missing")
|
return "", nil, fmt.Errorf("required env variables missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cmd == "VERSION" {
|
||||||
|
t.Stdin = bytes.NewReader(nil)
|
||||||
|
}
|
||||||
|
|
||||||
stdinData, err := ioutil.ReadAll(t.Stdin)
|
stdinData, err := ioutil.ReadAll(t.Stdin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, fmt.Errorf("error reading from stdin: %v", err)
|
return "", nil, fmt.Errorf("error reading from stdin: %v", err)
|
||||||
@ -159,18 +171,71 @@ func (t *dispatcher) checkVersionAndCall(cmdArgs *CmdArgs, pluginVersionInfo ver
|
|||||||
Details: verErr.Details(),
|
Details: verErr.Details(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return toCall(cmdArgs)
|
return toCall(cmdArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *dispatcher) pluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo) *types.Error {
|
func validateConfig(jsonBytes []byte) error {
|
||||||
|
var conf struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(jsonBytes, &conf); err != nil {
|
||||||
|
return fmt.Errorf("error reading network config: %s", err)
|
||||||
|
}
|
||||||
|
if conf.Name == "" {
|
||||||
|
return fmt.Errorf("missing network name")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *dispatcher) pluginMain(cmdAdd, cmdGet, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo, about string) *types.Error {
|
||||||
cmd, cmdArgs, err := t.getCmdArgsFromEnv()
|
cmd, cmdArgs, err := t.getCmdArgsFromEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Print the about string to stderr when no command is set
|
||||||
|
if t.Getenv("CNI_COMMAND") == "" && about != "" {
|
||||||
|
fmt.Fprintln(t.Stderr, about)
|
||||||
|
}
|
||||||
return createTypedError(err.Error())
|
return createTypedError(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cmd != "VERSION" {
|
||||||
|
err = validateConfig(cmdArgs.StdinData)
|
||||||
|
if err != nil {
|
||||||
|
return createTypedError(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch cmd {
|
switch cmd {
|
||||||
case "ADD":
|
case "ADD":
|
||||||
err = t.checkVersionAndCall(cmdArgs, versionInfo, cmdAdd)
|
err = t.checkVersionAndCall(cmdArgs, versionInfo, cmdAdd)
|
||||||
|
case "GET":
|
||||||
|
configVersion, err := t.ConfVersionDecoder.Decode(cmdArgs.StdinData)
|
||||||
|
if err != nil {
|
||||||
|
return createTypedError(err.Error())
|
||||||
|
}
|
||||||
|
if gtet, err := version.GreaterThanOrEqualTo(configVersion, "0.4.0"); err != nil {
|
||||||
|
return createTypedError(err.Error())
|
||||||
|
} else if !gtet {
|
||||||
|
return &types.Error{
|
||||||
|
Code: types.ErrIncompatibleCNIVersion,
|
||||||
|
Msg: "config version does not allow GET",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, pluginVersion := range versionInfo.SupportedVersions() {
|
||||||
|
gtet, err := version.GreaterThanOrEqualTo(pluginVersion, configVersion)
|
||||||
|
if err != nil {
|
||||||
|
return createTypedError(err.Error())
|
||||||
|
} else if gtet {
|
||||||
|
if err := t.checkVersionAndCall(cmdArgs, versionInfo, cmdGet); err != nil {
|
||||||
|
return createTypedError(err.Error())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &types.Error{
|
||||||
|
Code: types.ErrIncompatibleCNIVersion,
|
||||||
|
Msg: "plugin version does not allow GET",
|
||||||
|
}
|
||||||
case "DEL":
|
case "DEL":
|
||||||
err = t.checkVersionAndCall(cmdArgs, versionInfo, cmdDel)
|
err = t.checkVersionAndCall(cmdArgs, versionInfo, cmdDel)
|
||||||
case "VERSION":
|
case "VERSION":
|
||||||
@ -190,7 +255,7 @@ func (t *dispatcher) pluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error, versionIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PluginMainWithError is the core "main" for a plugin. It accepts
|
// PluginMainWithError is the core "main" for a plugin. It accepts
|
||||||
// callback functions for add and del CNI commands and returns an error.
|
// callback functions for add, get, and del CNI commands and returns an error.
|
||||||
//
|
//
|
||||||
// The caller must also specify what CNI spec versions the plugin supports.
|
// The caller must also specify what CNI spec versions the plugin supports.
|
||||||
//
|
//
|
||||||
@ -201,25 +266,28 @@ func (t *dispatcher) pluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error, versionIn
|
|||||||
//
|
//
|
||||||
// To let this package automatically handle errors and call os.Exit(1) for you,
|
// To let this package automatically handle errors and call os.Exit(1) for you,
|
||||||
// use PluginMain() instead.
|
// use PluginMain() instead.
|
||||||
func PluginMainWithError(cmdAdd, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo) *types.Error {
|
func PluginMainWithError(cmdAdd, cmdGet, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo, about string) *types.Error {
|
||||||
return (&dispatcher{
|
return (&dispatcher{
|
||||||
Getenv: os.Getenv,
|
Getenv: os.Getenv,
|
||||||
Stdin: os.Stdin,
|
Stdin: os.Stdin,
|
||||||
Stdout: os.Stdout,
|
Stdout: os.Stdout,
|
||||||
Stderr: os.Stderr,
|
Stderr: os.Stderr,
|
||||||
}).pluginMain(cmdAdd, cmdDel, versionInfo)
|
}).pluginMain(cmdAdd, cmdGet, cmdDel, versionInfo, about)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PluginMain is the core "main" for a plugin which includes automatic error handling.
|
// PluginMain is the core "main" for a plugin which includes automatic error handling.
|
||||||
//
|
//
|
||||||
// The caller must also specify what CNI spec versions the plugin supports.
|
// The caller must also specify what CNI spec versions the plugin supports.
|
||||||
//
|
//
|
||||||
// When an error occurs in either cmdAdd or cmdDel, PluginMain will print the error
|
// The caller can specify an "about" string, which is printed on stderr
|
||||||
|
// when no CNI_COMMAND is specified. The reccomended output is "CNI plugin <foo> v<version>"
|
||||||
|
//
|
||||||
|
// When an error occurs in either cmdAdd, cmdGet, or cmdDel, PluginMain will print the error
|
||||||
// as JSON to stdout and call os.Exit(1).
|
// as JSON to stdout and call os.Exit(1).
|
||||||
//
|
//
|
||||||
// To have more control over error handling, use PluginMainWithError() instead.
|
// To have more control over error handling, use PluginMainWithError() instead.
|
||||||
func PluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo) {
|
func PluginMain(cmdAdd, cmdGet, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo, about string) {
|
||||||
if e := PluginMainWithError(cmdAdd, cmdDel, versionInfo); e != nil {
|
if e := PluginMainWithError(cmdAdd, cmdGet, cmdDel, versionInfo, about); e != nil {
|
||||||
if err := e.Print(); err != nil {
|
if err := e.Print(); err != nil {
|
||||||
log.Print("Error writing error JSON to stdout: ", err)
|
log.Print("Error writing error JSON to stdout: ", err)
|
||||||
}
|
}
|
||||||
|
6
vendor/github.com/containernetworking/cni/pkg/types/current/types.go
generated
vendored
6
vendor/github.com/containernetworking/cni/pkg/types/current/types.go
generated
vendored
@ -24,9 +24,9 @@ import (
|
|||||||
"github.com/containernetworking/cni/pkg/types/020"
|
"github.com/containernetworking/cni/pkg/types/020"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ImplementedSpecVersion string = "0.3.1"
|
const ImplementedSpecVersion string = "0.4.0"
|
||||||
|
|
||||||
var SupportedVersions = []string{"0.3.0", ImplementedSpecVersion}
|
var SupportedVersions = []string{"0.3.0", "0.3.1", ImplementedSpecVersion}
|
||||||
|
|
||||||
func NewResult(data []byte) (types.Result, error) {
|
func NewResult(data []byte) (types.Result, error) {
|
||||||
result := &Result{}
|
result := &Result{}
|
||||||
@ -196,7 +196,7 @@ func (r *Result) Version() string {
|
|||||||
|
|
||||||
func (r *Result) GetAsVersion(version string) (types.Result, error) {
|
func (r *Result) GetAsVersion(version string) (types.Result, error) {
|
||||||
switch version {
|
switch version {
|
||||||
case "0.3.0", ImplementedSpecVersion:
|
case "0.3.0", "0.3.1", ImplementedSpecVersion:
|
||||||
r.CNIVersion = version
|
r.CNIVersion = version
|
||||||
return r, nil
|
return r, nil
|
||||||
case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]:
|
case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]:
|
||||||
|
12
vendor/github.com/containernetworking/cni/pkg/types/types.go
generated
vendored
12
vendor/github.com/containernetworking/cni/pkg/types/types.go
generated
vendored
@ -63,10 +63,12 @@ type NetConf struct {
|
|||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
Capabilities map[string]bool `json:"capabilities,omitempty"`
|
Capabilities map[string]bool `json:"capabilities,omitempty"`
|
||||||
IPAM struct {
|
IPAM IPAM `json:"ipam,omitempty"`
|
||||||
Type string `json:"type,omitempty"`
|
DNS DNS `json:"dns"`
|
||||||
} `json:"ipam,omitempty"`
|
}
|
||||||
DNS DNS `json:"dns"`
|
|
||||||
|
type IPAM struct {
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetConfList describes an ordered list of networks.
|
// NetConfList describes an ordered list of networks.
|
||||||
@ -167,7 +169,7 @@ func (r *Route) UnmarshalJSON(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) MarshalJSON() ([]byte, error) {
|
func (r Route) MarshalJSON() ([]byte, error) {
|
||||||
rt := route{
|
rt := route{
|
||||||
Dst: IPNet(r.Dst),
|
Dst: IPNet(r.Dst),
|
||||||
GW: r.GW,
|
GW: r.GW,
|
||||||
|
59
vendor/github.com/containernetworking/cni/pkg/version/plugin.go
generated
vendored
59
vendor/github.com/containernetworking/cni/pkg/version/plugin.go
generated
vendored
@ -18,6 +18,8 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PluginInfo reports information about CNI versioning
|
// PluginInfo reports information about CNI versioning
|
||||||
@ -79,3 +81,60 @@ func (*PluginDecoder) Decode(jsonBytes []byte) (PluginInfo, error) {
|
|||||||
}
|
}
|
||||||
return &info, nil
|
return &info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseVersion parses a version string like "3.0.1" or "0.4.5" into major,
|
||||||
|
// minor, and micro numbers or returns an error
|
||||||
|
func ParseVersion(version string) (int, int, int, error) {
|
||||||
|
var major, minor, micro int
|
||||||
|
parts := strings.Split(version, ".")
|
||||||
|
if len(parts) == 0 || len(parts) >= 4 {
|
||||||
|
return -1, -1, -1, fmt.Errorf("invalid version %q: too many or too few parts", version)
|
||||||
|
}
|
||||||
|
|
||||||
|
major, err := strconv.Atoi(parts[0])
|
||||||
|
if err != nil {
|
||||||
|
return -1, -1, -1, fmt.Errorf("failed to convert major version part %q: %v", parts[0], err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(parts) >= 2 {
|
||||||
|
minor, err = strconv.Atoi(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
return -1, -1, -1, fmt.Errorf("failed to convert minor version part %q: %v", parts[1], err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(parts) >= 3 {
|
||||||
|
micro, err = strconv.Atoi(parts[2])
|
||||||
|
if err != nil {
|
||||||
|
return -1, -1, -1, fmt.Errorf("failed to convert micro version part %q: %v", parts[2], err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return major, minor, micro, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GreaterThanOrEqualTo takes two string versions, parses them into major/minor/micro
|
||||||
|
// nubmers, and compares them to determine whether the first version is greater
|
||||||
|
// than or equal to the second
|
||||||
|
func GreaterThanOrEqualTo(version, otherVersion string) (bool, error) {
|
||||||
|
firstMajor, firstMinor, firstMicro, err := ParseVersion(version)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
secondMajor, secondMinor, secondMicro, err := ParseVersion(otherVersion)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if firstMajor > secondMajor {
|
||||||
|
return true, nil
|
||||||
|
} else if firstMajor == secondMajor {
|
||||||
|
if firstMinor > secondMinor {
|
||||||
|
return true, nil
|
||||||
|
} else if firstMinor == secondMinor && firstMicro >= secondMicro {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
4
vendor/github.com/containernetworking/cni/pkg/version/version.go
generated
vendored
4
vendor/github.com/containernetworking/cni/pkg/version/version.go
generated
vendored
@ -24,7 +24,7 @@ import (
|
|||||||
|
|
||||||
// Current reports the version of the CNI spec implemented by this library
|
// Current reports the version of the CNI spec implemented by this library
|
||||||
func Current() string {
|
func Current() string {
|
||||||
return "0.3.1"
|
return "0.4.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Legacy PluginInfo describes a plugin that is backwards compatible with the
|
// Legacy PluginInfo describes a plugin that is backwards compatible with the
|
||||||
@ -35,7 +35,7 @@ func Current() string {
|
|||||||
// Any future CNI spec versions which meet this definition should be added to
|
// Any future CNI spec versions which meet this definition should be added to
|
||||||
// this list.
|
// this list.
|
||||||
var Legacy = PluginSupports("0.1.0", "0.2.0")
|
var Legacy = PluginSupports("0.1.0", "0.2.0")
|
||||||
var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1")
|
var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0")
|
||||||
|
|
||||||
var resultFactories = []struct {
|
var resultFactories = []struct {
|
||||||
supportedVersions []string
|
supportedVersions []string
|
||||||
|
5
vendor/github.com/coreos/go-systemd/NOTICE
generated
vendored
Normal file
5
vendor/github.com/coreos/go-systemd/NOTICE
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
CoreOS Project
|
||||||
|
Copyright 2018 CoreOS, Inc
|
||||||
|
|
||||||
|
This product includes software developed at CoreOS, Inc.
|
||||||
|
(http://www.coreos.com/).
|
19
vendor/github.com/coreos/go-systemd/activation/files.go
generated
vendored
19
vendor/github.com/coreos/go-systemd/activation/files.go
generated
vendored
@ -18,18 +18,26 @@ package activation
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// based on: https://gist.github.com/alberts/4640792
|
|
||||||
const (
|
const (
|
||||||
|
// listenFdsStart corresponds to `SD_LISTEN_FDS_START`.
|
||||||
listenFdsStart = 3
|
listenFdsStart = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Files returns a slice containing a `os.File` object for each
|
||||||
|
// file descriptor passed to this process via systemd fd-passing protocol.
|
||||||
|
//
|
||||||
|
// The order of the file descriptors is preserved in the returned slice.
|
||||||
|
// `unsetEnv` is typically set to `true` in order to avoid clashes in
|
||||||
|
// fd usage and to avoid leaking environment flags to child processes.
|
||||||
func Files(unsetEnv bool) []*os.File {
|
func Files(unsetEnv bool) []*os.File {
|
||||||
if unsetEnv {
|
if unsetEnv {
|
||||||
defer os.Unsetenv("LISTEN_PID")
|
defer os.Unsetenv("LISTEN_PID")
|
||||||
defer os.Unsetenv("LISTEN_FDS")
|
defer os.Unsetenv("LISTEN_FDS")
|
||||||
|
defer os.Unsetenv("LISTEN_FDNAMES")
|
||||||
}
|
}
|
||||||
|
|
||||||
pid, err := strconv.Atoi(os.Getenv("LISTEN_PID"))
|
pid, err := strconv.Atoi(os.Getenv("LISTEN_PID"))
|
||||||
@ -42,10 +50,17 @@ func Files(unsetEnv bool) []*os.File {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
names := strings.Split(os.Getenv("LISTEN_FDNAMES"), ":")
|
||||||
|
|
||||||
files := make([]*os.File, 0, nfds)
|
files := make([]*os.File, 0, nfds)
|
||||||
for fd := listenFdsStart; fd < listenFdsStart+nfds; fd++ {
|
for fd := listenFdsStart; fd < listenFdsStart+nfds; fd++ {
|
||||||
syscall.CloseOnExec(fd)
|
syscall.CloseOnExec(fd)
|
||||||
files = append(files, os.NewFile(uintptr(fd), "LISTEN_FD_"+strconv.Itoa(fd)))
|
name := "LISTEN_FD_" + strconv.Itoa(fd)
|
||||||
|
offset := fd - listenFdsStart
|
||||||
|
if offset < len(names) && len(names[offset]) > 0 {
|
||||||
|
name = names[offset]
|
||||||
|
}
|
||||||
|
files = append(files, os.NewFile(uintptr(fd), name))
|
||||||
}
|
}
|
||||||
|
|
||||||
return files
|
return files
|
||||||
|
70
vendor/github.com/coreos/go-systemd/activation/listeners.go
generated
vendored
70
vendor/github.com/coreos/go-systemd/activation/listeners.go
generated
vendored
@ -15,6 +15,7 @@
|
|||||||
package activation
|
package activation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,14 +25,79 @@ import (
|
|||||||
// The order of the file descriptors is preserved in the returned slice.
|
// The order of the file descriptors is preserved in the returned slice.
|
||||||
// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
|
// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
|
||||||
// corresponding with "udp, tcp, tcp", then the slice would contain {nil, net.Listener, net.Listener}
|
// corresponding with "udp, tcp, tcp", then the slice would contain {nil, net.Listener, net.Listener}
|
||||||
func Listeners(unsetEnv bool) ([]net.Listener, error) {
|
func Listeners() ([]net.Listener, error) {
|
||||||
files := Files(unsetEnv)
|
files := Files(true)
|
||||||
listeners := make([]net.Listener, len(files))
|
listeners := make([]net.Listener, len(files))
|
||||||
|
|
||||||
for i, f := range files {
|
for i, f := range files {
|
||||||
if pc, err := net.FileListener(f); err == nil {
|
if pc, err := net.FileListener(f); err == nil {
|
||||||
listeners[i] = pc
|
listeners[i] = pc
|
||||||
|
f.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return listeners, nil
|
return listeners, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListenersWithNames maps a listener name to a set of net.Listener instances.
|
||||||
|
func ListenersWithNames() (map[string][]net.Listener, error) {
|
||||||
|
files := Files(true)
|
||||||
|
listeners := map[string][]net.Listener{}
|
||||||
|
|
||||||
|
for _, f := range files {
|
||||||
|
if pc, err := net.FileListener(f); err == nil {
|
||||||
|
current, ok := listeners[f.Name()]
|
||||||
|
if !ok {
|
||||||
|
listeners[f.Name()] = []net.Listener{pc}
|
||||||
|
} else {
|
||||||
|
listeners[f.Name()] = append(current, pc)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listeners, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TLSListeners returns a slice containing a net.listener for each matching TCP socket type
|
||||||
|
// passed to this process.
|
||||||
|
// It uses default Listeners func and forces TCP sockets handlers to use TLS based on tlsConfig.
|
||||||
|
func TLSListeners(tlsConfig *tls.Config) ([]net.Listener, error) {
|
||||||
|
listeners, err := Listeners()
|
||||||
|
|
||||||
|
if listeners == nil || err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if tlsConfig != nil && err == nil {
|
||||||
|
for i, l := range listeners {
|
||||||
|
// Activate TLS only for TCP sockets
|
||||||
|
if l.Addr().Network() == "tcp" {
|
||||||
|
listeners[i] = tls.NewListener(l, tlsConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return listeners, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TLSListenersWithNames maps a listener name to a net.Listener with
|
||||||
|
// the associated TLS configuration.
|
||||||
|
func TLSListenersWithNames(tlsConfig *tls.Config) (map[string][]net.Listener, error) {
|
||||||
|
listeners, err := ListenersWithNames()
|
||||||
|
|
||||||
|
if listeners == nil || err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if tlsConfig != nil && err == nil {
|
||||||
|
for _, ll := range listeners {
|
||||||
|
// Activate TLS only for TCP sockets
|
||||||
|
for i, l := range ll {
|
||||||
|
if l.Addr().Network() == "tcp" {
|
||||||
|
ll[i] = tls.NewListener(l, tlsConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return listeners, err
|
||||||
|
}
|
||||||
|
5
vendor/github.com/coreos/go-systemd/activation/packetconns.go
generated
vendored
5
vendor/github.com/coreos/go-systemd/activation/packetconns.go
generated
vendored
@ -24,13 +24,14 @@ import (
|
|||||||
// The order of the file descriptors is preserved in the returned slice.
|
// The order of the file descriptors is preserved in the returned slice.
|
||||||
// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
|
// Nil values are used to fill any gaps. For example if systemd were to return file descriptors
|
||||||
// corresponding with "udp, tcp, udp", then the slice would contain {net.PacketConn, nil, net.PacketConn}
|
// corresponding with "udp, tcp, udp", then the slice would contain {net.PacketConn, nil, net.PacketConn}
|
||||||
func PacketConns(unsetEnv bool) ([]net.PacketConn, error) {
|
func PacketConns() ([]net.PacketConn, error) {
|
||||||
files := Files(unsetEnv)
|
files := Files(true)
|
||||||
conns := make([]net.PacketConn, len(files))
|
conns := make([]net.PacketConn, len(files))
|
||||||
|
|
||||||
for i, f := range files {
|
for i, f := range files {
|
||||||
if pc, err := net.FilePacketConn(f); err == nil {
|
if pc, err := net.FilePacketConn(f); err == nil {
|
||||||
conns[i] = pc
|
conns[i] = pc
|
||||||
|
f.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return conns, nil
|
return conns, nil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user