Compare commits
122
Commits
v2.6.4
...
latest_release
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba64f8e8eb | ||
|
|
263aecf4ef | ||
|
|
f9239c9a44 | ||
|
|
9a2682671c | ||
|
|
ad621c807e | ||
|
|
164175160a | ||
|
|
edd28ab4cb | ||
|
|
4368dd5841 | ||
|
|
1dfe1f3b98 | ||
|
|
b1651c322a | ||
|
|
ba6741166d | ||
|
|
108f0a5c14 | ||
|
|
b04217d8e6 | ||
|
|
3ef97f0c7c | ||
|
|
e91900cc9e | ||
|
|
fe61992c06 | ||
|
|
8eeb3ca4f2 | ||
|
|
b7a9947c2f | ||
|
|
d81e908d1a | ||
|
|
a0ac81b3b4 | ||
|
|
c6d0d140a4 | ||
|
|
9bb14662e5 | ||
|
|
240d1b2f2a | ||
|
|
414cbfb838 | ||
|
|
fb7fc7ddae | ||
|
|
8c52698222 | ||
|
|
cb2e56fc44 | ||
|
|
30ce219794 | ||
|
|
911f506b63 | ||
|
|
4795ba5807 | ||
|
|
23a827088b | ||
|
|
269786abf5 | ||
|
|
9cf4104de7 | ||
|
|
5f27dbf17c | ||
|
|
0ab2d08f0c | ||
|
|
4d7e9931f9 | ||
|
|
fca23f805a | ||
|
|
905ec927a3 | ||
|
|
2864d1ebc5 | ||
|
|
b3d387fb86 | ||
|
|
d14502e071 | ||
|
|
9439606c57 | ||
|
|
feb05c0904 | ||
|
|
514695e127 | ||
|
|
f9e27f76d6 | ||
|
|
c3504788a0 | ||
|
|
4592758e48 | ||
|
|
2ec3e1ef1a | ||
|
|
0789670344 | ||
|
|
80a80816aa | ||
|
|
c50b3380ea | ||
|
|
aa9caab1b0 | ||
|
|
ce9d05e0bd | ||
|
|
0c4aeb3a0b | ||
|
|
f24cf798bc | ||
|
|
3d66dcd94e | ||
|
|
fab09693b9 | ||
|
|
cdbc25d462 | ||
|
|
6946731fdd | ||
|
|
0078fc535a | ||
|
|
9ffd0e3450 | ||
|
|
5b2311bb45 | ||
|
|
b0274e11be | ||
|
|
34dc4dabce | ||
|
|
28e482af14 | ||
|
|
c197624689 | ||
|
|
00bc020498 | ||
|
|
df52117bfa | ||
|
|
00623be8a7 | ||
|
|
4d3e8d4a82 | ||
|
|
2cc5c635c9 | ||
|
|
865e2b726f | ||
|
|
f6a3af4a10 | ||
|
|
2deb7e2e48 | ||
|
|
ce38141e5b | ||
|
|
6bc656d66c | ||
|
|
ca4f93d0d7 | ||
|
|
a3c76e141b | ||
|
|
f4009c39d8 | ||
|
|
9928ddb401 | ||
|
|
7b927a7bac | ||
|
|
341bac9968 | ||
|
|
1d7ca17c3e | ||
|
|
add109a63d | ||
|
|
0f276a4d63 | ||
|
|
0ac333b91c | ||
|
|
acbd744372 | ||
|
|
c0e5008202 | ||
|
|
899490c3f9 | ||
|
|
709b434f55 | ||
|
|
ca7103d007 | ||
|
|
66eb80d841 | ||
|
|
94e75e45af | ||
|
|
fa5e032e49 | ||
|
|
a90c0075c8 | ||
|
|
1ff09fd4d1 | ||
|
|
e0348233af | ||
|
|
495bea8890 | ||
|
|
88799b36b2 | ||
|
|
3d79b07dba | ||
|
|
27f8f9092f | ||
|
|
7174738d9d | ||
|
|
11d75b27a6 | ||
|
|
9be65b466b | ||
|
|
9d669c3312 | ||
|
|
d45579bf82 | ||
|
|
ac54cfb753 | ||
|
|
0d4099bba5 | ||
|
|
21c7bb3ff6 | ||
|
|
ff9bcdf561 | ||
|
|
0c4659c3b5 | ||
|
|
06b0a82465 | ||
|
|
6e1770d24d | ||
|
|
733df28a65 | ||
|
|
6a1fbec5e2 | ||
|
|
35d8465376 | ||
|
|
9f00f78d3b | ||
|
|
6a458d0712 | ||
|
|
7c97bb5d30 | ||
|
|
cee6929cb9 | ||
|
|
9a6d0c9cf5 | ||
|
|
fdf881420c |
No files matched your search
@@ -1,7 +1,7 @@
|
|||||||
version: 2
|
version: 2
|
||||||
defaults: &defaults
|
defaults: &defaults
|
||||||
docker:
|
docker:
|
||||||
- image: weaveworks/weavebuild:go-1-13-1-5110a604
|
- image: weaveworks/weavebuild:master-1dfe1f3b
|
||||||
working_directory: /go/src/github.com/weaveworks/weave
|
working_directory: /go/src/github.com/weaveworks/weave
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
@@ -1,3 +1,69 @@
|
|||||||
|
## Release 2.8.1
|
||||||
|
|
||||||
|
Fixes a problem introduced in 2.8.0 for machines whose ID is in /etc/machine-id #3886
|
||||||
|
Many thanks to contributor @avestuk for this fix.
|
||||||
|
|
||||||
|
Also move Kubernetes API calls out of Weave Net daemon #3885
|
||||||
|
- this reduces the size of the 'weaver' binary and stops it crashing when run on 32-bit ARM.
|
||||||
|
|
||||||
|
## Release 2.8.0
|
||||||
|
|
||||||
|
This release makes some important changes to trim the "attack surface" of the
|
||||||
|
Kubernetes install, and improves a couple of reported issues.
|
||||||
|
|
||||||
|
* Workaround to fix ipset conflict with iptables #3851, #3882
|
||||||
|
* Kubernetes: move kernel and CNI setup to init container #3880
|
||||||
|
* For K8s, stop running in host PID namespace #3876
|
||||||
|
* NetworkPolicy: avoid logging dropped packets that were not actually dropped #3852
|
||||||
|
* Build with Go version 1.15.6 #3883
|
||||||
|
|
||||||
|
Many thanks to contributors @drigz, @KevDBG and @NeonSludge.
|
||||||
|
|
||||||
|
[Full list of changes](https://github.com/weaveworks/weave/milestone/87?closed=1)
|
||||||
|
|
||||||
|
## Release 2.7.0
|
||||||
|
|
||||||
|
This release improves resiliency in a number of areas,
|
||||||
|
and extends the Prometheus metrics exported by Weave Net.
|
||||||
|
|
||||||
|
Change in behaviour: on Kubernetes, the client source IP is preserved
|
||||||
|
when calling from a pod to a service.
|
||||||
|
This feature, introduced in version 2.4.0 and previously turned on by
|
||||||
|
setting `NO_MASQ_LOCAL=1` is now on by default. #3389, #3756
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Reload router iptables rules if they get cleared, e.g. when firewalld restarts. #3802
|
||||||
|
(weave-npc rules are not reloaded)
|
||||||
|
* Add new `type` and `encryption` labels to `weave_connections` metric #3788, #3789
|
||||||
|
* Weave Net now exports Go metrics for heap size, garbage collection, etc. #3838
|
||||||
|
* Register container name and its network aliases with weaveDNS #3084, #3090
|
||||||
|
* Make DNS listen address configurable #1770, #3231
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
* weave-npc could crash if you deleted a Kubernetes Namespace containing pods #3833, #3836
|
||||||
|
* Ensure that weave-npc exits and restarts if it crashes #3764, #3792, #3841
|
||||||
|
* Avoid weave-kube failing on startup due to iptables lock #3828, #3835
|
||||||
|
|
||||||
|
### Build and test
|
||||||
|
|
||||||
|
* Reduce size of containers (weaveworks/weave goes from 99MB to 83MB) #3624, #3726
|
||||||
|
* Weave Net is now built with Go 1.14.4, which should improve performance #3838
|
||||||
|
* CI tests are now run against Docker 19.03.1, Kubernetes 1.14.0 #3687
|
||||||
|
|
||||||
|
Many thanks to contributors @berlic, @gobomb, @hairyhenderson, @naemono, @nesc58
|
||||||
|
|
||||||
|
[Full list of changes](https://github.com/weaveworks/weave/milestone/81?closed=1)
|
||||||
|
|
||||||
|
|
||||||
|
## Release 2.6.5
|
||||||
|
|
||||||
|
Fixes a bug that would leak memory every time a fast-datapath connection
|
||||||
|
was stopped. #3808
|
||||||
|
Also avoid a crash when the machine has ipv6 disabled. #3815
|
||||||
|
|
||||||
|
|
||||||
## Release 2.6.4
|
## Release 2.6.4
|
||||||
|
|
||||||
Improves the iptables rule added in 2.6.3 to block just the Weave Net
|
Improves the iptables rule added in 2.6.3 to block just the Weave Net
|
||||||
|
|||||||
+3
-3
@@ -1,3 +1,3 @@
|
|||||||
DOCKER_VERSION=17.06
|
DOCKER_VERSION=19.03.1
|
||||||
KUBERNETES_VERSION=1.11.0
|
KUBERNETES_VERSION=1.14.0
|
||||||
KUBERNETES_CNI_VERSION=0.6.0
|
KUBERNETES_CNI_VERSION=0.7.5
|
||||||
@@ -29,7 +29,7 @@ If you have any questions about, feedback for or a problem with Weave Net:
|
|||||||
|
|
||||||
- Read [the Weave Net docs](https://www.weave.works/docs/net/latest/overview).
|
- Read [the Weave Net docs](https://www.weave.works/docs/net/latest/overview).
|
||||||
- Invite yourself to the <a href="https://slack.weave.works/" target="_blank">Weave Users Slack</a>.
|
- Invite yourself to the <a href="https://slack.weave.works/" target="_blank">Weave Users Slack</a>.
|
||||||
- Ask a question on the [#net-dev](https://weave-community.slack.com/messages/net-dev/) slack channel.
|
- The channel for contributors and developers of Weave Net is [#net-dev](https://weave-community.slack.com/messages/net-dev/).
|
||||||
- Join the <a href="https://www.meetup.com/pro/Weave/"> Weave User Group </a> and get invited to online talks, hands-on training and meetups in your area.
|
- Join the <a href="https://www.meetup.com/pro/Weave/"> Weave User Group </a> and get invited to online talks, hands-on training and meetups in your area.
|
||||||
- [File an issue](https://github.com/weaveworks/weave/issues/new).
|
- [File an issue](https://github.com/weaveworks/weave/issues/new).
|
||||||
|
|
||||||
|
|||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
At Weaveworks we take security very seriously, and value our close relationship with members of the security community.
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
As an Open Source project, only the latest code has all fixes and security patches.
|
||||||
|
If you require a higher level of commitment, please [contact Weaveworks](https://www.weave.works/contact/) to discuss.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
To submit a security bug report please e-mail us at security@weave.works.
|
||||||
|
|
||||||
|
We also operate a Bug Bounty programme; see https://www.weave.works/bug-bounty/
|
||||||
-30
@@ -89,8 +89,6 @@ build() {
|
|||||||
## Inject the version numbers and build the distributables
|
## Inject the version numbers and build the distributables
|
||||||
## (library versions?)
|
## (library versions?)
|
||||||
sed -i.bak "/SCRIPT_VERSION=/ c\SCRIPT_VERSION=\"$VERSION\"" ./weave
|
sed -i.bak "/SCRIPT_VERSION=/ c\SCRIPT_VERSION=\"$VERSION\"" ./weave
|
||||||
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.6.yaml
|
|
||||||
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.7.yaml
|
|
||||||
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.8.yaml
|
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.8.yaml
|
||||||
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.9.yaml
|
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.9.yaml
|
||||||
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.11.yaml
|
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.11.yaml
|
||||||
@@ -162,20 +160,6 @@ draft() {
|
|||||||
--name "weave" \
|
--name "weave" \
|
||||||
--file "./weave"
|
--file "./weave"
|
||||||
|
|
||||||
github-release upload \
|
|
||||||
--user $GITHUB_USER \
|
|
||||||
--repo weave \
|
|
||||||
--tag $LATEST_TAG \
|
|
||||||
--name "weave-daemonset-k8s-1.6.yaml" \
|
|
||||||
--file "./prog/weave-kube/weave-daemonset-k8s-1.6.yaml"
|
|
||||||
|
|
||||||
github-release upload \
|
|
||||||
--user $GITHUB_USER \
|
|
||||||
--repo weave \
|
|
||||||
--tag $LATEST_TAG \
|
|
||||||
--name "weave-daemonset-k8s-1.7.yaml" \
|
|
||||||
--file "./prog/weave-kube/weave-daemonset-k8s-1.7.yaml"
|
|
||||||
|
|
||||||
github-release upload \
|
github-release upload \
|
||||||
--user $GITHUB_USER \
|
--user $GITHUB_USER \
|
||||||
--repo weave \
|
--repo weave \
|
||||||
@@ -284,20 +268,6 @@ publish() {
|
|||||||
--name "weave" \
|
--name "weave" \
|
||||||
--file "./weave"
|
--file "./weave"
|
||||||
|
|
||||||
github-release upload \
|
|
||||||
--user $GITHUB_USER \
|
|
||||||
--repo weave \
|
|
||||||
--tag latest_release \
|
|
||||||
--name "weave-daemonset-k8s-1.6.yaml" \
|
|
||||||
--file "./prog/weave-kube/weave-daemonset-k8s-1.6.yaml"
|
|
||||||
|
|
||||||
github-release upload \
|
|
||||||
--user $GITHUB_USER \
|
|
||||||
--repo weave \
|
|
||||||
--tag latest_release \
|
|
||||||
--name "weave-daemonset-k8s-1.7.yaml" \
|
|
||||||
--file "./prog/weave-kube/weave-daemonset-k8s-1.7.yaml"
|
|
||||||
|
|
||||||
github-release upload \
|
github-release upload \
|
||||||
--user $GITHUB_USER \
|
--user $GITHUB_USER \
|
||||||
--repo weave \
|
--repo weave \
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.13.3-buster
|
FROM golang:1.15.6-buster
|
||||||
|
|
||||||
# Support Raspberry Pi 2 and newer
|
# Support Raspberry Pi 2 and newer
|
||||||
ENV GOARM 7
|
ENV GOARM 7
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package chains
|
||||||
|
|
||||||
|
const (
|
||||||
|
MainChain = "WEAVE-NPC"
|
||||||
|
DefaultChain = "WEAVE-NPC-DEFAULT"
|
||||||
|
IngressChain = "WEAVE-NPC-INGRESS"
|
||||||
|
|
||||||
|
EgressChain = "WEAVE-NPC-EGRESS"
|
||||||
|
EgressDefaultChain = "WEAVE-NPC-EGRESS-DEFAULT"
|
||||||
|
EgressCustomChain = "WEAVE-NPC-EGRESS-CUSTOM"
|
||||||
|
EgressMarkChain = "WEAVE-NPC-EGRESS-ACCEPT"
|
||||||
|
)
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
module github.com/weaveworks/weave
|
||||||
|
|
||||||
|
go 1.14
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
|
||||||
|
github.com/Microsoft/go-winio v0.4.7 // indirect
|
||||||
|
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
||||||
|
github.com/andybalholm/go-bit v0.0.0-20150501193155-34813fe0e46a
|
||||||
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
||||||
|
github.com/aws/aws-sdk-go v1.13.22
|
||||||
|
github.com/boltdb/bolt v1.3.1
|
||||||
|
github.com/containerd/continuity v0.0.0-20180322171221-3e8f2ea4b190 // indirect
|
||||||
|
github.com/containernetworking/cni v0.5.2
|
||||||
|
github.com/coreos/go-iptables v0.3.0
|
||||||
|
github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible // indirect
|
||||||
|
github.com/docker/docker v17.12.0-ce-rc1.0.20180328155642-38588656727d+incompatible
|
||||||
|
github.com/docker/go-connections v0.3.0 // indirect
|
||||||
|
github.com/docker/go-units v0.3.2 // indirect
|
||||||
|
github.com/docker/libnetwork v0.8.0-dev.2.0.20180212220201-119badbd737b
|
||||||
|
github.com/docker/machine v0.14.0
|
||||||
|
github.com/fsouza/go-dockerclient v1.2.0
|
||||||
|
github.com/go-ini/ini v1.33.0 // indirect
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
||||||
|
github.com/google/go-cmp v0.5.1 // indirect
|
||||||
|
github.com/google/gopacket v1.1.16
|
||||||
|
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f // indirect
|
||||||
|
github.com/gorilla/mux v1.6.1
|
||||||
|
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
|
||||||
|
github.com/hashicorp/go-cleanhttp v0.0.0-20171218145408-d5fe4b57a186 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
|
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56
|
||||||
|
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.0.9 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.3 // indirect
|
||||||
|
github.com/mdlayher/raw v0.0.0-20181016155347-fa5ef3332ca9 // indirect
|
||||||
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
|
||||||
|
github.com/miekg/dns v1.0.4
|
||||||
|
github.com/onsi/ginkgo v1.14.0 // indirect
|
||||||
|
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
|
||||||
|
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||||
|
github.com/opencontainers/runc v0.1.1 // indirect
|
||||||
|
github.com/opencontainers/selinux v1.6.0 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1
|
||||||
|
github.com/pkg/profile v1.2.1
|
||||||
|
github.com/prometheus/client_golang v1.7.1
|
||||||
|
github.com/sirupsen/logrus v1.4.2
|
||||||
|
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||||
|
github.com/spf13/cobra v0.0.1
|
||||||
|
github.com/stretchr/testify v1.4.0
|
||||||
|
github.com/vishvananda/netlink v1.0.0
|
||||||
|
github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936
|
||||||
|
github.com/weaveworks/common v0.0.0-20180321110636-ebab3a78900a
|
||||||
|
github.com/weaveworks/go-checkpoint v0.0.0-20170503165305-ebbb8b0518ab
|
||||||
|
github.com/weaveworks/go-odp v0.0.0-20181017121109-6b0aa22550d9
|
||||||
|
github.com/weaveworks/mesh v0.0.0-20191105120815-58dbcc3e8e63
|
||||||
|
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
|
||||||
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1
|
||||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384
|
||||||
|
gopkg.in/ini.v1 v1.57.0 // indirect
|
||||||
|
gotest.tools v2.2.0+incompatible // indirect
|
||||||
|
k8s.io/api v0.18.6
|
||||||
|
k8s.io/apimachinery v0.18.6
|
||||||
|
k8s.io/client-go v0.18.6
|
||||||
|
)
|
||||||
@@ -0,0 +1,411 @@
|
|||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||||
|
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||||
|
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
|
||||||
|
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||||
|
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||||
|
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||||
|
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||||
|
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/Microsoft/go-winio v0.4.7 h1:vOvDiY/F1avSWlCWiKJjdYKz2jVjTK3pWPHndeG4OAY=
|
||||||
|
github.com/Microsoft/go-winio v0.4.7/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||||
|
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||||
|
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
||||||
|
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
||||||
|
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
|
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/andybalholm/go-bit v0.0.0-20150501193155-34813fe0e46a h1:yE4/B7ng2G9tr5DdT/x2bj3u6p3Rze2Ha/61eChret8=
|
||||||
|
github.com/andybalholm/go-bit v0.0.0-20150501193155-34813fe0e46a/go.mod h1:xPmFQkJW5/HS/ZMM6soMdODwdIOO9zs3yAhksnFQJE0=
|
||||||
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||||
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||||
|
github.com/aws/aws-sdk-go v1.13.22 h1:S18o71mCjRUw9bZzw61k2xjZx3/XtzwJKdAXx5CUf6s=
|
||||||
|
github.com/aws/aws-sdk-go v1.13.22/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k=
|
||||||
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||||
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
|
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
|
||||||
|
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/containerd/continuity v0.0.0-20180322171221-3e8f2ea4b190 h1:xySrq2Xw0gX07PHM/LS8kuGpRd3hKDz+0/QvIJRILYk=
|
||||||
|
github.com/containerd/continuity v0.0.0-20180322171221-3e8f2ea4b190/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
|
github.com/containernetworking/cni v0.5.2 h1:/nFPNGJQu4yiNvXxH31qL05FIyGG5Y/p0YxuUutl+PE=
|
||||||
|
github.com/containernetworking/cni v0.5.2/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||||
|
github.com/coreos/go-iptables v0.3.0 h1:UTQkjHl9rPwwtXZhXbY3T932cV9aUnKlSsZ7YGfJVXM=
|
||||||
|
github.com/coreos/go-iptables v0.3.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible h1:W1rhCpxfWMU0CaZSFWpmWfmB68zYZVksig+VC1ZbgI4=
|
||||||
|
github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
|
github.com/docker/docker v17.12.0-ce-rc1.0.20180328155642-38588656727d+incompatible h1:C81UCfrC3AgecXLr1vYezUVtYqTPlizDRO67F/lRU2U=
|
||||||
|
github.com/docker/docker v17.12.0-ce-rc1.0.20180328155642-38588656727d+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
|
github.com/docker/go-connections v0.3.0 h1:3lOnM9cSzgGwx8VfK/NGOW5fLQ0GjIlCkaktF+n1M6o=
|
||||||
|
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
|
github.com/docker/go-units v0.3.2 h1:Kjm80apys7gTtfVmCvVY8gwu10uofaFSrmAKOVrtueE=
|
||||||
|
github.com/docker/go-units v0.3.2/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
|
github.com/docker/libnetwork v0.8.0-dev.2.0.20180212220201-119badbd737b h1:u7WZJnaLG9o39ZmpCJEwuFM6nCBuUQL0y/AbyE5sbaM=
|
||||||
|
github.com/docker/libnetwork v0.8.0-dev.2.0.20180212220201-119badbd737b/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
|
||||||
|
github.com/docker/machine v0.14.0 h1:7zMwMAz0XbL27Q4NPqtW7I0wuhOaGFpq5WfvrUfZROM=
|
||||||
|
github.com/docker/machine v0.14.0/go.mod h1:I8mPNDeK1uH+JTcUU7X0ZW8KiYz0jyAgNaeSJ1rCfDI=
|
||||||
|
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||||
|
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||||
|
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||||
|
github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
|
||||||
|
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
|
github.com/fsouza/go-dockerclient v1.2.0 h1:lmjnUbZFR+De5PfuXCk62hAIlkokNtD9CaGPR8Iu5UU=
|
||||||
|
github.com/fsouza/go-dockerclient v1.2.0/go.mod h1:KpcjM623fQYE9MZiTGzKhjfxXAV9wbyX2C1cyRHfhl0=
|
||||||
|
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/go-ini/ini v1.33.0 h1:/0Y2X+/6jgfPYl2LOihvxikDfznXMufz0Zkr3mW+7Zg=
|
||||||
|
github.com/go-ini/ini v1.33.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||||
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
|
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||||
|
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||||
|
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||||
|
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
||||||
|
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
|
||||||
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||||
|
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
|
||||||
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
||||||
|
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/gopacket v1.1.16 h1:u6Afvia5C5srlLcbTwpHaFW918asLYPxieziOaWwz8M=
|
||||||
|
github.com/google/gopacket v1.1.16/go.mod h1:UCLx9mCmAwsVbn6qQl1WIEt2SO7Nd2fD0th1TBAsqBw=
|
||||||
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||||
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
|
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
|
github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI=
|
||||||
|
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
|
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f h1:9oNbS1z4rVpbnkHBdPZU4jo9bSmrLpII768arSyMFgk=
|
||||||
|
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
|
github.com/gorilla/mux v1.6.1 h1:KOwqsTYZdeuMacU7CxjMNYEKeBvLbxW+psodrbcEa3A=
|
||||||
|
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI=
|
||||||
|
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
|
||||||
|
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
|
||||||
|
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||||
|
github.com/hashicorp/go-cleanhttp v0.0.0-20171218145408-d5fe4b57a186 h1:URgjUo+bs1KwatoNbwG0uCO4dHN4r1jsp4a5AGgHRjo=
|
||||||
|
github.com/hashicorp/go-cleanhttp v0.0.0-20171218145408-d5fe4b57a186/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56 h1:742eGXur0715JMq73aD95/FU0XpVKXqNuTnEfXsLOYQ=
|
||||||
|
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
|
||||||
|
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE=
|
||||||
|
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||||
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
||||||
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
|
github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
|
||||||
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
github.com/mdlayher/raw v0.0.0-20181016155347-fa5ef3332ca9 h1:tOtO8DXiNGj9NshRKHWiZuGlSldPFzFCFYhNtsKTBCs=
|
||||||
|
github.com/mdlayher/raw v0.0.0-20181016155347-fa5ef3332ca9/go.mod h1:rC/yE65s/DoHB6BzVOUBNYBGTg772JVytyAytffIZkY=
|
||||||
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||||
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
|
github.com/miekg/dns v1.0.4 h1:Ec3LTJwwzqT1++63P12fhtdEbQhtPE7TBdD6rlhqrMM=
|
||||||
|
github.com/miekg/dns v1.0.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||||
|
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||||
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
|
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
|
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
||||||
|
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||||
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
|
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
|
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
||||||
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
|
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||||
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
|
github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=
|
||||||
|
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
|
github.com/opencontainers/selinux v1.6.0 h1:+bIAS/Za3q5FTwWym4fTB0vObnfCf3G/NC7K6Jx62mY=
|
||||||
|
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
||||||
|
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||||
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
|
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/profile v1.2.1 h1:F++O52m40owAmADcojzM+9gyjmMOY/T4oYJkgFDH8RE=
|
||||||
|
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
|
github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
|
||||||
|
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||||
|
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
|
||||||
|
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
|
||||||
|
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||||
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
|
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
|
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||||
|
github.com/spf13/cobra v0.0.1 h1:zZh3X5aZbdnoj+4XkaBxKfhO4ot82icYdhhREIAXIj8=
|
||||||
|
github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
|
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM=
|
||||||
|
github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936 h1:J9gO8RJCAFlln1jsvRba/CWVUnMHwObklfxxjErl1uk=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
|
||||||
|
github.com/weaveworks/common v0.0.0-20180321110636-ebab3a78900a h1:dIOYWkmKCq9tU3DY96p1D/8xXFWkqt9Jd1ipu6sTLSk=
|
||||||
|
github.com/weaveworks/common v0.0.0-20180321110636-ebab3a78900a/go.mod h1:pSm+0KR57BG3pvGoJWFXJSAC7+sEPewcvdt5StevL3A=
|
||||||
|
github.com/weaveworks/go-checkpoint v0.0.0-20170503165305-ebbb8b0518ab h1:mW+hgchD9qUUBqnuaDBj7BkcpFPk/FxeFcUFI5lvvUw=
|
||||||
|
github.com/weaveworks/go-checkpoint v0.0.0-20170503165305-ebbb8b0518ab/go.mod h1:qkbvw5GPibQ/Nf7IZJL0UoLwmJ6858b4S/hUWRd+cH4=
|
||||||
|
github.com/weaveworks/go-odp v0.0.0-20181017121109-6b0aa22550d9 h1:7OqrOqOJkneFGUT7CoR3uZnZP3ZyuUtzWNfv7GIc3RE=
|
||||||
|
github.com/weaveworks/go-odp v0.0.0-20181017121109-6b0aa22550d9/go.mod h1:6/WClQKiVm/SQf6WJXv49l+9K9ONE2U8DYpeXEk3X7k=
|
||||||
|
github.com/weaveworks/mesh v0.0.0-20191105120815-58dbcc3e8e63 h1:s0fUBZ8Vhtc3ruFmLIr3qVTQUb/j6ySkPLHoKKitHeM=
|
||||||
|
github.com/weaveworks/mesh v0.0.0-20191105120815-58dbcc3e8e63/go.mod h1:RZebXKv56dax5zXcLIJZm1Awk28sx0XODXF94Z8WssY=
|
||||||
|
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243 h1:R43TdZy32XXSXjJn7M/HhALJ9imq6ztLnChfYJpVDnM=
|
||||||
|
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||||
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc h1:c0o/qxkaO2LF5t6fQrT4b5hzyggAkLLlCUjqfRxd8Q4=
|
||||||
|
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
|
||||||
|
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
|
||||||
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
|
||||||
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
|
||||||
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg=
|
||||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
|
||||||
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||||
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
|
gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww=
|
||||||
|
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
k8s.io/api v0.18.6 h1:osqrAXbOQjkKIWDTjrqxWQ3w0GkKb1KA1XkUGHHYpeE=
|
||||||
|
k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI=
|
||||||
|
k8s.io/apimachinery v0.18.6 h1:RtFHnfGNfd1N0LeSrKCUznz5xtUP1elRGvHJbL3Ntag=
|
||||||
|
k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
|
||||||
|
k8s.io/client-go v0.18.6 h1:I+oWqJbibLSGsZj8Xs8F0aWVXJVIoUHWaaJV3kUN/Zw=
|
||||||
|
k8s.io/client-go v0.18.6/go.mod h1:/fwtGLjYMS1MaM5oi+eXhKwG+1UHidUEXRh6cNsdO0Q=
|
||||||
|
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
|
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||||
|
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||||
|
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||||
|
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||||
|
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY=
|
||||||
|
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||||
|
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU=
|
||||||
|
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
|
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||||
|
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||||
@@ -207,21 +207,6 @@ func (alloc *Allocator) doOperation(op operation, ops *[]operation) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given an operation, remove it from the pending queue
|
|
||||||
// Note the op may not be on the queue; it may have
|
|
||||||
// already succeeded. If it is on the queue, we call
|
|
||||||
// cancel on it, allowing callers waiting for the resultChans
|
|
||||||
// to unblock.
|
|
||||||
func (alloc *Allocator) cancelOp(opToCancel operation, ops *[]operation) {
|
|
||||||
for i, op := range *ops {
|
|
||||||
if op == opToCancel {
|
|
||||||
*ops = append((*ops)[:i], (*ops)[i+1:]...)
|
|
||||||
op.Cancel()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cancel all operations in a queue
|
// Cancel all operations in a queue
|
||||||
func (alloc *Allocator) cancelOps(ops *[]operation) {
|
func (alloc *Allocator) cancelOps(ops *[]operation) {
|
||||||
for _, op := range *ops {
|
for _, op := range *ops {
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
testStart1 = "10.0.1.0"
|
testStart1 = "10.0.1.0"
|
||||||
testStart2 = "10.0.2.0"
|
|
||||||
testStart3 = "10.0.3.0"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func returnFalse() bool { return false }
|
func returnFalse() bool { return false }
|
||||||
|
|||||||
+10
-9
@@ -1,6 +1,7 @@
|
|||||||
package ipam
|
package ipam
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -41,7 +42,7 @@ func writeAddresses(w http.ResponseWriter, cidrs []address.CIDR) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasBeenCancelled(dockerCli *docker.Client, closedChan <-chan bool, ident string, checkAlive bool) func() bool {
|
func hasBeenCancelled(dockerCli *docker.Client, closedChan <-chan struct{}, ident string, checkAlive bool) func() bool {
|
||||||
return func() bool {
|
return func() bool {
|
||||||
select {
|
select {
|
||||||
case <-closedChan:
|
case <-closedChan:
|
||||||
@@ -63,9 +64,9 @@ func cancellationErr(w http.ResponseWriter, err error) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (alloc *Allocator) handleHTTPAllocate(dockerCli *docker.Client, w http.ResponseWriter, ident string, checkAlive bool, subnet address.CIDR) {
|
func (alloc *Allocator) handleHTTPAllocate(ctx context.Context, dockerCli *docker.Client, w http.ResponseWriter, ident string, checkAlive bool, subnet address.CIDR) {
|
||||||
addr, err := alloc.Allocate(ident, subnet, checkAlive,
|
addr, err := alloc.Allocate(ident, subnet, checkAlive,
|
||||||
hasBeenCancelled(dockerCli, w.(http.CloseNotifier).CloseNotify(), ident, checkAlive))
|
hasBeenCancelled(dockerCli, ctx.Done(), ident, checkAlive))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !cancellationErr(w, err) {
|
if !cancellationErr(w, err) {
|
||||||
badRequest(w, err)
|
badRequest(w, err)
|
||||||
@@ -75,9 +76,9 @@ func (alloc *Allocator) handleHTTPAllocate(dockerCli *docker.Client, w http.Resp
|
|||||||
fmt.Fprintf(w, "%s/%d", addr, subnet.PrefixLen)
|
fmt.Fprintf(w, "%s/%d", addr, subnet.PrefixLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (alloc *Allocator) handleHTTPClaim(dockerCli *docker.Client, w http.ResponseWriter, ident string, cidr address.CIDR, checkAlive, noErrorOnUnknown bool) {
|
func (alloc *Allocator) handleHTTPClaim(ctx context.Context, dockerCli *docker.Client, w http.ResponseWriter, ident string, cidr address.CIDR, checkAlive, noErrorOnUnknown bool) {
|
||||||
err := alloc.Claim(ident, cidr, checkAlive, noErrorOnUnknown,
|
err := alloc.Claim(ident, cidr, checkAlive, noErrorOnUnknown,
|
||||||
hasBeenCancelled(dockerCli, w.(http.CloseNotifier).CloseNotify(), ident, checkAlive))
|
hasBeenCancelled(dockerCli, ctx.Done(), ident, checkAlive))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !cancellationErr(w, err) {
|
if !cancellationErr(w, err) {
|
||||||
badRequest(w, fmt.Errorf("Unable to claim: %s", err))
|
badRequest(w, fmt.Errorf("Unable to claim: %s", err))
|
||||||
@@ -99,7 +100,7 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID
|
|||||||
ident := vars["id"]
|
ident := vars["id"]
|
||||||
checkAlive := r.FormValue("check-alive") == "true"
|
checkAlive := r.FormValue("check-alive") == "true"
|
||||||
noErrorOnUnknown := r.FormValue("noErrorOnUnknown") == "true"
|
noErrorOnUnknown := r.FormValue("noErrorOnUnknown") == "true"
|
||||||
alloc.handleHTTPClaim(dockerCli, w, ident, cidr, checkAlive, noErrorOnUnknown)
|
alloc.handleHTTPClaim(r.Context(), dockerCli, w, ident, cidr, checkAlive, noErrorOnUnknown)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -164,13 +165,13 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID
|
|||||||
router.Methods("POST").Path("/ip/{id}/{ip}/{prefixlen}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
router.Methods("POST").Path("/ip/{id}/{ip}/{prefixlen}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
if subnet, ok := parseCIDR(w, vars["ip"]+"/"+vars["prefixlen"], true); ok {
|
if subnet, ok := parseCIDR(w, vars["ip"]+"/"+vars["prefixlen"], true); ok {
|
||||||
alloc.handleHTTPAllocate(dockerCli, w, vars["id"], r.FormValue("check-alive") == "true", subnet)
|
alloc.handleHTTPAllocate(r.Context(), dockerCli, w, vars["id"], r.FormValue("check-alive") == "true", subnet)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
router.Methods("POST").Path("/ip/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
router.Methods("POST").Path("/ip/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
alloc.handleHTTPAllocate(dockerCli, w, vars["id"], r.FormValue("check-alive") == "true", defaultSubnet)
|
alloc.handleHTTPAllocate(r.Context(), dockerCli, w, vars["id"], r.FormValue("check-alive") == "true", defaultSubnet)
|
||||||
})
|
})
|
||||||
|
|
||||||
router.Methods("DELETE").Path("/ip/{id}/{ip}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
router.Methods("DELETE").Path("/ip/{id}/{ip}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -203,6 +204,6 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID
|
|||||||
if alloc.tracker != nil {
|
if alloc.tracker != nil {
|
||||||
tracker = alloc.tracker.String()
|
tracker = alloc.tracker.String()
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, tracker)
|
fmt.Fprintln(w, tracker)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
+4
-1
@@ -1,6 +1,7 @@
|
|||||||
package ipam
|
package ipam
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -158,11 +159,13 @@ func TestHTTPCancel(t *testing.T) {
|
|||||||
|
|
||||||
// Ask the http server for a new address
|
// Ask the http server for a new address
|
||||||
req, _ := http.NewRequest("POST", allocURL(port, testCIDR1, containerID), nil)
|
req, _ := http.NewRequest("POST", allocURL(port, testCIDR1, containerID), nil)
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
req = req.WithContext(ctx)
|
||||||
// On another goroutine, wait for a bit then cancel the request
|
// On another goroutine, wait for a bit then cancel the request
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
common.Log.Debug("Cancelling allocate")
|
common.Log.Debug("Cancelling allocate")
|
||||||
http.DefaultTransport.(*http.Transport).CancelRequest(req)
|
cancel()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
res, _ := http.DefaultClient.Do(req)
|
res, _ := http.DefaultClient.Do(req)
|
||||||
|
|||||||
@@ -56,16 +56,6 @@ func (m *Model) addLink(a, b *TestNode) {
|
|||||||
m.readyLinks = append(m.readyLinks, &ab, &ba)
|
m.readyLinks = append(m.readyLinks, &ab, &ba)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) linkExists(a, b *TestNode) bool {
|
|
||||||
for _, l := range a.links {
|
|
||||||
if l.to == b {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestParams struct {
|
type TestParams struct {
|
||||||
// Number of nodes
|
// Number of nodes
|
||||||
nodeCount uint
|
nodeCount uint
|
||||||
|
|||||||
+1
-1
@@ -560,7 +560,7 @@ func (r *Ring) ChoosePeersToAskForSpace(start, end address.Address) []mesh.PeerN
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Ignore ranges with no free space
|
// Ignore ranges with no free space
|
||||||
if entry.Free <= 0 {
|
if entry.Free == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ func TestLowlevel(t *testing.T) {
|
|||||||
|
|
||||||
// test Donate when addresses are scarce
|
// test Donate when addresses are scarce
|
||||||
s = New()
|
s = New()
|
||||||
r, ok = s.Donate(address.NewRange(0, 1000))
|
_, ok = s.Donate(address.NewRange(0, 1000))
|
||||||
require.True(t, !ok, "donate on empty space should fail")
|
require.True(t, !ok, "donate on empty space should fail")
|
||||||
s.Add(0, 3)
|
s.Add(0, 3)
|
||||||
require.NoError(t, s.Claim(0))
|
require.NoError(t, s.Claim(0))
|
||||||
@@ -81,7 +81,7 @@ func TestLowlevel(t *testing.T) {
|
|||||||
r, ok = s.Donate(address.NewRange(0, 1000))
|
r, ok = s.Donate(address.NewRange(0, 1000))
|
||||||
require.True(t, ok, "donate")
|
require.True(t, ok, "donate")
|
||||||
require.Equal(t, address.NewRange(1, 1), r, "donate")
|
require.Equal(t, address.NewRange(1, 1), r, "donate")
|
||||||
r, ok = s.Donate(address.NewRange(0, 1000))
|
_, ok = s.Donate(address.NewRange(0, 1000))
|
||||||
require.True(t, !ok, "donate should fail")
|
require.True(t, !ok, "donate should fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,14 +24,6 @@ func (m *mockMessage) String() string {
|
|||||||
return fmt.Sprintf("-> %s [%x]", m.dst, m.buf)
|
return fmt.Sprintf("-> %s [%x]", m.dst, m.buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toStringArray(messages []mockMessage) []string {
|
|
||||||
out := make([]string, len(messages))
|
|
||||||
for i := range out {
|
|
||||||
out[i] = messages[i].String()
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockGossipComms struct {
|
type mockGossipComms struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
*testing.T
|
*testing.T
|
||||||
@@ -100,14 +92,6 @@ func (m *mockGossipComms) GossipUnicast(dstPeerName mesh.PeerName, buf []byte) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExpectMessage(alloc *Allocator, dst string, msgType byte, buf []byte) {
|
|
||||||
m := alloc.gossip.(*mockGossipComms)
|
|
||||||
dstPeerName, _ := mesh.PeerNameFromString(dst)
|
|
||||||
m.Lock()
|
|
||||||
m.messages = append(m.messages, mockMessage{dstPeerName, msgType, buf})
|
|
||||||
m.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExpectBroadcastMessage(alloc *Allocator, buf []byte) {
|
func ExpectBroadcastMessage(alloc *Allocator, buf []byte) {
|
||||||
m := alloc.gossip.(*mockGossipComms)
|
m := alloc.gossip.(*mockGossipComms)
|
||||||
m.Lock()
|
m.Lock()
|
||||||
@@ -208,15 +192,6 @@ func AssertNothingSent(t *testing.T, ch <-chan bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AssertNothingSentErr(t *testing.T, ch <-chan error) {
|
|
||||||
select {
|
|
||||||
case val := <-ch:
|
|
||||||
require.FailNow(t, fmt.Sprintf("Unexpected value on channel: %v", val))
|
|
||||||
default:
|
|
||||||
// no message received
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeNetworkOfAllocators(size int, cidr string, preClaims ...[]PreClaim) ([]*Allocator, *gossip.TestRouter, address.CIDR) {
|
func makeNetworkOfAllocators(size int, cidr string, preClaims ...[]PreClaim) ([]*Allocator, *gossip.TestRouter, address.CIDR) {
|
||||||
gossipRouter := gossip.NewTestRouter(0.0)
|
gossipRouter := gossip.NewTestRouter(0.0)
|
||||||
allocs := make([]*Allocator, size)
|
allocs := make([]*Allocator, size)
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ func NewAWSVPCTracker(bridgeName string) (*AWSVPCTracker, error) {
|
|||||||
func (t *AWSVPCTracker) HandleUpdate(prevRanges, currRanges []address.Range, local bool) error {
|
func (t *AWSVPCTracker) HandleUpdate(prevRanges, currRanges []address.Range, local bool) error {
|
||||||
t.debugf("replacing %q by %q; local(%t)", prevRanges, currRanges, local)
|
t.debugf("replacing %q by %q; local(%t)", prevRanges, currRanges, local)
|
||||||
|
|
||||||
prev, curr := RemoveCommon(address.NewCIDRs(Merge(prevRanges)), address.NewCIDRs(Merge(currRanges)))
|
prev, curr := address.RemoveCommon(address.NewCIDRs(address.Merge(prevRanges)), address.NewCIDRs(address.Merge(currRanges)))
|
||||||
|
|
||||||
// It might make sense to do the removal first and then add entries
|
// It might make sense to do the removal first and then add entries
|
||||||
// because of the 50 routes limit. However, in such case a container might
|
// because of the 50 routes limit. However, in such case a container might
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
package tracker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/weaveworks/weave/net/address"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
r0to127 = cidr("10.0.0.0", "10.0.0.127")
|
|
||||||
r128to255 = cidr("10.0.0.128", "10.0.0.255")
|
|
||||||
r0to255 = cidr("10.0.0.0", "10.0.0.255")
|
|
||||||
r1dot0to255 = cidr("10.0.1.0", "10.0.1.255")
|
|
||||||
r2dot0to255 = cidr("10.0.2.0", "10.0.2.255")
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRemoveCommon(t *testing.T) {
|
|
||||||
a := []address.CIDR{r0to127, r1dot0to255}
|
|
||||||
b := []address.CIDR{r1dot0to255, r2dot0to255}
|
|
||||||
newA, newB := RemoveCommon(a, b)
|
|
||||||
require.Equal(t, []address.CIDR{r0to127}, newA)
|
|
||||||
require.Equal(t, []address.CIDR{r2dot0to255}, newB)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMerge(t *testing.T) {
|
|
||||||
ranges := []address.Range{
|
|
||||||
r0to127.Range(),
|
|
||||||
r128to255.Range(),
|
|
||||||
r2dot0to255.Range(),
|
|
||||||
}
|
|
||||||
require.Equal(t, []address.Range{r0to255.Range(), r2dot0to255.Range()}, Merge(ranges))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper
|
|
||||||
|
|
||||||
// TODO(mp) DRY with helpers of other tests.
|
|
||||||
|
|
||||||
func ip(s string) address.Address {
|
|
||||||
addr, _ := address.ParseIP(s)
|
|
||||||
return addr
|
|
||||||
}
|
|
||||||
|
|
||||||
// [start; end]
|
|
||||||
func cidr(start, end string) address.CIDR {
|
|
||||||
c := address.Range{Start: ip(start), End: ip(end) + 1}.CIDRs()
|
|
||||||
if len(c) != 1 {
|
|
||||||
panic("invalid cidr")
|
|
||||||
}
|
|
||||||
return c[0]
|
|
||||||
}
|
|
||||||
+5
-1
@@ -90,7 +90,7 @@ type DNSServer struct {
|
|||||||
ns *Nameserver
|
ns *Nameserver
|
||||||
domain string
|
domain string
|
||||||
ttl uint32
|
ttl uint32
|
||||||
address string
|
address string // listen address and port, e.g. 1.2.3.4:53
|
||||||
|
|
||||||
servers []*dns.Server
|
servers []*dns.Server
|
||||||
upstream Upstream
|
upstream Upstream
|
||||||
@@ -99,6 +99,10 @@ type DNSServer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewDNSServer(ns *Nameserver, domain, address string, upstream Upstream, ttl uint32, clientTimeout time.Duration) (*DNSServer, error) {
|
func NewDNSServer(ns *Nameserver, domain, address string, upstream Upstream, ttl uint32, clientTimeout time.Duration) (*DNSServer, error) {
|
||||||
|
if _, _, err := net.SplitHostPort(address); err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid DNS listen address %q: %v", address, err)
|
||||||
|
}
|
||||||
|
|
||||||
s := &DNSServer{
|
s := &DNSServer{
|
||||||
ns: ns,
|
ns: ns,
|
||||||
domain: dns.Fqdn(domain),
|
domain: dns.Fqdn(domain),
|
||||||
|
|||||||
@@ -41,9 +41,7 @@ func TestTruncation(t *testing.T) {
|
|||||||
defer dnsserver.Stop()
|
defer dnsserver.Stop()
|
||||||
|
|
||||||
// Add 100 mappings to nameserver
|
// Add 100 mappings to nameserver
|
||||||
addrs := []address.Address{}
|
|
||||||
for i := address.Address(0); i < 100; i++ {
|
for i := address.Address(0); i < 100; i++ {
|
||||||
addrs = append(addrs, i)
|
|
||||||
nameserver.AddEntry("foo.weave.local.", "", mesh.UnknownPeerName, i)
|
nameserver.AddEntry("foo.weave.local.", "", mesh.UnknownPeerName, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package nameserver
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
@@ -84,3 +85,13 @@ func (n *Nameserver) HandleHTTP(router *mux.Router, dockerCli *docker.Client) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *DNSServer) HandleHTTP(router *mux.Router) {
|
||||||
|
router.Methods("GET").Path("/dns-address-port").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Fprint(w, d.address)
|
||||||
|
})
|
||||||
|
router.Methods("GET").Path("/dns-address").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
host, _, _ := net.SplitHostPort(d.address) // address is validated in NewDNSServer()
|
||||||
|
fmt.Fprint(w, host)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
package tracker
|
package address
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/weaveworks/weave/net/address"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Merge merges adjacent range entries.
|
// Merge merges adjacent range entries.
|
||||||
// The given slice has to be sorted in increasing order.
|
// The given slice has to be sorted in increasing order.
|
||||||
func Merge(r []address.Range) []address.Range {
|
func Merge(r []Range) []Range {
|
||||||
var merged []address.Range
|
var merged []Range
|
||||||
|
|
||||||
for i := range r {
|
for i := range r {
|
||||||
if prev := len(merged) - 1; prev >= 0 && merged[prev].End == r[i].Start {
|
if prev := len(merged) - 1; prev >= 0 && merged[prev].End == r[i].Start {
|
||||||
@@ -22,7 +18,7 @@ func Merge(r []address.Range) []address.Range {
|
|||||||
|
|
||||||
// RemoveCommon filters out CIDR ranges which are contained in both a and b slices.
|
// RemoveCommon filters out CIDR ranges which are contained in both a and b slices.
|
||||||
// Both slices have to be sorted in increasing order.
|
// Both slices have to be sorted in increasing order.
|
||||||
func RemoveCommon(a, b []address.CIDR) (newA, newB []address.CIDR) {
|
func RemoveCommon(a, b []CIDR) (newA, newB []CIDR) {
|
||||||
i, j := 0, 0
|
i, j := 0, 0
|
||||||
|
|
||||||
for i < len(a) && j < len(b) {
|
for i < len(a) && j < len(b) {
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package address
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
r0to127 = cidr2("10.0.0.0", "10.0.0.127")
|
||||||
|
r128to255 = cidr2("10.0.0.128", "10.0.0.255")
|
||||||
|
r0to255 = cidr2("10.0.0.0", "10.0.0.255")
|
||||||
|
r1dot0to255 = cidr2("10.0.1.0", "10.0.1.255")
|
||||||
|
r2dot0to255 = cidr2("10.0.2.0", "10.0.2.255")
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRemoveCommon(t *testing.T) {
|
||||||
|
a := []CIDR{r0to127, r1dot0to255}
|
||||||
|
b := []CIDR{r1dot0to255, r2dot0to255}
|
||||||
|
newA, newB := RemoveCommon(a, b)
|
||||||
|
require.Equal(t, []CIDR{r0to127}, newA)
|
||||||
|
require.Equal(t, []CIDR{r2dot0to255}, newB)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMerge(t *testing.T) {
|
||||||
|
ranges := []Range{
|
||||||
|
r0to127.Range(),
|
||||||
|
r128to255.Range(),
|
||||||
|
r2dot0to255.Range(),
|
||||||
|
}
|
||||||
|
require.Equal(t, []Range{r0to255.Range(), r2dot0to255.Range()}, Merge(ranges))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper
|
||||||
|
|
||||||
|
// [start; end]
|
||||||
|
func cidr2(start, end string) CIDR {
|
||||||
|
c := Range{Start: ip(start), End: ip(end) + 1}.CIDRs()
|
||||||
|
if len(c) != 1 {
|
||||||
|
panic("invalid cidr")
|
||||||
|
}
|
||||||
|
return c[0]
|
||||||
|
}
|
||||||
@@ -41,3 +41,11 @@ func sysctl(procPath, variable, value string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sysctlIfExists(procPath, variable, value string) error {
|
||||||
|
err := sysctl(procPath, variable, value)
|
||||||
|
if err != nil && os.IsNotExist(err) {
|
||||||
|
err = nil // ignore 'not found' errors
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
+57
-35
@@ -11,14 +11,12 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/weaveworks/weave/common"
|
||||||
|
"github.com/weaveworks/weave/common/chains"
|
||||||
"github.com/weaveworks/weave/common/odp"
|
"github.com/weaveworks/weave/common/odp"
|
||||||
"github.com/weaveworks/weave/ipam/tracker"
|
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/weaveworks/weave/net/address"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/weaveworks/weave/net/ipset"
|
||||||
"github.com/weaveworks/weave/npc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/* This code implements three possible configurations to connect
|
/* This code implements three possible configurations to connect
|
||||||
@@ -262,7 +260,7 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := configureIPTables(config, ips); err != nil {
|
if err := ConfigureIPTables(config, ips); err != nil {
|
||||||
return bridgeType, errors.Wrap(err, "configuring iptables")
|
return bridgeType, errors.Wrap(err, "configuring iptables")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,7 +279,7 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No ipv6 router advertisments please
|
// No ipv6 router advertisments please
|
||||||
if err := sysctl(procPath, "net/ipv6/conf/"+config.WeaveBridgeName+"/accept_ra", "0"); err != nil {
|
if err := sysctlIfExists(procPath, "net/ipv6/conf/"+config.WeaveBridgeName+"/accept_ra", "0"); err != nil {
|
||||||
return bridgeType, errors.Wrap(err, "setting accept_ra to 0")
|
return bridgeType, errors.Wrap(err, "setting accept_ra to 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,9 +295,7 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
|
|||||||
return bridgeType, errors.Wrapf(err, "configuring ARP cache on bridge %q", config.WeaveBridgeName)
|
return bridgeType, errors.Wrapf(err, "configuring ARP cache on bridge %q", config.WeaveBridgeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: No concurrent call to Expose is possible, as EnsureBridge is called
|
if err := Reexpose(config, log); err != nil {
|
||||||
// before any service has been started.
|
|
||||||
if err := reexpose(config, log); err != nil {
|
|
||||||
return bridgeType, err
|
return bridgeType, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,10 +427,40 @@ func (f fastdpImpl) attach(veth *netlink.Veth) error {
|
|||||||
return odp.AddDatapathInterfaceIfNotExist(f.datapathName, veth.Attrs().Name)
|
return odp.AddDatapathInterfaceIfNotExist(f.datapathName, veth.Attrs().Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
|
// ResetIPTables resets IPTables in case they're in a strange state from a previous run.
|
||||||
|
func ResetIPTables(config *BridgeConfig, ips ipset.Interface) error {
|
||||||
ipt, err := iptables.New()
|
ipt, err := iptables.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "creating iptables object")
|
return errors.Wrap(err, "creating iptables object while resetting")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !config.NPC {
|
||||||
|
// Create/Flush a chain for allowing ingress traffic when the bridge is exposed
|
||||||
|
if err := ipt.ClearChain("filter", "WEAVE-EXPOSE"); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to clear/create filter/WEAVE-EXPOSE chain")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ipt.ClearChain("nat", "WEAVE"); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to clear/create nat/WEAVE chain")
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.NoMasqLocal {
|
||||||
|
ips := ipset.New(common.LogLogger(), 0)
|
||||||
|
_ = ips.Destroy(NoMasqLocalIpset)
|
||||||
|
if err := ips.Create(NoMasqLocalIpset, ipset.HashNet); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigureIPTables idempotently configures all the iptables!
|
||||||
|
func ConfigureIPTables(config *BridgeConfig, ips ipset.Interface) error {
|
||||||
|
ipt, err := iptables.New()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "creating iptables object while configuring")
|
||||||
}
|
}
|
||||||
|
|
||||||
// The order among weave filter/FORWARD rules is important!
|
// The order among weave filter/FORWARD rules is important!
|
||||||
@@ -485,12 +511,12 @@ func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
|
|||||||
if config.NPC {
|
if config.NPC {
|
||||||
// Steer traffic via the NPC.
|
// Steer traffic via the NPC.
|
||||||
|
|
||||||
if err = ensureChains(ipt, "filter", npc.MainChain, npc.EgressChain); err != nil {
|
if err = ensureChains(ipt, "filter", chains.MainChain, chains.EgressChain); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Steer egress traffic destined to local node.
|
// Steer egress traffic destined to local node.
|
||||||
if err = ipt.AppendUnique("filter", "INPUT", "-i", config.WeaveBridgeName, "-j", npc.EgressChain); err != nil {
|
if err = ipt.AppendUnique("filter", "INPUT", "-i", config.WeaveBridgeName, "-j", chains.EgressChain); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fwdRules = append(fwdRules,
|
fwdRules = append(fwdRules,
|
||||||
@@ -499,11 +525,11 @@ func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
|
|||||||
// ACCEPT in WEAVE-NPC-EGRESS chain
|
// ACCEPT in WEAVE-NPC-EGRESS chain
|
||||||
{"-i", config.WeaveBridgeName,
|
{"-i", config.WeaveBridgeName,
|
||||||
"-m", "comment", "--comment", "NOTE: this must go before '-j KUBE-FORWARD'",
|
"-m", "comment", "--comment", "NOTE: this must go before '-j KUBE-FORWARD'",
|
||||||
"-j", npc.EgressChain},
|
"-j", chains.EgressChain},
|
||||||
// The following rules are for ingress NPC processing
|
// The following rules are for ingress NPC processing
|
||||||
{"-o", config.WeaveBridgeName,
|
{"-o", config.WeaveBridgeName,
|
||||||
"-m", "comment", "--comment", "NOTE: this must go before '-j KUBE-FORWARD'",
|
"-m", "comment", "--comment", "NOTE: this must go before '-j KUBE-FORWARD'",
|
||||||
"-j", npc.MainChain},
|
"-j", chains.MainChain},
|
||||||
{"-o", config.WeaveBridgeName, "-m", "state", "--state", "NEW", "-j", "NFLOG", "--nflog-group", "86"},
|
{"-o", config.WeaveBridgeName, "-m", "state", "--state", "NEW", "-j", "NFLOG", "--nflog-group", "86"},
|
||||||
{"-o", config.WeaveBridgeName, "-j", "DROP"},
|
{"-o", config.WeaveBridgeName, "-j", "DROP"},
|
||||||
}...)
|
}...)
|
||||||
@@ -515,8 +541,8 @@ func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
|
|||||||
|
|
||||||
if !config.NPC {
|
if !config.NPC {
|
||||||
// Create/Flush a chain for allowing ingress traffic when the bridge is exposed
|
// Create/Flush a chain for allowing ingress traffic when the bridge is exposed
|
||||||
if err := ipt.ClearChain("filter", "WEAVE-EXPOSE"); err != nil {
|
if err := ensureChains(ipt, "filter", "WEAVE-EXPOSE"); err != nil {
|
||||||
return errors.Wrap(err, "failed to clear/create filter/WEAVE-EXPOSE chain")
|
return errors.Wrap(err, "failed to ensure existence of filter/WEAVE-EXPOSE chain")
|
||||||
}
|
}
|
||||||
|
|
||||||
fwdRules = append(fwdRules, []string{"-o", config.WeaveBridgeName, "-j", "WEAVE-EXPOSE"})
|
fwdRules = append(fwdRules, []string{"-o", config.WeaveBridgeName, "-j", "WEAVE-EXPOSE"})
|
||||||
@@ -532,26 +558,22 @@ func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a chain for masquerading
|
// Create a chain for masquerading
|
||||||
if err := ipt.ClearChain("nat", "WEAVE"); err != nil {
|
if err := ensureChains(ipt, "nat", "WEAVE"); err != nil {
|
||||||
return errors.Wrap(err, "failed to clear/create nat/WEAVE chain")
|
return errors.Wrap(err, "failed to ensure existence of nat/WEAVE chain")
|
||||||
}
|
}
|
||||||
if err := ipt.AppendUnique("nat", "POSTROUTING", "-j", "WEAVE"); err != nil {
|
if err := ipt.AppendUnique("nat", "POSTROUTING", "-j", "WEAVE"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the cases where the weave bridge is the default gateway for
|
// For the cases where the weave bridge is the default gateway for
|
||||||
// containers (e.g. Kubernetes): create the ipset to store CIDRs allocated
|
// containers (e.g. Kubernetes): In `ResetIPTables` (which we assume
|
||||||
// by IPAM for local containers. In the case of Kubernetes, external traffic
|
// to have been called at this point) we create an ipset to store CIDRs
|
||||||
// sent to these CIDRs avoids SNAT'ing so that NodePort with
|
// allocated by IPAM for local containers.
|
||||||
// `"externalTrafficPolicy":"Local"` would receive packets with correct
|
// In the case of Kubernetes, external traffic sent to these CIDRs
|
||||||
// src IP addr.
|
// avoids SNAT'ing so that NodePort with `"externalTrafficPolicy":"Local"`
|
||||||
|
// would receive packets with correct src IP addr.
|
||||||
if config.NoMasqLocal {
|
if config.NoMasqLocal {
|
||||||
ips := ipset.New(common.LogLogger(), 0)
|
if err := ipt.AppendUnique("nat", "WEAVE",
|
||||||
_ = ips.Destroy(NoMasqLocalIpset)
|
|
||||||
if err := ips.Create(NoMasqLocalIpset, ipset.HashNet); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := ipt.Insert("nat", "WEAVE", 1,
|
|
||||||
"-m", "set", "--match-set", string(NoMasqLocalIpset), "dst",
|
"-m", "set", "--match-set", string(NoMasqLocalIpset), "dst",
|
||||||
"-m", "comment", "--comment", "Prevent SNAT to locally running containers",
|
"-m", "comment", "--comment", "Prevent SNAT to locally running containers",
|
||||||
"-j", "RETURN"); err != nil {
|
"-j", "RETURN"); err != nil {
|
||||||
@@ -564,13 +586,13 @@ func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
|
|||||||
|
|
||||||
type NoMasqLocalTracker struct {
|
type NoMasqLocalTracker struct {
|
||||||
ips ipset.Interface
|
ips ipset.Interface
|
||||||
owner types.UID
|
owner ipset.UID
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNoMasqLocalTracker(ips ipset.Interface) *NoMasqLocalTracker {
|
func NewNoMasqLocalTracker(ips ipset.Interface) *NoMasqLocalTracker {
|
||||||
return &NoMasqLocalTracker{
|
return &NoMasqLocalTracker{
|
||||||
ips: ips,
|
ips: ips,
|
||||||
owner: types.UID(0), // dummy ipset owner
|
owner: ipset.UID("0"), // dummy ipset owner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,9 +605,9 @@ func (t *NoMasqLocalTracker) HandleUpdate(prevRanges, currRanges []address.Range
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
prev, curr := tracker.RemoveCommon(
|
prev, curr := address.RemoveCommon(
|
||||||
address.NewCIDRs(tracker.Merge(prevRanges)),
|
address.NewCIDRs(address.Merge(prevRanges)),
|
||||||
address.NewCIDRs(tracker.Merge(currRanges)))
|
address.NewCIDRs(address.Merge(currRanges)))
|
||||||
|
|
||||||
for _, cidr := range curr {
|
for _, cidr := range curr {
|
||||||
if err := t.ips.AddEntry(t.owner, NoMasqLocalIpset, cidr.String(), ""); err != nil {
|
if err := t.ips.AddEntry(t.owner, NoMasqLocalIpset, cidr.String(), ""); err != nil {
|
||||||
@@ -609,7 +631,7 @@ func linkSetUpByName(linkName string) error {
|
|||||||
return netlink.LinkSetUp(link)
|
return netlink.LinkSetUp(link)
|
||||||
}
|
}
|
||||||
|
|
||||||
func reexpose(config *BridgeConfig, log *logrus.Logger) error {
|
func Reexpose(config *BridgeConfig, log *logrus.Logger) error {
|
||||||
// Get existing IP addrs of the weave bridge.
|
// Get existing IP addrs of the weave bridge.
|
||||||
// If the bridge hasn't been exposed, then this functions does nothing.
|
// If the bridge hasn't been exposed, then this functions does nothing.
|
||||||
//
|
//
|
||||||
|
|||||||
+2
-7
@@ -103,13 +103,8 @@ func addNatRule(ipt *iptables.IPTables, rulespec ...string) error {
|
|||||||
// Loop until we get an exit code other than "temporarily unavailable"
|
// Loop until we get an exit code other than "temporarily unavailable"
|
||||||
for {
|
for {
|
||||||
if err := ipt.AppendUnique("nat", "WEAVE", rulespec...); err != nil {
|
if err := ipt.AppendUnique("nat", "WEAVE", rulespec...); err != nil {
|
||||||
if ierr, ok := err.(*iptables.Error); ok {
|
if isResourceError(err) {
|
||||||
if status, ok := ierr.ExitError.Sys().(syscall.WaitStatus); ok {
|
continue
|
||||||
// (magic exit code 4 found in iptables source code; undocumented)
|
|
||||||
if status.ExitStatus() == 4 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -430,14 +430,6 @@ func (ipsec *IPSec) removeDropNonEncrypted(srcIP, dstIP net.IP, udpPort int, inS
|
|||||||
return ipsec.resetRules(rules, true)
|
return ipsec.resetRules(rules, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ipsec *IPSec) removeDropNonEncryptedInbound(srcIP, dstIP net.IP, inSPI SPI) error {
|
|
||||||
r := ruleMarkInboundESP(srcIP, dstIP, inSPI)
|
|
||||||
if err := ipsec.ipt.Delete(r.table, r.chain, r.rulespec...); err != nil {
|
|
||||||
return errors.Wrap(err, fmt.Sprintf("iptables delete unique (%s, %s, %s)", r.table, r.chain, r.rulespec))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// xfrm
|
// xfrm
|
||||||
|
|
||||||
func xfrmAllocSpiState(srcIP, dstIP net.IP) *netlink.XfrmState {
|
func xfrmAllocSpiState(srcIP, dstIP net.IP) *netlink.XfrmState {
|
||||||
|
|||||||
+46
-17
@@ -7,26 +7,31 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Name string
|
type Name string
|
||||||
|
|
||||||
type Type string
|
type Type string
|
||||||
|
|
||||||
|
type UID string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ListSet = Type("list:set")
|
ListSet = Type("list:set")
|
||||||
HashIP = Type("hash:ip")
|
HashIP = Type("hash:ip")
|
||||||
HashNet = Type("hash:net")
|
HashNet = Type("hash:net")
|
||||||
|
|
||||||
|
DestroyRetrySleepMs = 100
|
||||||
)
|
)
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
Create(ipsetName Name, ipsetType Type) error
|
Create(ipsetName Name, ipsetType Type) error
|
||||||
AddEntry(user types.UID, ipsetName Name, entry string, comment string) error
|
AddEntry(user UID, ipsetName Name, entry string, comment string) error
|
||||||
DelEntry(user types.UID, ipsetName Name, entry string) error
|
DelEntry(user UID, ipsetName Name, entry string) error
|
||||||
Exist(user types.UID, ipsetName Name, entry string) bool
|
EntryExists(user UID, ipsetName Name, entry string) bool
|
||||||
|
Exists(ipsetName Name) (bool, error)
|
||||||
Flush(ipsetName Name) error
|
Flush(ipsetName Name) error
|
||||||
Destroy(ipsetName Name) error
|
Destroy(ipsetName Name) error
|
||||||
|
|
||||||
@@ -49,7 +54,7 @@ type ipset struct {
|
|||||||
// There might be multiple users for the same ipset & entry pair because
|
// There might be multiple users for the same ipset & entry pair because
|
||||||
// events from k8s API server might be out of order causing duplicate IPs:
|
// events from k8s API server might be out of order causing duplicate IPs:
|
||||||
// https://github.com/weaveworks/weave/issues/2792.
|
// https://github.com/weaveworks/weave/issues/2792.
|
||||||
users map[entryKey]map[types.UID]struct{}
|
users map[entryKey]map[UID]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(logger *log.Logger, maxListSize int) Interface {
|
func New(logger *log.Logger, maxListSize int) Interface {
|
||||||
@@ -57,7 +62,7 @@ func New(logger *log.Logger, maxListSize int) Interface {
|
|||||||
Logger: logger,
|
Logger: logger,
|
||||||
enableComments: true,
|
enableComments: true,
|
||||||
maxListSize: maxListSize,
|
maxListSize: maxListSize,
|
||||||
users: make(map[entryKey]map[types.UID]struct{}),
|
users: make(map[entryKey]map[UID]struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for comment support
|
// Check for comment support
|
||||||
@@ -93,7 +98,7 @@ func (i *ipset) Create(ipsetName Name, ipsetType Type) error {
|
|||||||
return doExec(args...)
|
return doExec(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *ipset) AddEntry(user types.UID, ipsetName Name, entry string, comment string) error {
|
func (i *ipset) AddEntry(user UID, ipsetName Name, entry string, comment string) error {
|
||||||
i.Logger.Printf("adding entry %s to %s of %s", entry, ipsetName, user)
|
i.Logger.Printf("adding entry %s to %s of %s", entry, ipsetName, user)
|
||||||
|
|
||||||
if !i.addUser(user, ipsetName, entry) { // already in the set
|
if !i.addUser(user, ipsetName, entry) { // already in the set
|
||||||
@@ -109,7 +114,7 @@ func (i *ipset) AddEntry(user types.UID, ipsetName Name, entry string, comment s
|
|||||||
return doExec(args...)
|
return doExec(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *ipset) DelEntry(user types.UID, ipsetName Name, entry string) error {
|
func (i *ipset) DelEntry(user UID, ipsetName Name, entry string) error {
|
||||||
i.Logger.Printf("deleting entry %s from %s of %s", entry, ipsetName, user)
|
i.Logger.Printf("deleting entry %s from %s of %s", entry, ipsetName, user)
|
||||||
|
|
||||||
if !i.delUser(user, ipsetName, entry) { // still needed
|
if !i.delUser(user, ipsetName, entry) { // still needed
|
||||||
@@ -121,28 +126,52 @@ func (i *ipset) DelEntry(user types.UID, ipsetName Name, entry string) error {
|
|||||||
return doExec("del", string(ipsetName), entry)
|
return doExec("del", string(ipsetName), entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *ipset) Exist(user types.UID, ipsetName Name, entry string) bool {
|
func (i *ipset) EntryExists(user UID, ipsetName Name, entry string) bool {
|
||||||
return i.existUser(user, ipsetName, entry)
|
return i.existUser(user, ipsetName, entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dummy way to check whether a given ipset exists.
|
||||||
|
func (i *ipset) Exists(name Name) (bool, error) {
|
||||||
|
sets, err := i.List(string(name))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
for _, s := range sets {
|
||||||
|
if s == name {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (i *ipset) Flush(ipsetName Name) error {
|
func (i *ipset) Flush(ipsetName Name) error {
|
||||||
i.removeSetFromUsers(ipsetName)
|
i.removeSetFromUsers(ipsetName)
|
||||||
return doExec("flush", string(ipsetName))
|
return doExec("flush", string(ipsetName))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *ipset) FlushAll() error {
|
func (i *ipset) FlushAll() error {
|
||||||
i.users = make(map[entryKey]map[types.UID]struct{})
|
i.users = make(map[entryKey]map[UID]struct{})
|
||||||
return doExec("flush")
|
return doExec("flush")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *ipset) Destroy(ipsetName Name) error {
|
func (i *ipset) Destroy(ipsetName Name) error {
|
||||||
i.removeSetFromUsers(ipsetName)
|
i.removeSetFromUsers(ipsetName)
|
||||||
return doExec("destroy", string(ipsetName))
|
err := doExec("destroy", string(ipsetName))
|
||||||
|
if err != nil {
|
||||||
|
time.Sleep(DestroyRetrySleepMs * time.Millisecond)
|
||||||
|
return doExec("destroy", string(ipsetName))
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *ipset) DestroyAll() error {
|
func (i *ipset) DestroyAll() error {
|
||||||
i.users = make(map[entryKey]map[types.UID]struct{})
|
i.users = make(map[entryKey]map[UID]struct{})
|
||||||
return doExec("destroy")
|
err := doExec("destroy")
|
||||||
|
if err != nil {
|
||||||
|
time.Sleep(DestroyRetrySleepMs * time.Millisecond)
|
||||||
|
return doExec("destroy")
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch a list of all existing sets with a given prefix
|
// Fetch a list of all existing sets with a given prefix
|
||||||
@@ -164,12 +193,12 @@ func (i *ipset) List(prefix string) ([]Name, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if entry does not exist in ipset (entry has to be inserted into ipset).
|
// Returns true if entry does not exist in ipset (entry has to be inserted into ipset).
|
||||||
func (i *ipset) addUser(user types.UID, ipsetName Name, entry string) bool {
|
func (i *ipset) addUser(user UID, ipsetName Name, entry string) bool {
|
||||||
k := entryKey{ipsetName, entry}
|
k := entryKey{ipsetName, entry}
|
||||||
add := false
|
add := false
|
||||||
|
|
||||||
if i.users[k] == nil {
|
if i.users[k] == nil {
|
||||||
i.users[k] = make(map[types.UID]struct{})
|
i.users[k] = make(map[UID]struct{})
|
||||||
}
|
}
|
||||||
if len(i.users[k]) == 0 {
|
if len(i.users[k]) == 0 {
|
||||||
add = true
|
add = true
|
||||||
@@ -180,7 +209,7 @@ func (i *ipset) addUser(user types.UID, ipsetName Name, entry string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if user is the last owner of entry (entry has to be removed from ipset).
|
// Returns true if user is the last owner of entry (entry has to be removed from ipset).
|
||||||
func (i *ipset) delUser(user types.UID, ipsetName Name, entry string) bool {
|
func (i *ipset) delUser(user UID, ipsetName Name, entry string) bool {
|
||||||
k := entryKey{ipsetName, entry}
|
k := entryKey{ipsetName, entry}
|
||||||
|
|
||||||
oneLeft := len(i.users[k]) == 1
|
oneLeft := len(i.users[k]) == 1
|
||||||
@@ -193,7 +222,7 @@ func (i *ipset) delUser(user types.UID, ipsetName Name, entry string) bool {
|
|||||||
return oneLeft && (len(i.users[k]) == 0)
|
return oneLeft && (len(i.users[k]) == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *ipset) existUser(user types.UID, ipsetName Name, entry string) bool {
|
func (i *ipset) existUser(user UID, ipsetName Name, entry string) bool {
|
||||||
_, ok := i.users[entryKey{ipsetName, entry}][user]
|
_, ok := i.users[entryKey{ipsetName, entry}][user]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|||||||
+120
@@ -2,9 +2,13 @@ package net
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/coreos/go-iptables/iptables"
|
"github.com/coreos/go-iptables/iptables"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
utilwait "k8s.io/apimachinery/pkg/util/wait"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddChainWithRules creates a chain and appends given rules to it.
|
// AddChainWithRules creates a chain and appends given rules to it.
|
||||||
@@ -104,3 +108,119 @@ func ensureRulesAtTop(table, chain string, rulespecs [][]string, ipt *iptables.I
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func chainExists(ipt *iptables.IPTables, table string, chain string) (bool, error) {
|
||||||
|
existingChains, err := ipt.ListChains(table)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.Wrapf(err, "ipt.ListChains(%s)", table)
|
||||||
|
}
|
||||||
|
chainMap := make(map[string]struct{})
|
||||||
|
for _, c := range existingChains {
|
||||||
|
chainMap[c] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, found := chainMap[chain]
|
||||||
|
return found, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Max time we wait for an iptables flush to complete after we notice it has started
|
||||||
|
iptablesFlushTimeout = 5 * time.Second
|
||||||
|
// How often we poll while waiting for an iptables flush to complete
|
||||||
|
iptablesFlushPollTime = 100 * time.Millisecond
|
||||||
|
)
|
||||||
|
|
||||||
|
// MonitorForIptablesFlush periodically checks for a canary chain in iptables. If this canary chain goes missing it calls the reloadFunc.
|
||||||
|
// This is a more efficient way of detecting whether firewalld or another process has been removing rules that we rely on.
|
||||||
|
// The reloadFunc can then check whether other chains that should exist are still there, fix things and restore the canary.
|
||||||
|
func MonitorForIptablesFlush(log *logrus.Logger, canary string, tables []string, reloadFunc func(), interval time.Duration, stopCh <-chan struct{}) {
|
||||||
|
ipt, err := iptables.New()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("creating iptables object while initializing iptable Monitoring %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
_ = PollImmediateUntil(interval, func() (bool, error) {
|
||||||
|
for _, table := range tables {
|
||||||
|
if err := ensureChains(ipt, table, canary); err != nil {
|
||||||
|
log.Warningf("Could not set up iptables canary %s/%s: %v", table, canary, err)
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}, stopCh)
|
||||||
|
|
||||||
|
// Poll until stopCh is closed or iptables is flushed
|
||||||
|
err = utilwait.PollUntil(interval, func() (bool, error) {
|
||||||
|
if exists, err := chainExists(ipt, tables[0], canary); exists {
|
||||||
|
return false, nil
|
||||||
|
} else if isResourceError(err) {
|
||||||
|
log.Warningf("Could not check for iptables canary %s/%s: %v", tables[0], canary, err)
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
log.Infof("iptables canary %s/%s deleted", tables[0], canary)
|
||||||
|
|
||||||
|
// Wait for the other canaries to be deleted too before returning
|
||||||
|
// so we don't start reloading too soon.
|
||||||
|
err := utilwait.PollImmediate(iptablesFlushPollTime, iptablesFlushTimeout, func() (bool, error) {
|
||||||
|
for i := 1; i < len(tables); i++ {
|
||||||
|
if exists, err := chainExists(ipt, tables[i], canary); exists || isResourceError(err) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Warning("Inconsistent iptables state detected.")
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}, stopCh)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// stopCh was closed
|
||||||
|
for _, table := range tables {
|
||||||
|
_ = ipt.DeleteChain(table, canary)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Reloading after iptables flush")
|
||||||
|
reloadFunc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const iptablesStatusResourceProblem = 4
|
||||||
|
|
||||||
|
// isResourceError returns true if the error indicates that iptables ran into a "resource
|
||||||
|
// problem" and was unable to attempt the request. In particular, this will be true if it
|
||||||
|
// times out trying to get the iptables lock.
|
||||||
|
func isResourceError(err error) bool {
|
||||||
|
if ierr, ok := err.(*iptables.Error); ok {
|
||||||
|
if status, ok := ierr.ExitError.Sys().(syscall.WaitStatus); ok {
|
||||||
|
return status.ExitStatus() == iptablesStatusResourceProblem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// PollImmediateUntil tries a condition func until it returns true, an error or stopCh is closed.
|
||||||
|
//
|
||||||
|
// PollImmediateUntil runs the 'condition' before waiting for the interval.
|
||||||
|
// 'condition' will always be invoked at least once.
|
||||||
|
func PollImmediateUntil(interval time.Duration, condition utilwait.ConditionFunc, stopCh <-chan struct{}) error {
|
||||||
|
done, err := condition()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if done {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-stopCh:
|
||||||
|
return utilwait.ErrWaitTimeout
|
||||||
|
default:
|
||||||
|
return utilwait.PollUntil(interval, condition, stopCh)
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -50,10 +50,10 @@ func CreateAndAttachVeth(procPath, name, peerName, bridgeName string, mtu int, k
|
|||||||
return cleanup("attaching veth %q to %q: %s", name, bridgeName, err)
|
return cleanup("attaching veth %q to %q: %s", name, bridgeName, err)
|
||||||
}
|
}
|
||||||
// No ipv6 router advertisments please
|
// No ipv6 router advertisments please
|
||||||
if err := sysctl(procPath, "net/ipv6/conf/"+name+"/accept_ra", "0"); err != nil {
|
if err := sysctlIfExists(procPath, "net/ipv6/conf/"+name+"/accept_ra", "0"); err != nil {
|
||||||
return cleanup("setting accept_ra to 0: %s", err)
|
return cleanup("setting accept_ra to 0: %s", err)
|
||||||
}
|
}
|
||||||
if err := sysctl(procPath, "net/ipv6/conf/"+peerName+"/accept_ra", "0"); err != nil {
|
if err := sysctlIfExists(procPath, "net/ipv6/conf/"+peerName+"/accept_ra", "0"); err != nil {
|
||||||
return cleanup("setting accept_ra to 0: %s", err)
|
return cleanup("setting accept_ra to 0: %s", err)
|
||||||
}
|
}
|
||||||
if !bridgeType.IsFastdp() && !keepTXOn {
|
if !bridgeType.IsFastdp() && !keepTXOn {
|
||||||
|
|||||||
+1
-10
@@ -2,16 +2,7 @@ package npc
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
TableFilter = "filter"
|
TableFilter = "filter"
|
||||||
|
EgressMark = "0x40000/0x40000"
|
||||||
MainChain = "WEAVE-NPC"
|
|
||||||
DefaultChain = "WEAVE-NPC-DEFAULT"
|
|
||||||
IngressChain = "WEAVE-NPC-INGRESS"
|
|
||||||
|
|
||||||
EgressChain = "WEAVE-NPC-EGRESS"
|
|
||||||
EgressDefaultChain = "WEAVE-NPC-EGRESS-DEFAULT"
|
|
||||||
EgressCustomChain = "WEAVE-NPC-EGRESS-CUSTOM"
|
|
||||||
EgressMarkChain = "WEAVE-NPC-EGRESS-ACCEPT"
|
|
||||||
EgressMark = "0x40000/0x40000"
|
|
||||||
|
|
||||||
IpsetNamePrefix = "weave-"
|
IpsetNamePrefix = "weave-"
|
||||||
|
|
||||||
|
|||||||
+51
-38
@@ -1,6 +1,7 @@
|
|||||||
package npc
|
package npc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -12,22 +13,23 @@ import (
|
|||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/weaveworks/weave/common"
|
||||||
|
"github.com/weaveworks/weave/common/chains"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/weaveworks/weave/net/ipset"
|
||||||
"github.com/weaveworks/weave/npc/iptables"
|
"github.com/weaveworks/weave/npc/iptables"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NetworkPolicyController interface {
|
type NetworkPolicyController interface {
|
||||||
AddNamespace(ns *coreapi.Namespace) error
|
AddNamespace(ctx context.Context, ns *coreapi.Namespace) error
|
||||||
UpdateNamespace(oldObj, newObj *coreapi.Namespace) error
|
UpdateNamespace(ctx context.Context, oldObj, newObj *coreapi.Namespace) error
|
||||||
DeleteNamespace(ns *coreapi.Namespace) error
|
DeleteNamespace(ctx context.Context, ns *coreapi.Namespace) error
|
||||||
|
|
||||||
AddPod(obj *coreapi.Pod) error
|
AddPod(ctx context.Context, obj *coreapi.Pod) error
|
||||||
UpdatePod(oldObj, newObj *coreapi.Pod) error
|
UpdatePod(ctx context.Context, oldObj, newObj *coreapi.Pod) error
|
||||||
DeletePod(obj *coreapi.Pod) error
|
DeletePod(ctx context.Context, obj *coreapi.Pod) error
|
||||||
|
|
||||||
AddNetworkPolicy(obj interface{}) error
|
AddNetworkPolicy(ctx context.Context, obj interface{}) error
|
||||||
UpdateNetworkPolicy(oldObj, newObj interface{}) error
|
UpdateNetworkPolicy(ctx context.Context, oldObj, newObj interface{}) error
|
||||||
DeleteNetworkPolicy(obj interface{}) error
|
DeleteNetworkPolicy(ctx context.Context, obj interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type controller struct {
|
type controller struct {
|
||||||
@@ -60,9 +62,9 @@ func New(nodeName string, ipt iptables.Interface, ips ipset.Interface, clientset
|
|||||||
|
|
||||||
func (npc *controller) onNewNsSelector(selector *selector) error {
|
func (npc *controller) onNewNsSelector(selector *selector) error {
|
||||||
for _, ns := range npc.nss {
|
for _, ns := range npc.nss {
|
||||||
if ns.namespace != nil {
|
if ns.namespaceUID != "" {
|
||||||
if selector.matchesNamespaceSelector(ns.namespace.ObjectMeta.Labels) {
|
if selector.matchesNamespaceSelector(ns.namespaceLabels) {
|
||||||
if err := selector.addEntry(ns.namespace.ObjectMeta.UID, string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil {
|
if err := selector.addEntry(ns.namespaceUID, string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,11 +75,11 @@ func (npc *controller) onNewNsSelector(selector *selector) error {
|
|||||||
|
|
||||||
func (npc *controller) onNewNamespacePodsSelector(selector *selector) error {
|
func (npc *controller) onNewNamespacePodsSelector(selector *selector) error {
|
||||||
for _, ns := range npc.nss {
|
for _, ns := range npc.nss {
|
||||||
if ns.namespace != nil && len(ns.pods) > 0 {
|
if ns.namespaceUID != "" && len(ns.pods) > 0 {
|
||||||
for _, pod := range ns.pods {
|
for _, pod := range ns.pods {
|
||||||
if hasIP(pod) {
|
if hasIP(pod) {
|
||||||
if selector.matchesNamespacedPodSelector(pod.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels) {
|
if selector.matchesNamespacedPodSelector(pod.ObjectMeta.Labels, ns.namespaceLabels) {
|
||||||
if err := selector.addEntry(pod.ObjectMeta.UID, pod.Status.PodIP, podComment(pod)); err != nil {
|
if err := selector.addEntry(uid(pod), pod.Status.PodIP, podComment(pod)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,10 +91,10 @@ func (npc *controller) onNewNamespacePodsSelector(selector *selector) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (npc *controller) withNS(name string, f func(ns *ns) error) error {
|
func (npc *controller) withNS(ctx context.Context, name string, f func(ns *ns) error) error {
|
||||||
ns, found := npc.nss[name]
|
ns, found := npc.nss[name]
|
||||||
if !found {
|
if !found {
|
||||||
namespace, err := npc.clientset.CoreV1().Namespaces().Get(name, metav1.GetOptions{})
|
namespace, err := npc.clientset.CoreV1().Namespaces().Get(ctx, name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -115,37 +117,37 @@ func (npc *controller) withNS(name string, f func(ns *ns) error) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (npc *controller) AddPod(obj *coreapi.Pod) error {
|
func (npc *controller) AddPod(ctx context.Context, obj *coreapi.Pod) error {
|
||||||
npc.Lock()
|
npc.Lock()
|
||||||
defer npc.Unlock()
|
defer npc.Unlock()
|
||||||
|
|
||||||
common.Log.Debugf("EVENT AddPod %s", js(obj))
|
common.Log.Debugf("EVENT AddPod %s", js(obj))
|
||||||
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
|
return npc.withNS(ctx, obj.ObjectMeta.Namespace, func(ns *ns) error {
|
||||||
return errors.Wrap(ns.addPod(obj), "add pod")
|
return errors.Wrap(ns.addPod(obj), "add pod")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (npc *controller) UpdatePod(oldObj, newObj *coreapi.Pod) error {
|
func (npc *controller) UpdatePod(ctx context.Context, oldObj, newObj *coreapi.Pod) error {
|
||||||
npc.Lock()
|
npc.Lock()
|
||||||
defer npc.Unlock()
|
defer npc.Unlock()
|
||||||
|
|
||||||
common.Log.Debugf("EVENT UpdatePod %s %s", js(oldObj), js(newObj))
|
common.Log.Debugf("EVENT UpdatePod %s %s", js(oldObj), js(newObj))
|
||||||
return npc.withNS(oldObj.ObjectMeta.Namespace, func(ns *ns) error {
|
return npc.withNS(ctx, oldObj.ObjectMeta.Namespace, func(ns *ns) error {
|
||||||
return errors.Wrap(ns.updatePod(oldObj, newObj), "update pod")
|
return errors.Wrap(ns.updatePod(oldObj, newObj), "update pod")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (npc *controller) DeletePod(obj *coreapi.Pod) error {
|
func (npc *controller) DeletePod(ctx context.Context, obj *coreapi.Pod) error {
|
||||||
npc.Lock()
|
npc.Lock()
|
||||||
defer npc.Unlock()
|
defer npc.Unlock()
|
||||||
|
|
||||||
common.Log.Debugf("EVENT DeletePod %s", js(obj))
|
common.Log.Debugf("EVENT DeletePod %s", js(obj))
|
||||||
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
|
return npc.withNS(ctx, obj.ObjectMeta.Namespace, func(ns *ns) error {
|
||||||
return errors.Wrap(ns.deletePod(obj), "delete pod")
|
return errors.Wrap(ns.deletePod(obj), "delete pod")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (npc *controller) AddNetworkPolicy(obj interface{}) error {
|
func (npc *controller) AddNetworkPolicy(ctx context.Context, obj interface{}) error {
|
||||||
npc.Lock()
|
npc.Lock()
|
||||||
defer npc.Unlock()
|
defer npc.Unlock()
|
||||||
|
|
||||||
@@ -156,12 +158,15 @@ func (npc *controller) AddNetworkPolicy(obj interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if egressNetworkPolicy {
|
if egressNetworkPolicy {
|
||||||
npc.defaultEgressDrop = true
|
if err := npc.ipt.Append(TableFilter, chains.EgressChain,
|
||||||
if err := npc.ipt.Append(TableFilter, EgressChain,
|
"-m", "state", "--state", "NEW", "-m", "mark", "!", "--mark", EgressMark, "-j", "NFLOG", "--nflog-group", "86"); err != nil {
|
||||||
|
return fmt.Errorf("Failed to add iptable egress log rule: %w", err)
|
||||||
|
}
|
||||||
|
if err := npc.ipt.Append(TableFilter, chains.EgressChain,
|
||||||
"-m", "mark", "!", "--mark", EgressMark, "-j", "DROP"); err != nil {
|
"-m", "mark", "!", "--mark", EgressMark, "-j", "DROP"); err != nil {
|
||||||
npc.defaultEgressDrop = false
|
|
||||||
return fmt.Errorf("Failed to add iptable rule to drop egress traffic from the pods by default due to %s", err.Error())
|
return fmt.Errorf("Failed to add iptable rule to drop egress traffic from the pods by default due to %s", err.Error())
|
||||||
}
|
}
|
||||||
|
npc.defaultEgressDrop = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,12 +175,12 @@ func (npc *controller) AddNetworkPolicy(obj interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
common.Log.Infof("EVENT AddNetworkPolicy %s", js(obj))
|
common.Log.Infof("EVENT AddNetworkPolicy %s", js(obj))
|
||||||
return npc.withNS(nsName, func(ns *ns) error {
|
return npc.withNS(ctx, nsName, func(ns *ns) error {
|
||||||
return errors.Wrap(ns.addNetworkPolicy(obj), "add network policy")
|
return errors.Wrap(ns.addNetworkPolicy(obj), "add network policy")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (npc *controller) UpdateNetworkPolicy(oldObj, newObj interface{}) error {
|
func (npc *controller) UpdateNetworkPolicy(ctx context.Context, oldObj, newObj interface{}) error {
|
||||||
npc.Lock()
|
npc.Lock()
|
||||||
defer npc.Unlock()
|
defer npc.Unlock()
|
||||||
|
|
||||||
@@ -185,12 +190,12 @@ func (npc *controller) UpdateNetworkPolicy(oldObj, newObj interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
common.Log.Infof("EVENT UpdateNetworkPolicy %s %s", js(oldObj), js(newObj))
|
common.Log.Infof("EVENT UpdateNetworkPolicy %s %s", js(oldObj), js(newObj))
|
||||||
return npc.withNS(nsName, func(ns *ns) error {
|
return npc.withNS(ctx, nsName, func(ns *ns) error {
|
||||||
return errors.Wrap(ns.updateNetworkPolicy(oldObj, newObj), "update network policy")
|
return errors.Wrap(ns.updateNetworkPolicy(oldObj, newObj), "update network policy")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (npc *controller) DeleteNetworkPolicy(obj interface{}) error {
|
func (npc *controller) DeleteNetworkPolicy(ctx context.Context, obj interface{}) error {
|
||||||
npc.Lock()
|
npc.Lock()
|
||||||
defer npc.Unlock()
|
defer npc.Unlock()
|
||||||
|
|
||||||
@@ -200,37 +205,37 @@ func (npc *controller) DeleteNetworkPolicy(obj interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
common.Log.Infof("EVENT DeleteNetworkPolicy %s", js(obj))
|
common.Log.Infof("EVENT DeleteNetworkPolicy %s", js(obj))
|
||||||
return npc.withNS(nsName, func(ns *ns) error {
|
return npc.withNS(ctx, nsName, func(ns *ns) error {
|
||||||
return errors.Wrap(ns.deleteNetworkPolicy(obj), "delete network policy")
|
return errors.Wrap(ns.deleteNetworkPolicy(obj), "delete network policy")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (npc *controller) AddNamespace(obj *coreapi.Namespace) error {
|
func (npc *controller) AddNamespace(ctx context.Context, obj *coreapi.Namespace) error {
|
||||||
npc.Lock()
|
npc.Lock()
|
||||||
defer npc.Unlock()
|
defer npc.Unlock()
|
||||||
|
|
||||||
common.Log.Infof("EVENT AddNamespace %s", js(obj))
|
common.Log.Infof("EVENT AddNamespace %s", js(obj))
|
||||||
return npc.withNS(obj.ObjectMeta.Name, func(ns *ns) error {
|
return npc.withNS(ctx, obj.ObjectMeta.Name, func(ns *ns) error {
|
||||||
return errors.Wrap(ns.addNamespace(obj), "add namespace")
|
return errors.Wrap(ns.addNamespace(obj), "add namespace")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (npc *controller) UpdateNamespace(oldObj, newObj *coreapi.Namespace) error {
|
func (npc *controller) UpdateNamespace(ctx context.Context, oldObj, newObj *coreapi.Namespace) error {
|
||||||
npc.Lock()
|
npc.Lock()
|
||||||
defer npc.Unlock()
|
defer npc.Unlock()
|
||||||
|
|
||||||
common.Log.Infof("EVENT UpdateNamespace %s %s", js(oldObj), js(newObj))
|
common.Log.Infof("EVENT UpdateNamespace %s %s", js(oldObj), js(newObj))
|
||||||
return npc.withNS(oldObj.ObjectMeta.Name, func(ns *ns) error {
|
return npc.withNS(ctx, oldObj.ObjectMeta.Name, func(ns *ns) error {
|
||||||
return errors.Wrap(ns.updateNamespace(oldObj, newObj), "update namespace")
|
return errors.Wrap(ns.updateNamespace(oldObj, newObj), "update namespace")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (npc *controller) DeleteNamespace(obj *coreapi.Namespace) error {
|
func (npc *controller) DeleteNamespace(ctx context.Context, obj *coreapi.Namespace) error {
|
||||||
npc.Lock()
|
npc.Lock()
|
||||||
defer npc.Unlock()
|
defer npc.Unlock()
|
||||||
|
|
||||||
common.Log.Infof("EVENT DeleteNamespace %s", js(obj))
|
common.Log.Infof("EVENT DeleteNamespace %s", js(obj))
|
||||||
return npc.withNS(obj.ObjectMeta.Name, func(ns *ns) error {
|
return npc.withNS(ctx, obj.ObjectMeta.Name, func(ns *ns) error {
|
||||||
return errors.Wrap(ns.deleteNamespace(obj), "delete namespace")
|
return errors.Wrap(ns.deleteNamespace(obj), "delete namespace")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -262,3 +267,11 @@ func isEgressNetworkPolicy(obj interface{}) (bool, error) {
|
|||||||
}
|
}
|
||||||
return false, errInvalidNetworkPolicyObjType
|
return false, errInvalidNetworkPolicyObjType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func uid(pod *coreapi.Pod) ipset.UID {
|
||||||
|
return ipset.UID(pod.UID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func nsuid(ns *coreapi.Namespace) ipset.UID {
|
||||||
|
return ipset.UID(ns.UID)
|
||||||
|
}
|
||||||
+113
-93
@@ -1,6 +1,7 @@
|
|||||||
package npc
|
package npc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -8,11 +9,11 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/weaveworks/weave/common/chains"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/weaveworks/weave/net/ipset"
|
||||||
coreapi "k8s.io/api/core/v1"
|
coreapi "k8s.io/api/core/v1"
|
||||||
networkingv1 "k8s.io/api/networking/v1"
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
)
|
)
|
||||||
@@ -20,7 +21,7 @@ import (
|
|||||||
type mockSet struct {
|
type mockSet struct {
|
||||||
name ipset.Name
|
name ipset.Name
|
||||||
setType ipset.Type
|
setType ipset.Type
|
||||||
subSets map[string]map[types.UID]bool
|
subSets map[string]map[ipset.UID]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockIPSet struct {
|
type mockIPSet struct {
|
||||||
@@ -35,17 +36,17 @@ func (i *mockIPSet) Create(ipsetName ipset.Name, ipsetType ipset.Type) error {
|
|||||||
if _, ok := i.sets[string(ipsetName)]; ok {
|
if _, ok := i.sets[string(ipsetName)]; ok {
|
||||||
return errors.Errorf("ipset %s already exists", ipsetName)
|
return errors.Errorf("ipset %s already exists", ipsetName)
|
||||||
}
|
}
|
||||||
i.sets[string(ipsetName)] = mockSet{name: ipsetName, setType: ipsetType, subSets: make(map[string]map[types.UID]bool)}
|
i.sets[string(ipsetName)] = mockSet{name: ipsetName, setType: ipsetType, subSets: make(map[string]map[ipset.UID]bool)}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *mockIPSet) AddEntry(user types.UID, ipsetName ipset.Name, entry string, comment string) error {
|
func (i *mockIPSet) AddEntry(user ipset.UID, ipsetName ipset.Name, entry string, comment string) error {
|
||||||
log.Printf("adding entry %s to %s for %s", entry, ipsetName, user)
|
log.Printf("adding entry %s to %s for %s", entry, ipsetName, user)
|
||||||
if _, ok := i.sets[string(ipsetName)]; !ok {
|
if _, ok := i.sets[string(ipsetName)]; !ok {
|
||||||
return errors.Errorf("%s does not exist", entry)
|
return errors.Errorf("%s does not exist", entry)
|
||||||
}
|
}
|
||||||
if i.sets[string(ipsetName)].subSets[entry] == nil {
|
if i.sets[string(ipsetName)].subSets[entry] == nil {
|
||||||
i.sets[string(ipsetName)].subSets[entry] = make(map[types.UID]bool)
|
i.sets[string(ipsetName)].subSets[entry] = make(map[ipset.UID]bool)
|
||||||
}
|
}
|
||||||
if _, ok := i.sets[string(ipsetName)].subSets[entry][user]; ok {
|
if _, ok := i.sets[string(ipsetName)].subSets[entry][user]; ok {
|
||||||
return errors.Errorf("user %s already owns entry %s", user, entry)
|
return errors.Errorf("user %s already owns entry %s", user, entry)
|
||||||
@@ -55,7 +56,7 @@ func (i *mockIPSet) AddEntry(user types.UID, ipsetName ipset.Name, entry string,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *mockIPSet) DelEntry(user types.UID, ipsetName ipset.Name, entry string) error {
|
func (i *mockIPSet) DelEntry(user ipset.UID, ipsetName ipset.Name, entry string) error {
|
||||||
log.Printf("deleting entry %s from %s for %s", entry, ipsetName, user)
|
log.Printf("deleting entry %s from %s for %s", entry, ipsetName, user)
|
||||||
if _, ok := i.sets[string(ipsetName)]; !ok {
|
if _, ok := i.sets[string(ipsetName)]; !ok {
|
||||||
return errors.Errorf("ipset %s does not exist", ipsetName)
|
return errors.Errorf("ipset %s does not exist", ipsetName)
|
||||||
@@ -72,12 +73,17 @@ func (i *mockIPSet) DelEntry(user types.UID, ipsetName ipset.Name, entry string)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *mockIPSet) Exist(user types.UID, ipsetName ipset.Name, entry string) bool {
|
func (i *mockIPSet) EntryExists(user ipset.UID, ipsetName ipset.Name, entry string) bool {
|
||||||
_, ok := i.sets[string(ipsetName)].subSets[entry][user]
|
_, ok := i.sets[string(ipsetName)].subSets[entry][user]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *mockIPSet) entryExists(ipsetName ipset.Name, entry string) bool {
|
func (i *mockIPSet) Exists(ipsetName ipset.Name) (bool, error) {
|
||||||
|
_, ok := i.sets[string(ipsetName)]
|
||||||
|
return ok, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *mockIPSet) entriesExist(ipsetName ipset.Name, entry string) bool {
|
||||||
return len(i.sets[string(ipsetName)].subSets[entry]) > 0
|
return len(i.sets[string(ipsetName)].subSets[entry]) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,6 +161,7 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
|
|||||||
sourceNamespace := &coreapi.Namespace{
|
sourceNamespace := &coreapi.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "source",
|
Name: "source",
|
||||||
|
UID: "source",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"app": "source",
|
"app": "source",
|
||||||
},
|
},
|
||||||
@@ -164,6 +171,7 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
|
|||||||
destinationNamespace := &coreapi.Namespace{
|
destinationNamespace := &coreapi.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "destination",
|
Name: "destination",
|
||||||
|
UID: "destination",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,19 +208,20 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
|
|||||||
// Namespaces first
|
// Namespaces first
|
||||||
m := newMockIPSet()
|
m := newMockIPSet()
|
||||||
client := fake.NewSimpleClientset()
|
client := fake.NewSimpleClientset()
|
||||||
|
ctx := context.Background()
|
||||||
controller := New("foo", newMockIPTables(), &m, client)
|
controller := New("foo", newMockIPTables(), &m, client)
|
||||||
client.CoreV1().Namespaces().Create(sourceNamespace)
|
client.CoreV1().Namespaces().Create(ctx, sourceNamespace, metav1.CreateOptions{})
|
||||||
client.CoreV1().Namespaces().Create(destinationNamespace)
|
client.CoreV1().Namespaces().Create(ctx, destinationNamespace, metav1.CreateOptions{})
|
||||||
|
|
||||||
const (
|
const (
|
||||||
selectorIPSetName = "weave-I239Zp%sCvoVt*D6u=A!2]YEk"
|
selectorIPSetName = "weave-I239Zp%sCvoVt*D6u=A!2]YEk"
|
||||||
sourceIPSetName = "weave-HboJG1fGgG]/SR%k9H#hv5e96"
|
sourceIPSetName = "weave-HboJG1fGgG]/SR%k9H#hv5e96"
|
||||||
)
|
)
|
||||||
|
|
||||||
controller.AddNamespace(sourceNamespace)
|
controller.AddNamespace(ctx, sourceNamespace)
|
||||||
controller.AddNamespace(destinationNamespace)
|
controller.AddNamespace(ctx, destinationNamespace)
|
||||||
|
|
||||||
controller.AddNetworkPolicy(networkPolicy)
|
controller.AddNetworkPolicy(ctx, networkPolicy)
|
||||||
|
|
||||||
require.Equal(t, true, len(m.sets[selectorIPSetName].subSets[sourceIPSetName]) > 0)
|
require.Equal(t, true, len(m.sets[selectorIPSetName].subSets[sourceIPSetName]) > 0)
|
||||||
|
|
||||||
@@ -220,10 +229,10 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
|
|||||||
m = newMockIPSet()
|
m = newMockIPSet()
|
||||||
controller = New("foo", newMockIPTables(), &m, &fake.Clientset{})
|
controller = New("foo", newMockIPTables(), &m, &fake.Clientset{})
|
||||||
|
|
||||||
controller.AddNetworkPolicy(networkPolicy)
|
controller.AddNetworkPolicy(ctx, networkPolicy)
|
||||||
|
|
||||||
controller.AddNamespace(sourceNamespace)
|
controller.AddNamespace(ctx, sourceNamespace)
|
||||||
controller.AddNamespace(destinationNamespace)
|
controller.AddNamespace(ctx, destinationNamespace)
|
||||||
|
|
||||||
require.Equal(t, true, len(m.sets[selectorIPSetName].subSets[sourceIPSetName]) > 0)
|
require.Equal(t, true, len(m.sets[selectorIPSetName].subSets[sourceIPSetName]) > 0)
|
||||||
}
|
}
|
||||||
@@ -241,12 +250,14 @@ func TestDefaultAllow(t *testing.T) {
|
|||||||
m := newMockIPSet()
|
m := newMockIPSet()
|
||||||
controller := New("bar", newMockIPTables(), &m, &fake.Clientset{})
|
controller := New("bar", newMockIPTables(), &m, &fake.Clientset{})
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
defaultNamespace := &coreapi.Namespace{
|
defaultNamespace := &coreapi.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "default",
|
Name: "default",
|
||||||
|
UID: "default",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
controller.AddNamespace(defaultNamespace)
|
controller.AddNamespace(ctx, defaultNamespace)
|
||||||
|
|
||||||
// Should create an ipset for default-allow
|
// Should create an ipset for default-allow
|
||||||
require.Contains(t, m.sets, ingressDefaultAllowIPSetName)
|
require.Contains(t, m.sets, ingressDefaultAllowIPSetName)
|
||||||
@@ -259,11 +270,11 @@ func TestDefaultAllow(t *testing.T) {
|
|||||||
Name: "foo",
|
Name: "foo",
|
||||||
Labels: map[string]string{"run": "foo"}},
|
Labels: map[string]string{"run": "foo"}},
|
||||||
Status: coreapi.PodStatus{PodIP: fooPodIP}}
|
Status: coreapi.PodStatus{PodIP: fooPodIP}}
|
||||||
controller.AddPod(podFoo)
|
controller.AddPod(ctx, podFoo)
|
||||||
|
|
||||||
// Should add the foo pod to default-allow
|
// Should add the foo pod to default-allow
|
||||||
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, fooPodIP))
|
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, fooPodIP))
|
||||||
require.True(t, m.entryExists(egressDefaultAllowIPSetName, fooPodIP))
|
require.True(t, m.entriesExist(egressDefaultAllowIPSetName, fooPodIP))
|
||||||
|
|
||||||
podBar := &coreapi.Pod{
|
podBar := &coreapi.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -273,13 +284,13 @@ func TestDefaultAllow(t *testing.T) {
|
|||||||
Labels: map[string]string{"run": "bar"}},
|
Labels: map[string]string{"run": "bar"}},
|
||||||
Status: coreapi.PodStatus{PodIP: barPodIP}}
|
Status: coreapi.PodStatus{PodIP: barPodIP}}
|
||||||
podBarNoIP := &coreapi.Pod{ObjectMeta: podBar.ObjectMeta}
|
podBarNoIP := &coreapi.Pod{ObjectMeta: podBar.ObjectMeta}
|
||||||
controller.AddPod(podBarNoIP)
|
controller.AddPod(ctx, podBarNoIP)
|
||||||
|
|
||||||
controller.UpdatePod(podBarNoIP, podBar)
|
controller.UpdatePod(ctx, podBarNoIP, podBar)
|
||||||
|
|
||||||
// Should add the bar pod to default-allow
|
// Should add the bar pod to default-allow
|
||||||
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, barPodIP))
|
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, barPodIP))
|
||||||
require.True(t, m.entryExists(egressDefaultAllowIPSetName, barPodIP))
|
require.True(t, m.entriesExist(egressDefaultAllowIPSetName, barPodIP))
|
||||||
|
|
||||||
// Allow access from the bar pod to the foo pod
|
// Allow access from the bar pod to the foo pod
|
||||||
netpol := &networkingv1.NetworkPolicy{
|
netpol := &networkingv1.NetworkPolicy{
|
||||||
@@ -307,53 +318,53 @@ func TestDefaultAllow(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
controller.AddNetworkPolicy(netpol)
|
controller.AddNetworkPolicy(ctx, netpol)
|
||||||
|
|
||||||
// Should remove the foo pod from default-allow as the netpol selects it
|
// Should remove the foo pod from default-allow as the netpol selects it
|
||||||
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, fooPodIP))
|
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, fooPodIP))
|
||||||
require.False(t, m.entryExists(egressDefaultAllowIPSetName, fooPodIP))
|
require.False(t, m.entriesExist(egressDefaultAllowIPSetName, fooPodIP))
|
||||||
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, barPodIP))
|
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, barPodIP))
|
||||||
require.True(t, m.entryExists(egressDefaultAllowIPSetName, barPodIP))
|
require.True(t, m.entriesExist(egressDefaultAllowIPSetName, barPodIP))
|
||||||
|
|
||||||
podBarWithNewIP := *podBar
|
podBarWithNewIP := *podBar
|
||||||
podBarWithNewIP.Status.PodIP = barPodNewIP
|
podBarWithNewIP.Status.PodIP = barPodNewIP
|
||||||
controller.UpdatePod(podBar, &podBarWithNewIP)
|
controller.UpdatePod(ctx, podBar, &podBarWithNewIP)
|
||||||
|
|
||||||
// Should update IP addr of the bar pod in default-allow
|
// Should update IP addr of the bar pod in default-allow
|
||||||
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, barPodIP))
|
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, barPodIP))
|
||||||
require.False(t, m.entryExists(egressDefaultAllowIPSetName, barPodIP))
|
require.False(t, m.entriesExist(egressDefaultAllowIPSetName, barPodIP))
|
||||||
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, barPodNewIP))
|
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, barPodNewIP))
|
||||||
require.True(t, m.entryExists(egressDefaultAllowIPSetName, barPodNewIP))
|
require.True(t, m.entriesExist(egressDefaultAllowIPSetName, barPodNewIP))
|
||||||
|
|
||||||
controller.UpdatePod(&podBarWithNewIP, podBarNoIP)
|
controller.UpdatePod(ctx, &podBarWithNewIP, podBarNoIP)
|
||||||
// Should remove the bar pod from default-allow as it does not have any IP addr
|
// Should remove the bar pod from default-allow as it does not have any IP addr
|
||||||
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, barPodNewIP))
|
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, barPodNewIP))
|
||||||
require.False(t, m.entryExists(egressDefaultAllowIPSetName, barPodNewIP))
|
require.False(t, m.entriesExist(egressDefaultAllowIPSetName, barPodNewIP))
|
||||||
|
|
||||||
podFooWithNewLabel := *podFoo
|
podFooWithNewLabel := *podFoo
|
||||||
podFooWithNewLabel.ObjectMeta.Labels = map[string]string{"run": "new-foo"}
|
podFooWithNewLabel.ObjectMeta.Labels = map[string]string{"run": "new-foo"}
|
||||||
controller.UpdatePod(podFoo, &podFooWithNewLabel)
|
controller.UpdatePod(ctx, podFoo, &podFooWithNewLabel)
|
||||||
|
|
||||||
// Should bring back the foo pod to default-allow as it does not match dst of any netpol
|
// Should bring back the foo pod to default-allow as it does not match dst of any netpol
|
||||||
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, fooPodIP))
|
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, fooPodIP))
|
||||||
require.True(t, m.entryExists(egressDefaultAllowIPSetName, fooPodIP))
|
require.True(t, m.entriesExist(egressDefaultAllowIPSetName, fooPodIP))
|
||||||
|
|
||||||
controller.UpdatePod(&podFooWithNewLabel, podFoo)
|
controller.UpdatePod(ctx, &podFooWithNewLabel, podFoo)
|
||||||
// Should remove from default-allow as it matches the netpol after the update
|
// Should remove from default-allow as it matches the netpol after the update
|
||||||
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, fooPodIP))
|
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, fooPodIP))
|
||||||
require.False(t, m.entryExists(egressDefaultAllowIPSetName, fooPodIP))
|
require.False(t, m.entriesExist(egressDefaultAllowIPSetName, fooPodIP))
|
||||||
|
|
||||||
controller.DeleteNetworkPolicy(netpol)
|
controller.DeleteNetworkPolicy(ctx, netpol)
|
||||||
// Should bring back the foo pod to default-allow as no netpol selects it
|
// Should bring back the foo pod to default-allow as no netpol selects it
|
||||||
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, fooPodIP))
|
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, fooPodIP))
|
||||||
require.True(t, m.entryExists(egressDefaultAllowIPSetName, fooPodIP))
|
require.True(t, m.entriesExist(egressDefaultAllowIPSetName, fooPodIP))
|
||||||
|
|
||||||
controller.DeletePod(podFoo)
|
controller.DeletePod(ctx, podFoo)
|
||||||
// Should remove foo pod from default-allow
|
// Should remove foo pod from default-allow
|
||||||
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, fooPodIP))
|
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, fooPodIP))
|
||||||
require.False(t, m.entryExists(egressDefaultAllowIPSetName, fooPodIP))
|
require.False(t, m.entriesExist(egressDefaultAllowIPSetName, fooPodIP))
|
||||||
|
|
||||||
controller.DeleteNamespace(defaultNamespace)
|
controller.DeleteNamespace(ctx, defaultNamespace)
|
||||||
// Should remove default ipset
|
// Should remove default ipset
|
||||||
require.NotContains(t, m.sets, ingressDefaultAllowIPSetName)
|
require.NotContains(t, m.sets, ingressDefaultAllowIPSetName)
|
||||||
require.NotContains(t, m.sets, egressDefaultAllowIPSetName)
|
require.NotContains(t, m.sets, egressDefaultAllowIPSetName)
|
||||||
@@ -369,14 +380,16 @@ func TestOutOfOrderPodEvents(t *testing.T) {
|
|||||||
m := newMockIPSet()
|
m := newMockIPSet()
|
||||||
client := fake.NewSimpleClientset()
|
client := fake.NewSimpleClientset()
|
||||||
controller := New("qux", newMockIPTables(), &m, client)
|
controller := New("qux", newMockIPTables(), &m, client)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
defaultNamespace := &coreapi.Namespace{
|
defaultNamespace := &coreapi.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "default",
|
Name: "default",
|
||||||
|
UID: "default",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
client.CoreV1().Namespaces().Create(defaultNamespace)
|
client.CoreV1().Namespaces().Create(ctx, defaultNamespace, metav1.CreateOptions{})
|
||||||
controller.AddNamespace(defaultNamespace)
|
controller.AddNamespace(ctx, defaultNamespace)
|
||||||
|
|
||||||
podFoo := &coreapi.Pod{
|
podFoo := &coreapi.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -385,10 +398,10 @@ func TestOutOfOrderPodEvents(t *testing.T) {
|
|||||||
Name: "foo",
|
Name: "foo",
|
||||||
Labels: map[string]string{"run": "foo"}},
|
Labels: map[string]string{"run": "foo"}},
|
||||||
Status: coreapi.PodStatus{PodIP: podIP}}
|
Status: coreapi.PodStatus{PodIP: podIP}}
|
||||||
controller.AddPod(podFoo)
|
controller.AddPod(ctx, podFoo)
|
||||||
|
|
||||||
// Should be in default-allow as no netpol selects podFoo
|
// Should be in default-allow as no netpol selects podFoo
|
||||||
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
|
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
|
||||||
|
|
||||||
netpol := &networkingv1.NetworkPolicy{
|
netpol := &networkingv1.NetworkPolicy{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -407,10 +420,10 @@ func TestOutOfOrderPodEvents(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
controller.AddNetworkPolicy(netpol)
|
controller.AddNetworkPolicy(ctx, netpol)
|
||||||
|
|
||||||
// Shouldn't be in default-allow as netpol above selects podFoo
|
// Shouldn't be in default-allow as netpol above selects podFoo
|
||||||
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
|
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
|
||||||
|
|
||||||
podBar := &coreapi.Pod{
|
podBar := &coreapi.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -419,28 +432,28 @@ func TestOutOfOrderPodEvents(t *testing.T) {
|
|||||||
Name: "bar",
|
Name: "bar",
|
||||||
Labels: map[string]string{"run": "bar"}},
|
Labels: map[string]string{"run": "bar"}},
|
||||||
Status: coreapi.PodStatus{PodIP: podIP}}
|
Status: coreapi.PodStatus{PodIP: podIP}}
|
||||||
controller.AddPod(podBar)
|
controller.AddPod(ctx, podBar)
|
||||||
|
|
||||||
// Should be in default-allow as no netpol selects podBar
|
// Should be in default-allow as no netpol selects podBar
|
||||||
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
|
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
|
||||||
require.True(t, m.Exist(podBar.ObjectMeta.UID, ingressDefaultAllowIPSetName, podIP))
|
require.True(t, m.EntryExists(uid(podBar), ingressDefaultAllowIPSetName, podIP))
|
||||||
// Should be in run=bar ipset
|
// Should be in run=bar ipset
|
||||||
require.True(t, m.entryExists(runBarIPSetName, podIP))
|
require.True(t, m.entriesExist(runBarIPSetName, podIP))
|
||||||
|
|
||||||
controller.DeletePod(podFoo)
|
controller.DeletePod(ctx, podFoo)
|
||||||
// Multiple duplicate events should not affect npc state
|
// Multiple duplicate events should not affect npc state
|
||||||
controller.DeletePod(podFoo)
|
controller.DeletePod(ctx, podFoo)
|
||||||
controller.DeletePod(podFoo)
|
controller.DeletePod(ctx, podFoo)
|
||||||
|
|
||||||
// Should be in default-allow as no netpol selects podBar and podFoo removal
|
// Should be in default-allow as no netpol selects podBar and podFoo removal
|
||||||
// should not affect podBar in default-allow
|
// should not affect podBar in default-allow
|
||||||
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
|
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
|
||||||
|
|
||||||
controller.DeletePod(podBar)
|
controller.DeletePod(ctx, podBar)
|
||||||
|
|
||||||
// Should remove from default-allow and run=bar ipsets
|
// Should remove from default-allow and run=bar ipsets
|
||||||
require.Equal(t, 0, len(m.sets[ingressDefaultAllowIPSetName].subSets))
|
require.Equal(t, 0, len(m.sets[ingressDefaultAllowIPSetName].subSets))
|
||||||
require.False(t, m.entryExists(runBarIPSetName, podIP))
|
require.False(t, m.entriesExist(runBarIPSetName, podIP))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test case for https://github.com/weaveworks/weave/issues/3222
|
// Test case for https://github.com/weaveworks/weave/issues/3222
|
||||||
@@ -453,14 +466,16 @@ func TestNewTargetSelector(t *testing.T) {
|
|||||||
m := newMockIPSet()
|
m := newMockIPSet()
|
||||||
client := fake.NewSimpleClientset()
|
client := fake.NewSimpleClientset()
|
||||||
controller := New("baz", newMockIPTables(), &m, client)
|
controller := New("baz", newMockIPTables(), &m, client)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
defaultNamespace := &coreapi.Namespace{
|
defaultNamespace := &coreapi.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "default",
|
Name: "default",
|
||||||
|
UID: "default",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
client.CoreV1().Namespaces().Create(defaultNamespace)
|
client.CoreV1().Namespaces().Create(ctx, defaultNamespace, metav1.CreateOptions{})
|
||||||
controller.AddNamespace(defaultNamespace)
|
controller.AddNamespace(ctx, defaultNamespace)
|
||||||
|
|
||||||
podFoo := &coreapi.Pod{
|
podFoo := &coreapi.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -469,9 +484,9 @@ func TestNewTargetSelector(t *testing.T) {
|
|||||||
Name: "foo",
|
Name: "foo",
|
||||||
Labels: map[string]string{"run": "foo"}},
|
Labels: map[string]string{"run": "foo"}},
|
||||||
Status: coreapi.PodStatus{PodIP: podIP}}
|
Status: coreapi.PodStatus{PodIP: podIP}}
|
||||||
controller.AddPod(podFoo)
|
controller.AddPod(ctx, podFoo)
|
||||||
|
|
||||||
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
|
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
|
||||||
|
|
||||||
netpolBar := &networkingv1.NetworkPolicy{
|
netpolBar := &networkingv1.NetworkPolicy{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -489,10 +504,10 @@ func TestNewTargetSelector(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
controller.AddNetworkPolicy(netpolBar)
|
controller.AddNetworkPolicy(ctx, netpolBar)
|
||||||
|
|
||||||
// netpolBar target selector selects podFoo
|
// netpolBar target selector selects podFoo
|
||||||
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
|
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
|
||||||
|
|
||||||
netpolFoo := &networkingv1.NetworkPolicy{
|
netpolFoo := &networkingv1.NetworkPolicy{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -510,14 +525,14 @@ func TestNewTargetSelector(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
controller.AddNetworkPolicy(netpolFoo)
|
controller.AddNetworkPolicy(ctx, netpolFoo)
|
||||||
|
|
||||||
controller.DeleteNetworkPolicy(netpolBar)
|
controller.DeleteNetworkPolicy(ctx, netpolBar)
|
||||||
// netpolFoo target-selects podFoo
|
// netpolFoo target-selects podFoo
|
||||||
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
|
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
|
||||||
controller.DeleteNetworkPolicy(netpolFoo)
|
controller.DeleteNetworkPolicy(ctx, netpolFoo)
|
||||||
// No netpol target-selects podFoo
|
// No netpol target-selects podFoo
|
||||||
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
|
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEgressPolicyWithIPBlock(t *testing.T) {
|
func TestEgressPolicyWithIPBlock(t *testing.T) {
|
||||||
@@ -531,19 +546,22 @@ func TestEgressPolicyWithIPBlock(t *testing.T) {
|
|||||||
ipt := newMockIPTables()
|
ipt := newMockIPTables()
|
||||||
client := fake.NewSimpleClientset()
|
client := fake.NewSimpleClientset()
|
||||||
controller := New("foo", ipt, &m, client)
|
controller := New("foo", ipt, &m, client)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
defaultNamespace := &coreapi.Namespace{
|
defaultNamespace := &coreapi.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "default",
|
Name: "default",
|
||||||
|
UID: "default",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
nonDefaultNamespace := &coreapi.Namespace{
|
nonDefaultNamespace := &coreapi.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "non-default",
|
Name: "non-default",
|
||||||
|
UID: "non-default",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
client.CoreV1().Namespaces().Create(defaultNamespace)
|
client.CoreV1().Namespaces().Create(ctx, defaultNamespace, metav1.CreateOptions{})
|
||||||
client.CoreV1().Namespaces().Create(nonDefaultNamespace)
|
client.CoreV1().Namespaces().Create(ctx, nonDefaultNamespace, metav1.CreateOptions{})
|
||||||
|
|
||||||
netpolFoo := &networkingv1.NetworkPolicy{
|
netpolFoo := &networkingv1.NetworkPolicy{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -569,16 +587,16 @@ func TestEgressPolicyWithIPBlock(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := controller.AddNetworkPolicy(netpolFoo)
|
err := controller.AddNetworkPolicy(ctx, netpolFoo)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, 2, len(m.sets[exceptIPSetName].subSets))
|
require.Equal(t, 2, len(m.sets[exceptIPSetName].subSets))
|
||||||
require.True(t, m.entryExists(exceptIPSetName, "192.168.48.1/32"))
|
require.True(t, m.entriesExist(exceptIPSetName, "192.168.48.1/32"))
|
||||||
require.True(t, m.entryExists(exceptIPSetName, "192.168.48.2/32"))
|
require.True(t, m.entriesExist(exceptIPSetName, "192.168.48.2/32"))
|
||||||
|
|
||||||
// Each egress rule is represented as two iptables rules (-J MARK and -J RETURN).
|
// Each egress rule is represented as two iptables rules (-J MARK and -J RETURN).
|
||||||
require.Equal(t, 2, len(ipt.rules[EgressCustomChain]))
|
require.Equal(t, 2, len(ipt.rules[chains.EgressCustomChain]))
|
||||||
for rule := range ipt.rules[EgressCustomChain] {
|
for rule := range ipt.rules[chains.EgressCustomChain] {
|
||||||
require.Contains(t, rule, "-d 192.168.48.0/24 -m set ! --match-set "+exceptIPSetName+" dst")
|
require.Contains(t, rule, "-d 192.168.48.0/24 -m set ! --match-set "+exceptIPSetName+" dst")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,7 +628,7 @@ func TestEgressPolicyWithIPBlock(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err = controller.AddNetworkPolicy(netpolBar)
|
err = controller.AddNetworkPolicy(ctx, netpolBar)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 2, len(m.sets[exceptIPSetNameInNonDefault].subSets))
|
require.Equal(t, 2, len(m.sets[exceptIPSetNameInNonDefault].subSets))
|
||||||
}
|
}
|
||||||
@@ -626,14 +644,16 @@ func TestIngressPolicyWithIPBlockAndPortSpecified(t *testing.T) {
|
|||||||
ipt := newMockIPTables()
|
ipt := newMockIPTables()
|
||||||
client := fake.NewSimpleClientset()
|
client := fake.NewSimpleClientset()
|
||||||
controller := New("any", ipt, &m, client)
|
controller := New("any", ipt, &m, client)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
defaultNamespace := &coreapi.Namespace{
|
defaultNamespace := &coreapi.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "default",
|
Name: "default",
|
||||||
|
UID: "default",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
client.CoreV1().Namespaces().Create(defaultNamespace)
|
client.CoreV1().Namespaces().Create(ctx, defaultNamespace, metav1.CreateOptions{})
|
||||||
|
|
||||||
podBar := &coreapi.Pod{
|
podBar := &coreapi.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -642,8 +662,8 @@ func TestIngressPolicyWithIPBlockAndPortSpecified(t *testing.T) {
|
|||||||
Name: "bar",
|
Name: "bar",
|
||||||
Labels: map[string]string{"run": "bar"}},
|
Labels: map[string]string{"run": "bar"}},
|
||||||
Status: coreapi.PodStatus{PodIP: barPodIP}}
|
Status: coreapi.PodStatus{PodIP: barPodIP}}
|
||||||
controller.AddPod(podBar)
|
controller.AddPod(ctx, podBar)
|
||||||
defer controller.DeletePod(podBar)
|
defer controller.DeletePod(ctx, podBar)
|
||||||
|
|
||||||
portProtocol := coreapi.ProtocolTCP
|
portProtocol := coreapi.ProtocolTCP
|
||||||
port := intstr.FromInt(80)
|
port := intstr.FromInt(80)
|
||||||
@@ -678,15 +698,15 @@ func TestIngressPolicyWithIPBlockAndPortSpecified(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := controller.AddNetworkPolicy(netpolicty)
|
err := controller.AddNetworkPolicy(ctx, netpolicty)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer controller.DeleteNetworkPolicy(netpolicty)
|
defer controller.DeleteNetworkPolicy(ctx, netpolicty)
|
||||||
|
|
||||||
require.Equal(t, 1, len(m.sets[runBarIPSetName].subSets))
|
require.Equal(t, 1, len(m.sets[runBarIPSetName].subSets))
|
||||||
require.True(t, m.entryExists(runBarIPSetName, barPodIP))
|
require.True(t, m.entriesExist(runBarIPSetName, barPodIP))
|
||||||
|
|
||||||
require.Equal(t, 1, len(ipt.rules[IngressChain]))
|
require.Equal(t, 1, len(ipt.rules[chains.IngressChain]))
|
||||||
for rule := range ipt.rules[IngressChain] {
|
for rule := range ipt.rules[chains.IngressChain] {
|
||||||
require.Contains(t, rule, "-s 192.168.48.4/32 -m set --match-set "+runBarIPSetName+" dst --dport 80")
|
require.Contains(t, rule, "-s 192.168.48.4/32 -m set --match-set "+runBarIPSetName+" dst --dport 80")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-6
@@ -6,7 +6,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
networkingv1 "k8s.io/api/networking/v1"
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/weaveworks/weave/common"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/weaveworks/weave/net/ipset"
|
||||||
@@ -51,17 +50,17 @@ func (spec *ipBlockSpec) getRuleSpec(src bool) ([]string, string) {
|
|||||||
|
|
||||||
type ipBlockSet struct {
|
type ipBlockSet struct {
|
||||||
ips ipset.Interface
|
ips ipset.Interface
|
||||||
users map[string]map[types.UID]struct{}
|
users map[string]map[ipset.UID]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIPBlockSet(ips ipset.Interface) *ipBlockSet {
|
func newIPBlockSet(ips ipset.Interface) *ipBlockSet {
|
||||||
return &ipBlockSet{
|
return &ipBlockSet{
|
||||||
ips: ips,
|
ips: ips,
|
||||||
users: make(map[string]map[types.UID]struct{}),
|
users: make(map[string]map[ipset.UID]struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ipBlockSet) deprovision(user types.UID, current, desired map[string]*ipBlockSpec) error {
|
func (s *ipBlockSet) deprovision(user ipset.UID, current, desired map[string]*ipBlockSpec) error {
|
||||||
for key, spec := range current {
|
for key, spec := range current {
|
||||||
if key == "" {
|
if key == "" {
|
||||||
continue
|
continue
|
||||||
@@ -83,7 +82,7 @@ func (s *ipBlockSet) deprovision(user types.UID, current, desired map[string]*ip
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ipBlockSet) provision(user types.UID, current, desired map[string]*ipBlockSpec) (err error) {
|
func (s *ipBlockSet) provision(user ipset.UID, current, desired map[string]*ipBlockSpec) (err error) {
|
||||||
for key, spec := range desired {
|
for key, spec := range desired {
|
||||||
if key == "" {
|
if key == "" {
|
||||||
// No need to provision an ipBlock with empty list of excepted CIDRs
|
// No need to provision an ipBlock with empty list of excepted CIDRs
|
||||||
@@ -106,7 +105,7 @@ func (s *ipBlockSet) provision(user types.UID, current, desired map[string]*ipBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.users[key] = make(map[types.UID]struct{})
|
s.users[key] = make(map[ipset.UID]struct{})
|
||||||
}
|
}
|
||||||
s.users[key][user] = struct{}{}
|
s.users[key][user] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|||||||
+62
-66
@@ -8,10 +8,10 @@ import (
|
|||||||
extnapi "k8s.io/api/extensions/v1beta1"
|
extnapi "k8s.io/api/extensions/v1beta1"
|
||||||
networkingv1 "k8s.io/api/networking/v1"
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/weaveworks/weave/common"
|
||||||
|
"github.com/weaveworks/weave/common/chains"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/weaveworks/weave/net/ipset"
|
||||||
"github.com/weaveworks/weave/npc/iptables"
|
"github.com/weaveworks/weave/npc/iptables"
|
||||||
)
|
)
|
||||||
@@ -22,13 +22,14 @@ type ns struct {
|
|||||||
ipt iptables.Interface // interface to iptables
|
ipt iptables.Interface // interface to iptables
|
||||||
ips ipset.Interface // interface to ipset
|
ips ipset.Interface // interface to ipset
|
||||||
|
|
||||||
name string // k8s Namespace name
|
name string // k8s Namespace name
|
||||||
nodeName string // my node name
|
nodeName string // my node name
|
||||||
namespace *coreapi.Namespace // k8s Namespace object
|
namespaceUID ipset.UID // k8s Namespace UID
|
||||||
pods map[types.UID]*coreapi.Pod // k8s Pod objects by UID
|
namespaceLabels map[string]string // k8s Namespace labels
|
||||||
policies map[types.UID]interface{} // k8s NetworkPolicy objects by UID
|
pods map[ipset.UID]*coreapi.Pod // k8s Pod objects by UID
|
||||||
|
policies map[ipset.UID]interface{} // k8s NetworkPolicy objects by UID
|
||||||
|
|
||||||
uid types.UID // surrogate UID to own allPods selector
|
uid ipset.UID // surrogate UID to own allPods selector
|
||||||
allPods *selectorSpec // hash:ip ipset of all pod IPs in this namespace
|
allPods *selectorSpec // hash:ip ipset of all pod IPs in this namespace
|
||||||
|
|
||||||
// stores IP addrs of pods which are not selected by any target podSelector of
|
// stores IP addrs of pods which are not selected by any target podSelector of
|
||||||
@@ -54,11 +55,12 @@ func newNS(name, nodeName string, ipt iptables.Interface, ips ipset.Interface, n
|
|||||||
ipt: ipt,
|
ipt: ipt,
|
||||||
ips: ips,
|
ips: ips,
|
||||||
name: name,
|
name: name,
|
||||||
namespace: namespaceObj,
|
namespaceUID: nsuid(namespaceObj),
|
||||||
|
namespaceLabels: namespaceObj.ObjectMeta.Labels,
|
||||||
nodeName: nodeName,
|
nodeName: nodeName,
|
||||||
pods: make(map[types.UID]*coreapi.Pod),
|
pods: make(map[ipset.UID]*coreapi.Pod),
|
||||||
policies: make(map[types.UID]interface{}),
|
policies: make(map[ipset.UID]interface{}),
|
||||||
uid: uuid.NewUUID(),
|
uid: ipset.UID(uuid.NewUUID()),
|
||||||
allPods: allPods,
|
allPods: allPods,
|
||||||
nsSelectors: nsSelectors,
|
nsSelectors: nsSelectors,
|
||||||
namespacedPodsSelectors: namespacedPodsSelectors,
|
namespacedPodsSelectors: namespacedPodsSelectors,
|
||||||
@@ -88,7 +90,7 @@ func newNS(name, nodeName string, ipt iptables.Interface, ips ipset.Interface, n
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ns *ns) empty() bool {
|
func (ns *ns) empty() bool {
|
||||||
return len(ns.pods) == 0 && len(ns.policies) == 0 && ns.namespace == nil
|
return len(ns.pods) == 0 && len(ns.policies) == 0 && ns.namespaceUID == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ns *ns) destroy() error {
|
func (ns *ns) destroy() error {
|
||||||
@@ -99,7 +101,7 @@ func (ns *ns) onNewPodSelector(selector *selector) error {
|
|||||||
for _, pod := range ns.pods {
|
for _, pod := range ns.pods {
|
||||||
if hasIP(pod) {
|
if hasIP(pod) {
|
||||||
if selector.matchesPodSelector(pod.ObjectMeta.Labels) {
|
if selector.matchesPodSelector(pod.ObjectMeta.Labels) {
|
||||||
if err := selector.addEntry(pod.ObjectMeta.UID, pod.Status.PodIP, podComment(pod)); err != nil {
|
if err := selector.addEntry(uid(pod), pod.Status.PodIP, podComment(pod)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +117,7 @@ func (ns *ns) onNewTargetPodSelector(selector *selector, policyType policyType)
|
|||||||
// Remove the pod from default-allow if dst podselector matches the pod
|
// Remove the pod from default-allow if dst podselector matches the pod
|
||||||
ipset := ns.defaultAllowIPSetName(policyType)
|
ipset := ns.defaultAllowIPSetName(policyType)
|
||||||
if selector.matchesPodSelector(pod.ObjectMeta.Labels) {
|
if selector.matchesPodSelector(pod.ObjectMeta.Labels) {
|
||||||
if err := ns.ips.DelEntry(pod.ObjectMeta.UID, ipset, pod.Status.PodIP); err != nil {
|
if err := ns.ips.DelEntry(uid(pod), ipset, pod.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,44 +153,37 @@ func (ns *ns) addToDefaultAllowIfNoMatching(pod *coreapi.Pod, policyType policyT
|
|||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
ipset := ns.defaultAllowIPSetName(policyType)
|
ipset := ns.defaultAllowIPSetName(policyType)
|
||||||
if err := ns.ips.AddEntry(pod.ObjectMeta.UID, ipset, pod.Status.PodIP, podComment(pod)); err != nil {
|
if err := ns.ips.AddEntry(uid(pod), ipset, pod.Status.PodIP, podComment(pod)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ns *ns) checkLocalPod(obj *coreapi.Pod) bool {
|
|
||||||
if obj.Spec.NodeName != ns.nodeName {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ns *ns) addPod(obj *coreapi.Pod) error {
|
func (ns *ns) addPod(obj *coreapi.Pod) error {
|
||||||
ns.pods[obj.ObjectMeta.UID] = obj
|
ns.pods[uid(obj)] = obj
|
||||||
|
|
||||||
if !hasIP(obj) {
|
if !hasIP(obj) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
foundIngress, foundEgress, err := ns.podSelectors.addToMatchingPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
|
foundIngress, foundEgress, err := ns.podSelectors.addToMatchingPodSelector(uid(obj), obj.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// If there are no matching target selectors, add the pod to default-allow
|
// If there are no matching target selectors, add the pod to default-allow
|
||||||
if !foundIngress {
|
if !foundIngress {
|
||||||
if err := ns.ips.AddEntry(obj.ObjectMeta.UID, ns.ingressDefaultAllowIPSet, obj.Status.PodIP, podComment(obj)); err != nil {
|
if err := ns.ips.AddEntry(uid(obj), ns.ingressDefaultAllowIPSet, obj.Status.PodIP, podComment(obj)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !foundEgress {
|
if !foundEgress {
|
||||||
if err := ns.ips.AddEntry(obj.ObjectMeta.UID, ns.egressDefaultAllowIPSet, obj.Status.PodIP, podComment(obj)); err != nil {
|
if err := ns.ips.AddEntry(uid(obj), ns.egressDefaultAllowIPSet, obj.Status.PodIP, podComment(obj)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
|
err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(uid(obj), obj.ObjectMeta.Labels, ns.namespaceLabels, obj.Status.PodIP, podComment(obj))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -197,44 +192,44 @@ func (ns *ns) addPod(obj *coreapi.Pod) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
|
func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
|
||||||
delete(ns.pods, oldObj.ObjectMeta.UID)
|
delete(ns.pods, uid(oldObj))
|
||||||
ns.pods[newObj.ObjectMeta.UID] = newObj
|
ns.pods[uid(newObj)] = newObj
|
||||||
|
|
||||||
if !hasIP(oldObj) && !hasIP(newObj) {
|
if !hasIP(oldObj) && !hasIP(newObj) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasIP(oldObj) && !hasIP(newObj) {
|
if hasIP(oldObj) && !hasIP(newObj) {
|
||||||
if err := ns.ips.DelEntry(oldObj.ObjectMeta.UID, ns.ingressDefaultAllowIPSet, oldObj.Status.PodIP); err != nil {
|
if err := ns.ips.DelEntry(uid(oldObj), ns.ingressDefaultAllowIPSet, oldObj.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ns.ips.DelEntry(oldObj.ObjectMeta.UID, ns.egressDefaultAllowIPSet, oldObj.Status.PodIP); err != nil {
|
if err := ns.ips.DelEntry(uid(oldObj), ns.egressDefaultAllowIPSet, oldObj.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(oldObj.ObjectMeta.UID, oldObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, oldObj.Status.PodIP); err != nil {
|
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(uid(oldObj), oldObj.ObjectMeta.Labels, ns.namespaceLabels, oldObj.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ns.podSelectors.delFromMatchingPodSelector(oldObj.ObjectMeta.UID, oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
|
return ns.podSelectors.delFromMatchingPodSelector(uid(oldObj), oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasIP(oldObj) && hasIP(newObj) {
|
if !hasIP(oldObj) && hasIP(newObj) {
|
||||||
foundIngress, foundEgress, err := ns.podSelectors.addToMatchingPodSelector(newObj.ObjectMeta.UID, newObj.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
|
foundIngress, foundEgress, err := ns.podSelectors.addToMatchingPodSelector(uid(newObj), newObj.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !foundIngress {
|
if !foundIngress {
|
||||||
if err := ns.ips.AddEntry(newObj.ObjectMeta.UID, ns.ingressDefaultAllowIPSet, newObj.Status.PodIP, podComment(newObj)); err != nil {
|
if err := ns.ips.AddEntry(uid(newObj), ns.ingressDefaultAllowIPSet, newObj.Status.PodIP, podComment(newObj)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !foundEgress {
|
if !foundEgress {
|
||||||
if err := ns.ips.AddEntry(newObj.ObjectMeta.UID, ns.egressDefaultAllowIPSet, newObj.Status.PodIP, podComment(newObj)); err != nil {
|
if err := ns.ips.AddEntry(uid(newObj), ns.egressDefaultAllowIPSet, newObj.Status.PodIP, podComment(newObj)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(newObj.ObjectMeta.UID, newObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
|
err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(uid(newObj), newObj.ObjectMeta.Labels, ns.namespaceLabels, newObj.Status.PodIP, podComment(newObj))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -261,12 +256,12 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if oldMatch {
|
if oldMatch {
|
||||||
if err := ps.delEntry(oldObj.ObjectMeta.UID, oldObj.Status.PodIP); err != nil {
|
if err := ps.delEntry(uid(oldObj), oldObj.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if newMatch {
|
if newMatch {
|
||||||
if err := ps.addEntry(newObj.ObjectMeta.UID, newObj.Status.PodIP, podComment(newObj)); err != nil {
|
if err := ps.addEntry(uid(newObj), newObj.Status.PodIP, podComment(newObj)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,18 +274,18 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, ps := range ns.namespacedPodsSelectors.entries {
|
for _, ps := range ns.namespacedPodsSelectors.entries {
|
||||||
oldMatch := ps.matchesNamespacedPodSelector(oldObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels)
|
oldMatch := ps.matchesNamespacedPodSelector(oldObj.ObjectMeta.Labels, ns.namespaceLabels)
|
||||||
newMatch := ps.matchesNamespacedPodSelector(newObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels)
|
newMatch := ps.matchesNamespacedPodSelector(newObj.ObjectMeta.Labels, ns.namespaceLabels)
|
||||||
if oldMatch == newMatch && oldObj.Status.PodIP == newObj.Status.PodIP {
|
if oldMatch == newMatch && oldObj.Status.PodIP == newObj.Status.PodIP {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if oldMatch {
|
if oldMatch {
|
||||||
if err := ps.delEntry(oldObj.ObjectMeta.UID, oldObj.Status.PodIP); err != nil {
|
if err := ps.delEntry(uid(oldObj), oldObj.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if newMatch {
|
if newMatch {
|
||||||
if err := ps.addEntry(newObj.ObjectMeta.UID, newObj.Status.PodIP, podComment(newObj)); err != nil {
|
if err := ps.addEntry(uid(newObj), newObj.Status.PodIP, podComment(newObj)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,7 +300,7 @@ func (ns *ns) addOrRemoveToDefaultAllowIPSet(ps *selector, oldObj, newObj *corea
|
|||||||
if ns.podSelectors.targetSelectorExist(ps, policyType) {
|
if ns.podSelectors.targetSelectorExist(ps, policyType) {
|
||||||
switch {
|
switch {
|
||||||
case !oldMatch && newMatch:
|
case !oldMatch && newMatch:
|
||||||
if err := ns.ips.DelEntry(oldObj.ObjectMeta.UID, ipset, oldObj.Status.PodIP); err != nil {
|
if err := ns.ips.DelEntry(uid(oldObj), ipset, oldObj.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case oldMatch && !newMatch:
|
case oldMatch && !newMatch:
|
||||||
@@ -318,22 +313,22 @@ func (ns *ns) addOrRemoveToDefaultAllowIPSet(ps *selector, oldObj, newObj *corea
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ns *ns) deletePod(obj *coreapi.Pod) error {
|
func (ns *ns) deletePod(obj *coreapi.Pod) error {
|
||||||
delete(ns.pods, obj.ObjectMeta.UID)
|
delete(ns.pods, uid(obj))
|
||||||
|
|
||||||
if !hasIP(obj) {
|
if !hasIP(obj) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ns.ips.DelEntry(obj.ObjectMeta.UID, ns.ingressDefaultAllowIPSet, obj.Status.PodIP); err != nil {
|
if err := ns.ips.DelEntry(uid(obj), ns.ingressDefaultAllowIPSet, obj.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ns.ips.DelEntry(obj.ObjectMeta.UID, ns.egressDefaultAllowIPSet, obj.Status.PodIP); err != nil {
|
if err := ns.ips.DelEntry(uid(obj), ns.egressDefaultAllowIPSet, obj.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ns.podSelectors.delFromMatchingPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP); err != nil {
|
if err := ns.podSelectors.delFromMatchingPodSelector(uid(obj), obj.ObjectMeta.Labels, obj.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, obj.Status.PodIP); err != nil {
|
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(uid(obj), obj.ObjectMeta.Labels, ns.namespaceLabels, obj.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -441,12 +436,12 @@ func (ns *ns) updateDefaultAllowIPSetEntry(oldObj, newObj *coreapi.Pod, ipsetNam
|
|||||||
// Instead of iterating over all selectors we check whether old pod IP
|
// Instead of iterating over all selectors we check whether old pod IP
|
||||||
// has been inserted into default-allow ipset to decide whether the IP
|
// has been inserted into default-allow ipset to decide whether the IP
|
||||||
// in the ipset has to be updated.
|
// in the ipset has to be updated.
|
||||||
if ns.ips.Exist(oldObj.ObjectMeta.UID, ipsetName, oldObj.Status.PodIP) {
|
if ns.ips.EntryExists(uid(oldObj), ipsetName, oldObj.Status.PodIP) {
|
||||||
|
|
||||||
if err := ns.ips.DelEntry(oldObj.ObjectMeta.UID, ipsetName, oldObj.Status.PodIP); err != nil {
|
if err := ns.ips.DelEntry(uid(oldObj), ipsetName, oldObj.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ns.ips.AddEntry(newObj.ObjectMeta.UID, ipsetName, newObj.Status.PodIP, podComment(newObj)); err != nil {
|
if err := ns.ips.AddEntry(uid(newObj), ipsetName, newObj.Status.PodIP, podComment(newObj)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,12 +450,12 @@ func (ns *ns) updateDefaultAllowIPSetEntry(oldObj, newObj *coreapi.Pod, ipsetNam
|
|||||||
|
|
||||||
func bypassRules(namespace string, ingress, egress ipset.Name) map[string][][]string {
|
func bypassRules(namespace string, ingress, egress ipset.Name) map[string][][]string {
|
||||||
return map[string][][]string{
|
return map[string][][]string{
|
||||||
DefaultChain: {
|
chains.DefaultChain: {
|
||||||
{"-m", "set", "--match-set", string(ingress), "dst", "-j", "ACCEPT",
|
{"-m", "set", "--match-set", string(ingress), "dst", "-j", "ACCEPT",
|
||||||
"-m", "comment", "--comment", "DefaultAllow ingress isolation for namespace: " + namespace},
|
"-m", "comment", "--comment", "DefaultAllow ingress isolation for namespace: " + namespace},
|
||||||
},
|
},
|
||||||
EgressDefaultChain: {
|
chains.EgressDefaultChain: {
|
||||||
{"-m", "set", "--match-set", string(egress), "src", "-j", EgressMarkChain,
|
{"-m", "set", "--match-set", string(egress), "src", "-j", chains.EgressMarkChain,
|
||||||
"-m", "comment", "--comment", "DefaultAllow egress isolation for namespace: " + namespace},
|
"-m", "comment", "--comment", "DefaultAllow egress isolation for namespace: " + namespace},
|
||||||
{"-m", "set", "--match-set", string(egress), "src", "-j", "RETURN",
|
{"-m", "set", "--match-set", string(egress), "src", "-j", "RETURN",
|
||||||
"-m", "comment", "--comment", "DefaultAllow egress isolation for namespace: " + namespace},
|
"-m", "comment", "--comment", "DefaultAllow egress isolation for namespace: " + namespace},
|
||||||
@@ -495,7 +490,8 @@ func (ns *ns) deleteBypassRules() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ns *ns) addNamespace(obj *coreapi.Namespace) error {
|
func (ns *ns) addNamespace(obj *coreapi.Namespace) error {
|
||||||
ns.namespace = obj
|
ns.namespaceUID = ipset.UID(obj.ObjectMeta.UID)
|
||||||
|
ns.namespaceLabels = obj.ObjectMeta.Labels
|
||||||
|
|
||||||
// Insert a rule to bypass policies
|
// Insert a rule to bypass policies
|
||||||
if err := ns.ensureBypassRules(); err != nil {
|
if err := ns.ensureBypassRules(); err != nil {
|
||||||
@@ -503,15 +499,15 @@ func (ns *ns) addNamespace(obj *coreapi.Namespace) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add namespace ipset to matching namespace selectors
|
// Add namespace ipset to matching namespace selectors
|
||||||
err := ns.nsSelectors.addToMatchingNamespaceSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName), namespaceComment(ns))
|
err := ns.nsSelectors.addToMatchingNamespaceSelector(nsuid(obj), obj.ObjectMeta.Labels, string(ns.allPods.ipsetName), namespaceComment(ns))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
|
func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
|
||||||
ns.namespace = newObj
|
|
||||||
|
|
||||||
// Re-evaluate namespace selector membership if labels have changed
|
// Re-evaluate namespace selector membership if labels have changed
|
||||||
if !equals(oldObj.ObjectMeta.Labels, newObj.ObjectMeta.Labels) {
|
if !equals(oldObj.ObjectMeta.Labels, newObj.ObjectMeta.Labels) {
|
||||||
|
ns.namespaceLabels = newObj.ObjectMeta.Labels
|
||||||
|
|
||||||
for _, selector := range ns.nsSelectors.entries {
|
for _, selector := range ns.nsSelectors.entries {
|
||||||
oldMatch := selector.matchesNamespaceSelector(oldObj.ObjectMeta.Labels)
|
oldMatch := selector.matchesNamespaceSelector(oldObj.ObjectMeta.Labels)
|
||||||
newMatch := selector.matchesNamespaceSelector(newObj.ObjectMeta.Labels)
|
newMatch := selector.matchesNamespaceSelector(newObj.ObjectMeta.Labels)
|
||||||
@@ -519,12 +515,12 @@ func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if oldMatch {
|
if oldMatch {
|
||||||
if err := selector.delEntry(ns.namespace.ObjectMeta.UID, string(ns.allPods.ipsetName)); err != nil {
|
if err := selector.delEntry(ns.namespaceUID, string(ns.allPods.ipsetName)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if newMatch {
|
if newMatch {
|
||||||
if err := selector.addEntry(ns.namespace.ObjectMeta.UID, string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil {
|
if err := selector.addEntry(ns.namespaceUID, string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -535,7 +531,7 @@ func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ns *ns) deleteNamespace(obj *coreapi.Namespace) error {
|
func (ns *ns) deleteNamespace(obj *coreapi.Namespace) error {
|
||||||
ns.namespace = nil
|
ns.namespaceUID = ""
|
||||||
|
|
||||||
// Remove bypass rule
|
// Remove bypass rule
|
||||||
if err := ns.deleteBypassRules(); err != nil {
|
if err := ns.deleteBypassRules(); err != nil {
|
||||||
@@ -543,7 +539,7 @@ func (ns *ns) deleteNamespace(obj *coreapi.Namespace) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove namespace ipset from any matching namespace selectors
|
// Remove namespace ipset from any matching namespace selectors
|
||||||
err := ns.nsSelectors.delFromMatchingNamespaceSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
|
err := ns.nsSelectors.delFromMatchingNamespaceSelector(nsuid(obj), obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -593,7 +589,7 @@ func (ns *ns) defaultAllowIPSetName(pt policyType) ipset.Name {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ns *ns) analyse(obj interface{}) (
|
func (ns *ns) analyse(obj interface{}) (
|
||||||
uid types.UID,
|
uid ipset.UID,
|
||||||
rules map[string]*ruleSpec,
|
rules map[string]*ruleSpec,
|
||||||
nsSelectors, podSelectors, namespacedPodsSelectors map[string]*selectorSpec,
|
nsSelectors, podSelectors, namespacedPodsSelectors map[string]*selectorSpec,
|
||||||
ipBlocks map[string]*ipBlockSpec,
|
ipBlocks map[string]*ipBlockSpec,
|
||||||
@@ -601,9 +597,9 @@ func (ns *ns) analyse(obj interface{}) (
|
|||||||
|
|
||||||
switch p := obj.(type) {
|
switch p := obj.(type) {
|
||||||
case *extnapi.NetworkPolicy:
|
case *extnapi.NetworkPolicy:
|
||||||
uid = p.ObjectMeta.UID
|
uid = ipset.UID(p.ObjectMeta.UID)
|
||||||
case *networkingv1.NetworkPolicy:
|
case *networkingv1.NetworkPolicy:
|
||||||
uid = p.ObjectMeta.UID
|
uid = ipset.UID(p.ObjectMeta.UID)
|
||||||
default:
|
default:
|
||||||
err = errInvalidNetworkPolicyObjType
|
err = errInvalidNetworkPolicyObjType
|
||||||
return
|
return
|
||||||
|
|||||||
+10
-10
@@ -5,9 +5,9 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/weaveworks/weave/common"
|
||||||
|
"github.com/weaveworks/weave/common/chains"
|
||||||
|
"github.com/weaveworks/weave/net/ipset"
|
||||||
"github.com/weaveworks/weave/npc/iptables"
|
"github.com/weaveworks/weave/npc/iptables"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -55,9 +55,9 @@ func newRuleSpec(policyType policyType, proto *string, srcHost, dstHost ruleHost
|
|||||||
|
|
||||||
func (spec *ruleSpec) iptChain() string {
|
func (spec *ruleSpec) iptChain() string {
|
||||||
if spec.policyType == policyTypeEgress {
|
if spec.policyType == policyTypeEgress {
|
||||||
return EgressCustomChain
|
return chains.EgressCustomChain
|
||||||
}
|
}
|
||||||
return IngressChain
|
return chains.IngressChain
|
||||||
}
|
}
|
||||||
|
|
||||||
func (spec *ruleSpec) iptRuleSpecs() [][]string {
|
func (spec *ruleSpec) iptRuleSpecs() [][]string {
|
||||||
@@ -71,7 +71,7 @@ func (spec *ruleSpec) iptRuleSpecs() [][]string {
|
|||||||
// policyTypeEgress
|
// policyTypeEgress
|
||||||
ruleMark := make([]string, len(spec.args))
|
ruleMark := make([]string, len(spec.args))
|
||||||
copy(ruleMark, spec.args)
|
copy(ruleMark, spec.args)
|
||||||
ruleMark = append(ruleMark, "-j", EgressMarkChain)
|
ruleMark = append(ruleMark, "-j", chains.EgressMarkChain)
|
||||||
ruleReturn := make([]string, len(spec.args))
|
ruleReturn := make([]string, len(spec.args))
|
||||||
copy(ruleReturn, spec.args)
|
copy(ruleReturn, spec.args)
|
||||||
ruleReturn = append(ruleReturn, "-j", "RETURN")
|
ruleReturn = append(ruleReturn, "-j", "RETURN")
|
||||||
@@ -80,14 +80,14 @@ func (spec *ruleSpec) iptRuleSpecs() [][]string {
|
|||||||
|
|
||||||
type ruleSet struct {
|
type ruleSet struct {
|
||||||
ipt iptables.Interface
|
ipt iptables.Interface
|
||||||
users map[string]map[types.UID]struct{}
|
users map[string]map[ipset.UID]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRuleSet(ipt iptables.Interface) *ruleSet {
|
func newRuleSet(ipt iptables.Interface) *ruleSet {
|
||||||
return &ruleSet{ipt, make(map[string]map[types.UID]struct{})}
|
return &ruleSet{ipt, make(map[string]map[ipset.UID]struct{})}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *ruleSet) deprovision(user types.UID, current, desired map[string]*ruleSpec) error {
|
func (rs *ruleSet) deprovision(user ipset.UID, current, desired map[string]*ruleSpec) error {
|
||||||
for key, spec := range current {
|
for key, spec := range current {
|
||||||
if _, found := desired[key]; !found {
|
if _, found := desired[key]; !found {
|
||||||
delete(rs.users[key], user)
|
delete(rs.users[key], user)
|
||||||
@@ -108,7 +108,7 @@ func (rs *ruleSet) deprovision(user types.UID, current, desired map[string]*rule
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *ruleSet) provision(user types.UID, current, desired map[string]*ruleSpec) error {
|
func (rs *ruleSet) provision(user ipset.UID, current, desired map[string]*ruleSpec) error {
|
||||||
for key, spec := range desired {
|
for key, spec := range desired {
|
||||||
if _, found := current[key]; !found {
|
if _, found := current[key]; !found {
|
||||||
if _, found := rs.users[key]; !found {
|
if _, found := rs.users[key]; !found {
|
||||||
@@ -119,7 +119,7 @@ func (rs *ruleSet) provision(user types.UID, current, desired map[string]*ruleSp
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rs.users[key] = make(map[types.UID]struct{})
|
rs.users[key] = make(map[ipset.UID]struct{})
|
||||||
}
|
}
|
||||||
rs.users[key][user] = struct{}{}
|
rs.users[key][user] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-15
@@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/weaveworks/weave/common"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/weaveworks/weave/net/ipset"
|
||||||
@@ -60,7 +59,7 @@ func (spec *selectorSpec) getRuleSpec(src bool) ([]string, string) {
|
|||||||
}
|
}
|
||||||
rule := []string{"-m", "set", "--match-set", string(spec.ipsetName), dir}
|
rule := []string{"-m", "set", "--match-set", string(spec.ipsetName), dir}
|
||||||
|
|
||||||
comment := "anywhere"
|
var comment string
|
||||||
if spec.nsName != "" {
|
if spec.nsName != "" {
|
||||||
comment = fmt.Sprintf("pods: namespace: %s, selector: %s", spec.nsName, spec.key)
|
comment = fmt.Sprintf("pods: namespace: %s, selector: %s", spec.nsName, spec.key)
|
||||||
} else {
|
} else {
|
||||||
@@ -87,11 +86,11 @@ func (s *selector) matchesNamespacedPodSelector(podsLabelMap, namespaceLabelMap
|
|||||||
return s.spec.podSelector.Matches(labels.Set(podsLabelMap)) && s.spec.namespaceSelector.Matches(labels.Set(namespaceLabelMap))
|
return s.spec.podSelector.Matches(labels.Set(podsLabelMap)) && s.spec.namespaceSelector.Matches(labels.Set(namespaceLabelMap))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *selector) addEntry(user types.UID, entry string, comment string) error {
|
func (s *selector) addEntry(user ipset.UID, entry string, comment string) error {
|
||||||
return s.ips.AddEntry(user, s.spec.ipsetName, entry, comment)
|
return s.ips.AddEntry(user, s.spec.ipsetName, entry, comment)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *selector) delEntry(user types.UID, entry string) error {
|
func (s *selector) delEntry(user ipset.UID, entry string) error {
|
||||||
return s.ips.DelEntry(user, s.spec.ipsetName, entry)
|
return s.ips.DelEntry(user, s.spec.ipsetName, entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +106,7 @@ type selectorSet struct {
|
|||||||
// invoked after the last instance of target selector has been deprovisioned
|
// invoked after the last instance of target selector has been deprovisioned
|
||||||
onDestroyTargetSelector selectorWithPolicyTypeFn
|
onDestroyTargetSelector selectorWithPolicyTypeFn
|
||||||
|
|
||||||
users map[string]map[types.UID]struct{} // list of users per selector
|
users map[string]map[ipset.UID]struct{} // list of users per selector
|
||||||
entries map[string]*selector
|
entries map[string]*selector
|
||||||
|
|
||||||
// We need to keep track of target selector instances to be able to invoke
|
// We need to keep track of target selector instances to be able to invoke
|
||||||
@@ -122,12 +121,12 @@ func newSelectorSet(ips ipset.Interface, onNewSelector selectorFn, onNewTargetSe
|
|||||||
onNewSelector: onNewSelector,
|
onNewSelector: onNewSelector,
|
||||||
onNewTargetSelector: onNewTargetSelector,
|
onNewTargetSelector: onNewTargetSelector,
|
||||||
onDestroyTargetSelector: onDestroyTargetSelector,
|
onDestroyTargetSelector: onDestroyTargetSelector,
|
||||||
users: make(map[string]map[types.UID]struct{}),
|
users: make(map[string]map[ipset.UID]struct{}),
|
||||||
entries: make(map[string]*selector),
|
entries: make(map[string]*selector),
|
||||||
targetSelectorsCount: make(map[string]map[policyType]int)}
|
targetSelectorsCount: make(map[string]map[policyType]int)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *selectorSet) addToMatchingPodSelector(user types.UID, podLabelsMap map[string]string, entry string, comment string) (bool, bool, error) {
|
func (ss *selectorSet) addToMatchingPodSelector(user ipset.UID, podLabelsMap map[string]string, entry string, comment string) (bool, bool, error) {
|
||||||
foundIngress := false
|
foundIngress := false
|
||||||
foundEgress := false
|
foundEgress := false
|
||||||
for _, s := range ss.entries {
|
for _, s := range ss.entries {
|
||||||
@@ -146,7 +145,7 @@ func (ss *selectorSet) addToMatchingPodSelector(user types.UID, podLabelsMap map
|
|||||||
return foundIngress, foundEgress, nil
|
return foundIngress, foundEgress, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *selectorSet) addToMatchingNamespaceSelector(user types.UID, namespaceLabelsMap map[string]string, entry string, comment string) error {
|
func (ss *selectorSet) addToMatchingNamespaceSelector(user ipset.UID, namespaceLabelsMap map[string]string, entry string, comment string) error {
|
||||||
for _, s := range ss.entries {
|
for _, s := range ss.entries {
|
||||||
if s.matchesNamespaceSelector(namespaceLabelsMap) {
|
if s.matchesNamespaceSelector(namespaceLabelsMap) {
|
||||||
if err := s.addEntry(user, entry, comment); err != nil {
|
if err := s.addEntry(user, entry, comment); err != nil {
|
||||||
@@ -157,7 +156,7 @@ func (ss *selectorSet) addToMatchingNamespaceSelector(user types.UID, namespaceL
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *selectorSet) addToMatchingNamespacedPodSelector(user types.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string, comment string) error {
|
func (ss *selectorSet) addToMatchingNamespacedPodSelector(user ipset.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string, comment string) error {
|
||||||
for _, s := range ss.entries {
|
for _, s := range ss.entries {
|
||||||
if s.matchesNamespacedPodSelector(podLabelsMap, namespaceLabelsMap) {
|
if s.matchesNamespacedPodSelector(podLabelsMap, namespaceLabelsMap) {
|
||||||
if err := s.addEntry(user, entry, comment); err != nil {
|
if err := s.addEntry(user, entry, comment); err != nil {
|
||||||
@@ -168,7 +167,7 @@ func (ss *selectorSet) addToMatchingNamespacedPodSelector(user types.UID, podLab
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *selectorSet) delFromMatchingPodSelector(user types.UID, podLabelsMap map[string]string, entry string) error {
|
func (ss *selectorSet) delFromMatchingPodSelector(user ipset.UID, podLabelsMap map[string]string, entry string) error {
|
||||||
for _, s := range ss.entries {
|
for _, s := range ss.entries {
|
||||||
if s.matchesPodSelector(podLabelsMap) {
|
if s.matchesPodSelector(podLabelsMap) {
|
||||||
if err := s.delEntry(user, entry); err != nil {
|
if err := s.delEntry(user, entry); err != nil {
|
||||||
@@ -179,7 +178,7 @@ func (ss *selectorSet) delFromMatchingPodSelector(user types.UID, podLabelsMap m
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *selectorSet) delFromMatchingNamespaceSelector(user types.UID, namespaceLabelsMap map[string]string, entry string) error {
|
func (ss *selectorSet) delFromMatchingNamespaceSelector(user ipset.UID, namespaceLabelsMap map[string]string, entry string) error {
|
||||||
for _, s := range ss.entries {
|
for _, s := range ss.entries {
|
||||||
if s.matchesNamespaceSelector(namespaceLabelsMap) {
|
if s.matchesNamespaceSelector(namespaceLabelsMap) {
|
||||||
if err := s.delEntry(user, entry); err != nil {
|
if err := s.delEntry(user, entry); err != nil {
|
||||||
@@ -190,7 +189,7 @@ func (ss *selectorSet) delFromMatchingNamespaceSelector(user types.UID, namespac
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *selectorSet) delFromMatchingNamespacedPodSelector(user types.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string) error {
|
func (ss *selectorSet) delFromMatchingNamespacedPodSelector(user ipset.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string) error {
|
||||||
for _, s := range ss.entries {
|
for _, s := range ss.entries {
|
||||||
if s.matchesNamespacedPodSelector(podLabelsMap, namespaceLabelsMap) {
|
if s.matchesNamespacedPodSelector(podLabelsMap, namespaceLabelsMap) {
|
||||||
if err := s.delEntry(user, entry); err != nil {
|
if err := s.delEntry(user, entry); err != nil {
|
||||||
@@ -205,7 +204,7 @@ func (ss *selectorSet) targetSelectorExist(s *selector, policyType policyType) b
|
|||||||
return ss.targetSelectorsCount[s.spec.key][policyType] > 0
|
return ss.targetSelectorsCount[s.spec.key][policyType] > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *selectorSet) deprovision(user types.UID, current, desired map[string]*selectorSpec) error {
|
func (ss *selectorSet) deprovision(user ipset.UID, current, desired map[string]*selectorSpec) error {
|
||||||
for key, spec := range current {
|
for key, spec := range current {
|
||||||
if _, found := desired[key]; !found {
|
if _, found := desired[key]; !found {
|
||||||
delete(ss.users[key], user)
|
delete(ss.users[key], user)
|
||||||
@@ -233,7 +232,7 @@ func (ss *selectorSet) deprovision(user types.UID, current, desired map[string]*
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *selectorSet) provision(user types.UID, current, desired map[string]*selectorSpec) error {
|
func (ss *selectorSet) provision(user ipset.UID, current, desired map[string]*selectorSpec) error {
|
||||||
for key, spec := range desired {
|
for key, spec := range desired {
|
||||||
if _, found := current[key]; !found {
|
if _, found := current[key]; !found {
|
||||||
selector := &selector{ss.ips, spec}
|
selector := &selector{ss.ips, spec}
|
||||||
@@ -246,7 +245,7 @@ func (ss *selectorSet) provision(user types.UID, current, desired map[string]*se
|
|||||||
if err := ss.onNewSelector(selector); err != nil {
|
if err := ss.onNewSelector(selector); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ss.users[key] = make(map[types.UID]struct{})
|
ss.users[key] = make(map[ipset.UID]struct{})
|
||||||
ss.entries[key] = selector
|
ss.entries[key] = selector
|
||||||
}
|
}
|
||||||
ss.users[key][user] = struct{}{}
|
ss.users[key][user] = struct{}{}
|
||||||
|
|||||||
+22
-2
@@ -29,6 +29,12 @@ func (w *watcher) ContainerStarted(id string) {
|
|||||||
w.driver.warn("ContainerStarted", "error inspecting container %s: %s", id, err)
|
w.driver.warn("ContainerStarted", "error inspecting container %s: %s", id, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
domain, err := w.weave.DNSDomain()
|
||||||
|
if err != nil {
|
||||||
|
w.driver.warn("ContainerStarted", "unable to get weave dns domain: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
// check that it's on our network
|
// check that it's on our network
|
||||||
for _, net := range info.NetworkSettings.Networks {
|
for _, net := range info.NetworkSettings.Networks {
|
||||||
network, err := w.driver.findNetworkInfo(net.NetworkID)
|
network, err := w.driver.findNetworkInfo(net.NetworkID)
|
||||||
@@ -39,8 +45,22 @@ func (w *watcher) ContainerStarted(id string) {
|
|||||||
if network.isOurs {
|
if network.isOurs {
|
||||||
if w.driver.dns {
|
if w.driver.dns {
|
||||||
fqdn := fmt.Sprintf("%s.%s", info.Config.Hostname, info.Config.Domainname)
|
fqdn := fmt.Sprintf("%s.%s", info.Config.Hostname, info.Config.Domainname)
|
||||||
if err := w.weave.RegisterWithDNS(id, fqdn, net.IPAddress); err != nil {
|
|
||||||
w.driver.warn("ContainerStarted", "unable to register %s with weaveDNS: %s", id, err)
|
aliases := make([]string, 0, len(net.Aliases)+2)
|
||||||
|
aliases = append(aliases, fqdn)
|
||||||
|
|
||||||
|
if len(domain) > 0 && len(info.Name) > 1 && info.Name[0] == '/' {
|
||||||
|
name := fmt.Sprintf("%s.%s", info.Name[1:], domain)
|
||||||
|
aliases = append(aliases, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
aliases = append(aliases, net.Aliases...)
|
||||||
|
|
||||||
|
for _, alias := range aliases {
|
||||||
|
w.driver.debug("ContainerStarted", "going to register %s with weaveDNS", alias)
|
||||||
|
if err := w.weave.RegisterWithDNS(id, alias, net.IPAddress); err != nil {
|
||||||
|
w.driver.warn("ContainerStarted", "unable to register %s with weaveDNS: %s", id, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
netNSPath := weavenet.NSPathByPidWithProc(w.driver.procPath, info.State.Pid)
|
netNSPath := weavenet.NSPathByPidWithProc(w.driver.procPath, info.State.Pid)
|
||||||
|
|||||||
@@ -201,24 +201,6 @@ func (listener *listener) leaveEndpoint(w http.ResponseWriter, r *http.Request)
|
|||||||
emptyOrErrorResponse(w, listener.d.LeaveEndpoint(&l))
|
emptyOrErrorResponse(w, listener.d.LeaveEndpoint(&l))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (listener *listener) discoverNew(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var disco api.DiscoveryNotification
|
|
||||||
if err := json.NewDecoder(r.Body).Decode(&disco); err != nil {
|
|
||||||
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
emptyOrErrorResponse(w, listener.d.DiscoverNew(&disco))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (listener *listener) discoverDelete(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var disco api.DiscoveryNotification
|
|
||||||
if err := json.NewDecoder(r.Body).Decode(&disco); err != nil {
|
|
||||||
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
emptyOrErrorResponse(w, listener.d.DiscoverDelete(&disco))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===
|
// ===
|
||||||
|
|
||||||
func (listener *listener) getIpamCapabilities(w http.ResponseWriter, r *http.Request) {
|
func (listener *listener) getIpamCapabilities(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Kubernetes uses etcd to distribute and synchronise these annotations so we don't
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -38,29 +39,31 @@ const (
|
|||||||
retryPeriod = time.Second * 2
|
retryPeriod = time.Second * 2
|
||||||
jitterFactor = 1.0
|
jitterFactor = 1.0
|
||||||
|
|
||||||
|
progName = "kube-peers.weave.works"
|
||||||
// Prefix all our annotation keys with this string so they don't clash with anyone else's
|
// Prefix all our annotation keys with this string so they don't clash with anyone else's
|
||||||
KubePeersPrefix = "kube-peers.weave.works/"
|
KubePeersPrefix = progName + "/"
|
||||||
// KubePeersAnnotationKey is the default annotation key
|
// KubePeersAnnotationKey is the default annotation key
|
||||||
KubePeersAnnotationKey = KubePeersPrefix + "peers"
|
KubePeersAnnotationKey = KubePeersPrefix + "peers"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (cml *configMapAnnotations) Init() error {
|
func (cml *configMapAnnotations) Init() error {
|
||||||
|
ctx := context.Background()
|
||||||
for {
|
for {
|
||||||
// Since it's potentially racy to GET, then CREATE if not found, we wrap in a check loop
|
// Since it's potentially racy to GET, then CREATE if not found, we wrap in a check loop
|
||||||
// so that if the configmap is created after our GET but before or CREATE, we'll gracefully
|
// so that if the configmap is created after our GET but before or CREATE, we'll gracefully
|
||||||
// re-try to get the configmap.
|
// re-try to get the configmap.
|
||||||
var err error
|
var err error
|
||||||
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Get(cml.ConfigMapName, api.GetOptions{})
|
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Get(ctx, cml.ConfigMapName, api.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !kubeErrors.IsNotFound(err) {
|
if !kubeErrors.IsNotFound(err) {
|
||||||
return errors.Wrapf(err, "Unable to fetch ConfigMap %s/%s", cml.Namespace, cml.ConfigMapName)
|
return errors.Wrapf(err, "Unable to fetch ConfigMap %s/%s", cml.Namespace, cml.ConfigMapName)
|
||||||
}
|
}
|
||||||
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Create(&v1.ConfigMap{
|
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Create(ctx, &v1.ConfigMap{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: cml.ConfigMapName,
|
Name: cml.ConfigMapName,
|
||||||
Namespace: cml.Namespace,
|
Namespace: cml.Namespace,
|
||||||
},
|
},
|
||||||
})
|
}, api.CreateOptions{FieldManager: progName})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if kubeErrors.IsAlreadyExists(err) {
|
if kubeErrors.IsAlreadyExists(err) {
|
||||||
continue
|
continue
|
||||||
@@ -95,29 +98,29 @@ func (cml *configMapAnnotations) GetAnnotation(key string) (string, bool) {
|
|||||||
return value, ok
|
return value, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cml *configMapAnnotations) UpdateAnnotation(key, value string) (err error) {
|
func (cml *configMapAnnotations) UpdateAnnotation(ctx context.Context, key, value string) (err error) {
|
||||||
if cml.cm == nil || cml.cm.Annotations == nil {
|
if cml.cm == nil || cml.cm.Annotations == nil {
|
||||||
return errors.New("endpoint not initialized, call Init first")
|
return errors.New("endpoint not initialized, call Init first")
|
||||||
}
|
}
|
||||||
// speculatively change the state, then replace with whatever comes back
|
// speculatively change the state, then replace with whatever comes back
|
||||||
// from Update(), which will be the latest on the server, or nil if error
|
// from Update(), which will be the latest on the server, or nil if error
|
||||||
cml.cm.Annotations[cleanKey(key)] = value
|
cml.cm.Annotations[cleanKey(key)] = value
|
||||||
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(cml.cm)
|
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(ctx, cml.cm, api.UpdateOptions{FieldManager: progName})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cml *configMapAnnotations) RemoveAnnotation(key string) (err error) {
|
func (cml *configMapAnnotations) RemoveAnnotation(ctx context.Context, key string) (err error) {
|
||||||
if cml.cm == nil || cml.cm.Annotations == nil {
|
if cml.cm == nil || cml.cm.Annotations == nil {
|
||||||
return errors.New("endpoint not initialized, call Init first")
|
return errors.New("endpoint not initialized, call Init first")
|
||||||
}
|
}
|
||||||
// speculatively change the state, then replace with whatever comes back
|
// speculatively change the state, then replace with whatever comes back
|
||||||
// from Update(), which will be the latest on the server, or nil if error
|
// from Update(), which will be the latest on the server, or nil if error
|
||||||
delete(cml.cm.Annotations, cleanKey(key))
|
delete(cml.cm.Annotations, cleanKey(key))
|
||||||
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(cml.cm)
|
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(ctx, cml.cm, api.UpdateOptions{FieldManager: progName})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cml *configMapAnnotations) RemoveAnnotationsWithValue(valueToRemove string) (err error) {
|
func (cml *configMapAnnotations) RemoveAnnotationsWithValue(ctx context.Context, valueToRemove string) (err error) {
|
||||||
if cml.cm == nil || cml.cm.Annotations == nil {
|
if cml.cm == nil || cml.cm.Annotations == nil {
|
||||||
return errors.New("endpoint not initialized, call Init first")
|
return errors.New("endpoint not initialized, call Init first")
|
||||||
}
|
}
|
||||||
@@ -128,7 +131,7 @@ func (cml *configMapAnnotations) RemoveAnnotationsWithValue(valueToRemove string
|
|||||||
delete(cml.cm.Annotations, key) // don't need to clean this key as it came from the map
|
delete(cml.cm.Annotations, key) // don't need to clean this key as it came from the map
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(cml.cm)
|
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(ctx, cml.cm, api.UpdateOptions{FieldManager: progName})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-6
@@ -6,6 +6,7 @@ This involves peer management, such as getting the latest peers or removing defu
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@@ -34,7 +35,8 @@ type nodeInfo struct {
|
|||||||
|
|
||||||
// return the IP addresses of all nodes in the cluster
|
// return the IP addresses of all nodes in the cluster
|
||||||
func getKubePeers(c kubernetes.Interface, includeWithNoIPAddr bool) ([]nodeInfo, error) {
|
func getKubePeers(c kubernetes.Interface, includeWithNoIPAddr bool) ([]nodeInfo, error) {
|
||||||
nodeList, err := c.CoreV1().Nodes().List(api.ListOptions{})
|
ctx := context.Background()
|
||||||
|
nodeList, err := c.CoreV1().Nodes().List(ctx, api.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -155,6 +157,7 @@ func reclaimRemovedPeers(kube kubernetes.Interface, cml *configMapAnnotations, m
|
|||||||
// Return a bool to show whether we attempted to change anything,
|
// Return a bool to show whether we attempted to change anything,
|
||||||
// and an error if something went wrong.
|
// and an error if something went wrong.
|
||||||
func reclaimPeer(weave weaveClient, cml *configMapAnnotations, peerName string, myPeerName string) (changed bool, err error) {
|
func reclaimPeer(weave weaveClient, cml *configMapAnnotations, peerName string, myPeerName string) (changed bool, err error) {
|
||||||
|
ctx := context.Background()
|
||||||
common.Log.Debugln("[kube-peers] Preparing to remove disappeared peer", peerName)
|
common.Log.Debugln("[kube-peers] Preparing to remove disappeared peer", peerName)
|
||||||
okToRemove := false
|
okToRemove := false
|
||||||
nonExistentPeer := false
|
nonExistentPeer := false
|
||||||
@@ -187,7 +190,7 @@ func reclaimPeer(weave weaveClient, cml *configMapAnnotations, peerName string,
|
|||||||
if !found || nonExistentPeer {
|
if !found || nonExistentPeer {
|
||||||
// 5. If non-existent, write an annotation with key X and contents "my identity"
|
// 5. If non-existent, write an annotation with key X and contents "my identity"
|
||||||
common.Log.Debugln("[kube-peers] Noting I plan to remove ", peerName)
|
common.Log.Debugln("[kube-peers] Noting I plan to remove ", peerName)
|
||||||
if err := cml.UpdateAnnotation(KubePeersPrefix+peerName, myPeerName); err == nil {
|
if err := cml.UpdateAnnotation(ctx, KubePeersPrefix+peerName, myPeerName); err == nil {
|
||||||
okToRemove = true
|
okToRemove = true
|
||||||
} else {
|
} else {
|
||||||
common.Log.Errorln("[kube-peers] error from UpdateAnnotation: ", err)
|
common.Log.Errorln("[kube-peers] error from UpdateAnnotation: ", err)
|
||||||
@@ -209,7 +212,7 @@ func reclaimPeer(weave weaveClient, cml *configMapAnnotations, peerName string,
|
|||||||
}
|
}
|
||||||
err = cml.LoopUpdate(func() error {
|
err = cml.LoopUpdate(func() error {
|
||||||
// 7aa. Remove any annotations Z* that have contents X
|
// 7aa. Remove any annotations Z* that have contents X
|
||||||
if err := cml.RemoveAnnotationsWithValue(peerName); err != nil {
|
if err := cml.RemoveAnnotationsWithValue(ctx, peerName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// 7a. Remove X from peerList
|
// 7a. Remove X from peerList
|
||||||
@@ -219,14 +222,14 @@ func reclaimPeer(weave weaveClient, cml *configMapAnnotations, peerName string,
|
|||||||
}
|
}
|
||||||
if storedPeerList.contains(peerName) {
|
if storedPeerList.contains(peerName) {
|
||||||
storedPeerList.remove(peerName)
|
storedPeerList.remove(peerName)
|
||||||
if err := cml.UpdatePeerList(*storedPeerList); err != nil {
|
if err := cml.UpdatePeerList(ctx, *storedPeerList); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
common.Log.Infof("[kube-peers] annotation was removed already for %s", peerName)
|
common.Log.Infof("[kube-peers] annotation was removed already for %s", peerName)
|
||||||
}
|
}
|
||||||
// 7b. Remove annotation with key X
|
// 7b. Remove annotation with key X
|
||||||
return cml.RemoveAnnotation(KubePeersPrefix + peerName)
|
return cml.RemoveAnnotation(ctx, KubePeersPrefix+peerName)
|
||||||
})
|
})
|
||||||
// 8. If step 5 failed due to optimistic lock conflict, stop: someone else is handling X
|
// 8. If step 5 failed due to optimistic lock conflict, stop: someone else is handling X
|
||||||
|
|
||||||
@@ -311,6 +314,8 @@ func main() {
|
|||||||
justReclaim bool
|
justReclaim bool
|
||||||
justCheck bool
|
justCheck bool
|
||||||
justSetNodeStatus bool
|
justSetNodeStatus bool
|
||||||
|
justVersion bool
|
||||||
|
justUID bool
|
||||||
peerName string
|
peerName string
|
||||||
nodeName string
|
nodeName string
|
||||||
logLevel string
|
logLevel string
|
||||||
@@ -320,6 +325,8 @@ func main() {
|
|||||||
flag.BoolVar(&runReclaimDaemon, "run-reclaim-daemon", false, "run background process that reclaim IP space from dead peers ")
|
flag.BoolVar(&runReclaimDaemon, "run-reclaim-daemon", false, "run background process that reclaim IP space from dead peers ")
|
||||||
flag.BoolVar(&justCheck, "check-peer-new", false, "return success if peer name is not stored in annotation")
|
flag.BoolVar(&justCheck, "check-peer-new", false, "return success if peer name is not stored in annotation")
|
||||||
flag.BoolVar(&justSetNodeStatus, "set-node-status", false, "set NodeNetworkUnavailable to false")
|
flag.BoolVar(&justSetNodeStatus, "set-node-status", false, "set NodeNetworkUnavailable to false")
|
||||||
|
flag.BoolVar(&justVersion, "print-k8s-version", false, "print the Kubernetes version and exit")
|
||||||
|
flag.BoolVar(&justUID, "print-uid", false, "print a UID for this installation and exit")
|
||||||
flag.StringVar(&peerName, "peer-name", "unknown", "name of this Weave Net peer")
|
flag.StringVar(&peerName, "peer-name", "unknown", "name of this Weave Net peer")
|
||||||
flag.StringVar(&nodeName, "node-name", "unknown", "name of this Kubernetes node")
|
flag.StringVar(&nodeName, "node-name", "unknown", "name of this Kubernetes node")
|
||||||
flag.StringVar(&logLevel, "log-level", "info", "logging level (debug, info, warning, error)")
|
flag.StringVar(&logLevel, "log-level", "info", "logging level (debug, info, warning, error)")
|
||||||
@@ -368,9 +375,24 @@ func main() {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if justVersion {
|
||||||
|
k8sVersion, err := c.Discovery().ServerVersion()
|
||||||
|
if err != nil {
|
||||||
|
common.Log.Fatalf("[kube-peers] Could not get Kubernetes version: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Println(k8sVersion.String())
|
||||||
|
}
|
||||||
|
if justUID {
|
||||||
|
// use UID of `weave-net` configmap as unique ID of the Kubernetes cluster
|
||||||
|
cm, err := c.CoreV1().ConfigMaps(configMapNamespace).Get(context.Background(), configMapName, api.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
common.Log.Fatalf("Unable to fetch ConfigMap %s/%s to infer unique cluster ID", configMapNamespace, configMapName)
|
||||||
|
}
|
||||||
|
fmt.Println(cm.ObjectMeta.UID)
|
||||||
|
}
|
||||||
if runReclaimDaemon {
|
if runReclaimDaemon {
|
||||||
// Handle SIGINT and SIGTERM
|
// Handle SIGINT and SIGTERM
|
||||||
ch := make(chan os.Signal)
|
ch := make(chan os.Signal, 1)
|
||||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
||||||
stopCh := make(chan struct{})
|
stopCh := make(chan struct{})
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
)
|
)
|
||||||
@@ -24,6 +25,6 @@ func setNodeNetworkUnavailableFalse(c kubernetes.Interface, nodeName string) err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
patch := []byte(fmt.Sprintf(`{"status":{"conditions":%s}}`, raw))
|
patch := []byte(fmt.Sprintf(`{"status":{"conditions":%s}}`, raw))
|
||||||
_, err = c.CoreV1().Nodes().PatchStatus(nodeName, patch)
|
_, err = c.CoreV1().Nodes().PatchStatus(context.Background(), nodeName, patch)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ This module deals with operations on the peerlist backed by Kubernetes' annotati
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@@ -62,12 +63,12 @@ func (cml *configMapAnnotations) GetPeerList() (*peerList, error) {
|
|||||||
return &record, nil
|
return &record, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cml *configMapAnnotations) UpdatePeerList(list peerList) error {
|
func (cml *configMapAnnotations) UpdatePeerList(ctx context.Context, list peerList) error {
|
||||||
recordBytes, err := json.Marshal(list)
|
recordBytes, err := json.Marshal(list)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return cml.UpdateAnnotation(KubePeersAnnotationKey, string(recordBytes))
|
return cml.UpdateAnnotation(ctx, KubePeersAnnotationKey, string(recordBytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the list of all peers that have gone through this code path
|
// update the list of all peers that have gone through this code path
|
||||||
@@ -81,7 +82,7 @@ func addMyselfToPeerList(cml *configMapAnnotations, c kubernetes.Interface, peer
|
|||||||
}
|
}
|
||||||
if !list.contains(peerName) {
|
if !list.contains(peerName) {
|
||||||
list.add(peerName, name)
|
list.add(peerName, name)
|
||||||
err = cml.UpdatePeerList(*list)
|
err = cml.UpdatePeerList(context.Background(), *list)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -16,8 +17,6 @@ const (
|
|||||||
peerName3 = "03:00:00:00:00:00"
|
peerName3 = "03:00:00:00:00:00"
|
||||||
nodeName1 = "fake-node-1"
|
nodeName1 = "fake-node-1"
|
||||||
nodeName2 = "fake-node-2"
|
nodeName2 = "fake-node-2"
|
||||||
|
|
||||||
testIters = 1000
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPeerListBasic(t *testing.T) {
|
func TestPeerListBasic(t *testing.T) {
|
||||||
@@ -46,7 +45,7 @@ func TestPeerListBasic(t *testing.T) {
|
|||||||
|
|
||||||
storedPeerList.remove(peerName1)
|
storedPeerList.remove(peerName1)
|
||||||
require.Equal(t, 1, len(storedPeerList.Peers))
|
require.Equal(t, 1, len(storedPeerList.Peers))
|
||||||
err = cml.UpdatePeerList(*storedPeerList)
|
err = cml.UpdatePeerList(context.Background(), *storedPeerList)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
check1, err = checkIamInPeerList(cml, c, peerName1)
|
check1, err = checkIamInPeerList(cml, c, peerName1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ LABEL maintainer="Weaveworks <help@weave.works>" \
|
|||||||
org.opencontainers.image.source="https://github.com/weaveworks/weave" \
|
org.opencontainers.image.source="https://github.com/weaveworks/weave" \
|
||||||
org.opencontainers.image.vendor="Weaveworks"
|
org.opencontainers.image.vendor="Weaveworks"
|
||||||
|
|
||||||
ADD ./launch.sh ./kube-utils /home/weave/
|
ADD ./init.sh ./launch.sh ./kube-utils /home/weave/
|
||||||
ENTRYPOINT ["/home/weave/launch.sh"]
|
ENTRYPOINT ["/home/weave/launch.sh"]
|
||||||
|
|
||||||
# This label will change for every build, and should therefore be the last layer of the image:
|
# This label will change for every build, and should therefore be the last layer of the image:
|
||||||
|
|||||||
Executable
+64
@@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Initialisation of Weave Net pod: check Linux settings and install CNI plugin
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
modprobe_safe() {
|
||||||
|
modprobe $1 || echo "Ignore the error if \"$1\" is built-in in the kernel" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check whether xt_set actually exists
|
||||||
|
xt_set_exists() {
|
||||||
|
# Clean everything up in advance, in case there's leftovers
|
||||||
|
iptables -w -F WEAVE-KUBE-TEST 2>/dev/null || true
|
||||||
|
iptables -w -X WEAVE-KUBE-TEST 2>/dev/null || true
|
||||||
|
ipset destroy weave-kube-test 2>/dev/null || true
|
||||||
|
|
||||||
|
ipset create weave-kube-test hash:ip
|
||||||
|
iptables -w -t filter -N WEAVE-KUBE-TEST
|
||||||
|
if ! iptables -w -A WEAVE-KUBE-TEST -m set --match-set weave-kube-test src -j DROP; then
|
||||||
|
NOT_EXIST=1
|
||||||
|
fi
|
||||||
|
iptables -w -F WEAVE-KUBE-TEST
|
||||||
|
iptables -w -X WEAVE-KUBE-TEST
|
||||||
|
# delay to allow kernel to clean up - see https://github.com/weaveworks/weave/issues/3847
|
||||||
|
sleep 1
|
||||||
|
ipset destroy weave-kube-test
|
||||||
|
[ -z "$NOT_EXIST" ] || (echo "\"xt_set\" does not exist" >&2 && return 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default for network policy
|
||||||
|
EXPECT_NPC=${EXPECT_NPC:-1}
|
||||||
|
|
||||||
|
# Ensure we have the required modules for NPC
|
||||||
|
if [ "${EXPECT_NPC}" != "0" ]; then
|
||||||
|
modprobe_safe br_netfilter
|
||||||
|
modprobe_safe xt_set
|
||||||
|
xt_set_exists
|
||||||
|
fi
|
||||||
|
|
||||||
|
# kube-proxy requires that bridged traffic passes through netfilter
|
||||||
|
if ! BRIDGE_NF_ENABLED=$(cat /proc/sys/net/bridge/bridge-nf-call-iptables); then
|
||||||
|
echo "Cannot detect bridge-nf support - network policy and iptables mode kubeproxy may not work reliably" >&2
|
||||||
|
else
|
||||||
|
if [ "$BRIDGE_NF_ENABLED" != "1" ]; then
|
||||||
|
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This is where we expect the manifest to map host directories
|
||||||
|
HOST_ROOT=${HOST_ROOT:-/host}
|
||||||
|
|
||||||
|
# Install CNI plugin binary to typical CNI bin location
|
||||||
|
# with fall-back to CNI directory used by kube-up on GCI OS
|
||||||
|
if ! mkdir -p $HOST_ROOT/opt/cni/bin ; then
|
||||||
|
if mkdir -p $HOST_ROOT/home/kubernetes/bin ; then
|
||||||
|
export WEAVE_CNI_PLUGIN_DIR=$HOST_ROOT/home/kubernetes/bin
|
||||||
|
else
|
||||||
|
echo "Failed to install the Weave CNI plugin" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
mkdir -p $HOST_ROOT/etc/cni/net.d
|
||||||
|
export HOST_ROOT
|
||||||
|
/home/weave/weave --local setup-cni
|
||||||
+10
-55
@@ -1,10 +1,10 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
# Launch of Weave Net pod - requires that init.sh has been run previously
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
modprobe_safe() {
|
# If this is run from an older manifest, run the init script here
|
||||||
modprobe $1 || echo "Ignore the error if \"$1\" is built-in in the kernel" >&2
|
[ "${INIT_CONTAINER}" = "true" ] || "$(dirname "$0")/init.sh"
|
||||||
}
|
|
||||||
|
|
||||||
# Setup iptables backend to be legacy or nftable
|
# Setup iptables backend to be legacy or nftable
|
||||||
setup_iptables_backend() {
|
setup_iptables_backend() {
|
||||||
@@ -34,24 +34,6 @@ setup_iptables_backend() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check whether xt_set actually exists
|
|
||||||
xt_set_exists() {
|
|
||||||
# Clean everything up in advance, in case there's leftovers
|
|
||||||
iptables -F WEAVE-KUBE-TEST 2>/dev/null || true
|
|
||||||
iptables -X WEAVE-KUBE-TEST 2>/dev/null || true
|
|
||||||
ipset destroy weave-kube-test 2>/dev/null || true
|
|
||||||
|
|
||||||
ipset create weave-kube-test hash:ip
|
|
||||||
iptables -t filter -N WEAVE-KUBE-TEST
|
|
||||||
if ! iptables -A WEAVE-KUBE-TEST -m set --match-set weave-kube-test src -j DROP; then
|
|
||||||
NOT_EXIST=1
|
|
||||||
fi
|
|
||||||
iptables -F WEAVE-KUBE-TEST
|
|
||||||
iptables -X WEAVE-KUBE-TEST
|
|
||||||
ipset destroy weave-kube-test
|
|
||||||
[ -z "$NOT_EXIST" ] || (echo "\"xt_set\" does not exist" >&2 && return 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_iptables_backend
|
setup_iptables_backend
|
||||||
|
|
||||||
# Default if not supplied - same as weave net default
|
# Default if not supplied - same as weave net default
|
||||||
@@ -68,22 +50,6 @@ DB_PREFIX=${DB_PREFIX:-/weavedb/weave-net}
|
|||||||
# Default for network policy
|
# Default for network policy
|
||||||
EXPECT_NPC=${EXPECT_NPC:-1}
|
EXPECT_NPC=${EXPECT_NPC:-1}
|
||||||
|
|
||||||
# Ensure we have the required modules for NPC
|
|
||||||
if [ "${EXPECT_NPC}" != "0" ]; then
|
|
||||||
modprobe_safe br_netfilter
|
|
||||||
modprobe_safe xt_set
|
|
||||||
xt_set_exists
|
|
||||||
fi
|
|
||||||
|
|
||||||
# kube-proxy requires that bridged traffic passes through netfilter
|
|
||||||
if ! BRIDGE_NF_ENABLED=$(cat /proc/sys/net/bridge/bridge-nf-call-iptables); then
|
|
||||||
echo "Cannot detect bridge-nf support - network policy and iptables mode kubeproxy may not work reliably" >&2
|
|
||||||
else
|
|
||||||
if [ "$BRIDGE_NF_ENABLED" != "1" ]; then
|
|
||||||
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
STATUS_OPTS="--metrics-addr=$METRICS_ADDR"
|
STATUS_OPTS="--metrics-addr=$METRICS_ADDR"
|
||||||
# --status-addr exposes internal information, so only turn it on if asked to.
|
# --status-addr exposes internal information, so only turn it on if asked to.
|
||||||
if [ -n "${WEAVE_STATUS_ADDR}" ]; then
|
if [ -n "${WEAVE_STATUS_ADDR}" ]; then
|
||||||
@@ -96,9 +62,9 @@ if [ "${EXPECT_NPC}" = "0" ]; then
|
|||||||
WEAVE_NPC_OPTS=""
|
WEAVE_NPC_OPTS=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
NO_MASQ_LOCAL_OPT=""
|
NO_MASQ_LOCAL_OPT="--no-masq-local"
|
||||||
if [ -n "${NO_MASQ_LOCAL}" ]; then
|
if [ "${NO_MASQ_LOCAL}" = "0" ]; then
|
||||||
NO_MASQ_LOCAL_OPT="--no-masq-local"
|
NO_MASQ_LOCAL_OPT=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Kubernetes sets HOSTNAME to the host's hostname
|
# Kubernetes sets HOSTNAME to the host's hostname
|
||||||
@@ -152,6 +118,10 @@ fi
|
|||||||
# weaver is running as the DB can only be opened by one process at a time
|
# weaver is running as the DB can only be opened by one process at a time
|
||||||
/usr/bin/weaveutil set-db-flag "$DB_PREFIX" peer-reclaim ok
|
/usr/bin/weaveutil set-db-flag "$DB_PREFIX" peer-reclaim ok
|
||||||
|
|
||||||
|
# couple more variables
|
||||||
|
WEAVE_KUBERNETES_VERSION=$(/home/weave/kube-utils -print-k8s-version)
|
||||||
|
WEAVE_KUBERNETES_UID=$(/home/weave/kube-utils -print-uid)
|
||||||
|
|
||||||
post_start_actions() {
|
post_start_actions() {
|
||||||
# Wait for weave process to become responsive
|
# Wait for weave process to become responsive
|
||||||
while true ; do
|
while true ; do
|
||||||
@@ -159,20 +129,6 @@ post_start_actions() {
|
|||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
|
|
||||||
# Install CNI plugin binary to typical CNI bin location
|
|
||||||
# with fall-back to CNI directory used by kube-up on GCI OS
|
|
||||||
if ! mkdir -p $HOST_ROOT/opt/cni/bin ; then
|
|
||||||
if mkdir -p $HOST_ROOT/home/kubernetes/bin ; then
|
|
||||||
export WEAVE_CNI_PLUGIN_DIR=$HOST_ROOT/home/kubernetes/bin
|
|
||||||
else
|
|
||||||
echo "Failed to install the Weave CNI plugin" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
mkdir -p $HOST_ROOT/etc/cni/net.d
|
|
||||||
export HOST_ROOT
|
|
||||||
/home/weave/weave --local setup-cni
|
|
||||||
|
|
||||||
# Attempt to run the reclaim process, but don't halt the script if it fails
|
# Attempt to run the reclaim process, but don't halt the script if it fails
|
||||||
/home/weave/kube-utils -reclaim -node-name="$HOSTNAME" -peer-name="$PEERNAME" -log-level=debug || true
|
/home/weave/kube-utils -reclaim -node-name="$HOSTNAME" -peer-name="$PEERNAME" -log-level=debug || true
|
||||||
|
|
||||||
@@ -189,7 +145,6 @@ post_start_actions &
|
|||||||
|
|
||||||
/home/weave/weaver $EXTRA_ARGS --port=6783 $(router_bridge_opts) \
|
/home/weave/weaver $EXTRA_ARGS --port=6783 $(router_bridge_opts) \
|
||||||
--name="$PEERNAME" \
|
--name="$PEERNAME" \
|
||||||
--host-root=$HOST_ROOT \
|
|
||||||
--http-addr=$HTTP_ADDR $STATUS_OPTS --docker-api='' --no-dns \
|
--http-addr=$HTTP_ADDR $STATUS_OPTS --docker-api='' --no-dns \
|
||||||
--db-prefix="$DB_PREFIX" \
|
--db-prefix="$DB_PREFIX" \
|
||||||
--ipalloc-range=$IPALLOC_RANGE $NICKNAME_ARG \
|
--ipalloc-range=$IPALLOC_RANGE $NICKNAME_ARG \
|
||||||
|
|||||||
@@ -118,11 +118,34 @@ items:
|
|||||||
labels:
|
labels:
|
||||||
name: weave-net
|
name: weave-net
|
||||||
spec:
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: weave-init
|
||||||
|
image: 'weaveworks/weave-kube:latest'
|
||||||
|
imagePullPolicy: Always
|
||||||
|
command:
|
||||||
|
- /home/weave/init.sh
|
||||||
|
env:
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
volumeMounts:
|
||||||
|
- name: cni-bin
|
||||||
|
mountPath: /host/opt
|
||||||
|
- name: cni-bin2
|
||||||
|
mountPath: /host/home
|
||||||
|
- name: cni-conf
|
||||||
|
mountPath: /host/etc
|
||||||
|
- name: lib-modules
|
||||||
|
mountPath: /lib/modules
|
||||||
|
- name: xtables-lock
|
||||||
|
mountPath: /run/xtables.lock
|
||||||
|
readOnly: false
|
||||||
containers:
|
containers:
|
||||||
- name: weave
|
- name: weave
|
||||||
command:
|
command:
|
||||||
- /home/weave/launch.sh
|
- /home/weave/launch.sh
|
||||||
env:
|
env:
|
||||||
|
- name: INIT_CONTAINER
|
||||||
|
value: "true"
|
||||||
- name: HOSTNAME
|
- name: HOSTNAME
|
||||||
valueFrom:
|
valueFrom:
|
||||||
fieldRef:
|
fieldRef:
|
||||||
@@ -143,16 +166,12 @@ items:
|
|||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: weavedb
|
- name: weavedb
|
||||||
mountPath: /weavedb
|
mountPath: /weavedb
|
||||||
- name: cni-bin
|
|
||||||
mountPath: /host/opt
|
|
||||||
- name: cni-bin2
|
|
||||||
mountPath: /host/home
|
|
||||||
- name: cni-conf
|
|
||||||
mountPath: /host/etc
|
|
||||||
- name: dbus
|
- name: dbus
|
||||||
mountPath: /host/var/lib/dbus
|
mountPath: /host/var/lib/dbus
|
||||||
- name: lib-modules
|
readOnly: true
|
||||||
mountPath: /lib/modules
|
- mountPath: /host/etc/machine-id
|
||||||
|
name: cni-machine-id
|
||||||
|
readOnly: true
|
||||||
- name: xtables-lock
|
- name: xtables-lock
|
||||||
mountPath: /run/xtables.lock
|
mountPath: /run/xtables.lock
|
||||||
readOnly: false
|
readOnly: false
|
||||||
@@ -177,7 +196,7 @@ items:
|
|||||||
readOnly: false
|
readOnly: false
|
||||||
hostNetwork: true
|
hostNetwork: true
|
||||||
dnsPolicy: ClusterFirstWithHostNet
|
dnsPolicy: ClusterFirstWithHostNet
|
||||||
hostPID: true
|
hostPID: false
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
securityContext:
|
securityContext:
|
||||||
seLinuxOptions: {}
|
seLinuxOptions: {}
|
||||||
@@ -200,6 +219,9 @@ items:
|
|||||||
- name: cni-conf
|
- name: cni-conf
|
||||||
hostPath:
|
hostPath:
|
||||||
path: /etc
|
path: /etc
|
||||||
|
- name: cni-machine-id
|
||||||
|
hostPath:
|
||||||
|
path: /etc/machine-id
|
||||||
- name: dbus
|
- name: dbus
|
||||||
hostPath:
|
hostPath:
|
||||||
path: /var/lib/dbus
|
path: /var/lib/dbus
|
||||||
|
|||||||
@@ -1,181 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: List
|
|
||||||
items:
|
|
||||||
- apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: weave-net
|
|
||||||
labels:
|
|
||||||
name: weave-net
|
|
||||||
namespace: kube-system
|
|
||||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: weave-net
|
|
||||||
labels:
|
|
||||||
name: weave-net
|
|
||||||
rules:
|
|
||||||
- apiGroups:
|
|
||||||
- ''
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
- namespaces
|
|
||||||
- nodes
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- extensions
|
|
||||||
resources:
|
|
||||||
- networkpolicies
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: weave-net
|
|
||||||
labels:
|
|
||||||
name: weave-net
|
|
||||||
roleRef:
|
|
||||||
kind: ClusterRole
|
|
||||||
name: weave-net
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: weave-net
|
|
||||||
namespace: kube-system
|
|
||||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: Role
|
|
||||||
metadata:
|
|
||||||
name: weave-net-kube-peer
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
name: weave-net-kube-peer
|
|
||||||
rules:
|
|
||||||
- apiGroups:
|
|
||||||
- ''
|
|
||||||
resources:
|
|
||||||
- configmaps
|
|
||||||
resourceNames:
|
|
||||||
- weave-net
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- update
|
|
||||||
- apiGroups:
|
|
||||||
- ''
|
|
||||||
resources:
|
|
||||||
- configmaps
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: RoleBinding
|
|
||||||
metadata:
|
|
||||||
name: weave-net-kube-peer
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
name: weave-net-kube-peer
|
|
||||||
roleRef:
|
|
||||||
kind: Role
|
|
||||||
name: weave-net-kube-peer
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: weave-net
|
|
||||||
namespace: kube-system
|
|
||||||
- apiVersion: extensions/v1beta1
|
|
||||||
kind: DaemonSet
|
|
||||||
metadata:
|
|
||||||
name: weave-net
|
|
||||||
labels:
|
|
||||||
name: weave-net
|
|
||||||
namespace: kube-system
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
name: weave-net
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: weave
|
|
||||||
command:
|
|
||||||
- /home/weave/launch.sh
|
|
||||||
env:
|
|
||||||
- name: HOSTNAME
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
apiVersion: v1
|
|
||||||
fieldPath: spec.nodeName
|
|
||||||
image: 'weaveworks/weave-kube:latest'
|
|
||||||
imagePullPolicy: Always
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
host: 127.0.0.1
|
|
||||||
path: /status
|
|
||||||
port: 6784
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 50m
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
volumeMounts:
|
|
||||||
- name: weavedb
|
|
||||||
mountPath: /weavedb
|
|
||||||
- name: cni-bin
|
|
||||||
mountPath: /host/opt
|
|
||||||
- name: cni-bin2
|
|
||||||
mountPath: /host/home
|
|
||||||
- name: cni-conf
|
|
||||||
mountPath: /host/etc
|
|
||||||
- name: dbus
|
|
||||||
mountPath: /host/var/lib/dbus
|
|
||||||
- name: lib-modules
|
|
||||||
mountPath: /lib/modules
|
|
||||||
- name: weave-npc
|
|
||||||
env:
|
|
||||||
- name: HOSTNAME
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
apiVersion: v1
|
|
||||||
fieldPath: spec.nodeName
|
|
||||||
image: 'weaveworks/weave-npc:latest'
|
|
||||||
imagePullPolicy: Always
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 50m
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
hostNetwork: true
|
|
||||||
hostPID: true
|
|
||||||
restartPolicy: Always
|
|
||||||
securityContext:
|
|
||||||
seLinuxOptions: {}
|
|
||||||
serviceAccountName: weave-net
|
|
||||||
tolerations:
|
|
||||||
- effect: NoSchedule
|
|
||||||
operator: Exists
|
|
||||||
- effect: NoExecute
|
|
||||||
operator: Exists
|
|
||||||
volumes:
|
|
||||||
- name: weavedb
|
|
||||||
hostPath:
|
|
||||||
path: /var/lib/weave
|
|
||||||
- name: cni-bin
|
|
||||||
hostPath:
|
|
||||||
path: /opt
|
|
||||||
- name: cni-bin2
|
|
||||||
hostPath:
|
|
||||||
path: /home
|
|
||||||
- name: cni-conf
|
|
||||||
hostPath:
|
|
||||||
path: /etc
|
|
||||||
- name: dbus
|
|
||||||
hostPath:
|
|
||||||
path: /var/lib/dbus
|
|
||||||
- name: lib-modules
|
|
||||||
hostPath:
|
|
||||||
path: /lib/modules
|
|
||||||
updateStrategy:
|
|
||||||
type: RollingUpdate
|
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: List
|
|
||||||
items:
|
|
||||||
- apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: weave-net
|
|
||||||
labels:
|
|
||||||
name: weave-net
|
|
||||||
namespace: kube-system
|
|
||||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: weave-net
|
|
||||||
labels:
|
|
||||||
name: weave-net
|
|
||||||
rules:
|
|
||||||
- apiGroups:
|
|
||||||
- ''
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
- namespaces
|
|
||||||
- nodes
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- 'networking.k8s.io'
|
|
||||||
resources:
|
|
||||||
- networkpolicies
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- ''
|
|
||||||
resources:
|
|
||||||
- nodes/status
|
|
||||||
verbs:
|
|
||||||
- patch
|
|
||||||
- update
|
|
||||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: weave-net
|
|
||||||
labels:
|
|
||||||
name: weave-net
|
|
||||||
roleRef:
|
|
||||||
kind: ClusterRole
|
|
||||||
name: weave-net
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: weave-net
|
|
||||||
namespace: kube-system
|
|
||||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: Role
|
|
||||||
metadata:
|
|
||||||
name: weave-net
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
name: weave-net
|
|
||||||
rules:
|
|
||||||
- apiGroups:
|
|
||||||
- ''
|
|
||||||
resources:
|
|
||||||
- configmaps
|
|
||||||
resourceNames:
|
|
||||||
- weave-net
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- update
|
|
||||||
- apiGroups:
|
|
||||||
- ''
|
|
||||||
resources:
|
|
||||||
- configmaps
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
|
||||||
kind: RoleBinding
|
|
||||||
metadata:
|
|
||||||
name: weave-net
|
|
||||||
namespace: kube-system
|
|
||||||
labels:
|
|
||||||
name: weave-net
|
|
||||||
roleRef:
|
|
||||||
kind: Role
|
|
||||||
name: weave-net
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: weave-net
|
|
||||||
namespace: kube-system
|
|
||||||
- apiVersion: extensions/v1beta1
|
|
||||||
kind: DaemonSet
|
|
||||||
metadata:
|
|
||||||
name: weave-net
|
|
||||||
labels:
|
|
||||||
name: weave-net
|
|
||||||
namespace: kube-system
|
|
||||||
spec:
|
|
||||||
# Wait 5 seconds to let pod connect before rolling next pod
|
|
||||||
minReadySeconds: 5
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
name: weave-net
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: weave
|
|
||||||
command:
|
|
||||||
- /home/weave/launch.sh
|
|
||||||
env:
|
|
||||||
- name: HOSTNAME
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
apiVersion: v1
|
|
||||||
fieldPath: spec.nodeName
|
|
||||||
image: 'weaveworks/weave-kube:latest'
|
|
||||||
imagePullPolicy: Always
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
host: 127.0.0.1
|
|
||||||
path: /status
|
|
||||||
port: 6784
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 50m
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
volumeMounts:
|
|
||||||
- name: weavedb
|
|
||||||
mountPath: /weavedb
|
|
||||||
- name: cni-bin
|
|
||||||
mountPath: /host/opt
|
|
||||||
- name: cni-bin2
|
|
||||||
mountPath: /host/home
|
|
||||||
- name: cni-conf
|
|
||||||
mountPath: /host/etc
|
|
||||||
- name: dbus
|
|
||||||
mountPath: /host/var/lib/dbus
|
|
||||||
- name: lib-modules
|
|
||||||
mountPath: /lib/modules
|
|
||||||
- name: xtables-lock
|
|
||||||
mountPath: /run/xtables.lock
|
|
||||||
readOnly: false
|
|
||||||
- name: weave-npc
|
|
||||||
env:
|
|
||||||
- name: HOSTNAME
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
apiVersion: v1
|
|
||||||
fieldPath: spec.nodeName
|
|
||||||
image: 'weaveworks/weave-npc:latest'
|
|
||||||
imagePullPolicy: Always
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 50m
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
volumeMounts:
|
|
||||||
- name: xtables-lock
|
|
||||||
mountPath: /run/xtables.lock
|
|
||||||
readOnly: false
|
|
||||||
hostNetwork: true
|
|
||||||
hostPID: true
|
|
||||||
restartPolicy: Always
|
|
||||||
securityContext:
|
|
||||||
seLinuxOptions: {}
|
|
||||||
serviceAccountName: weave-net
|
|
||||||
tolerations:
|
|
||||||
- effect: NoSchedule
|
|
||||||
operator: Exists
|
|
||||||
- effect: NoExecute
|
|
||||||
operator: Exists
|
|
||||||
volumes:
|
|
||||||
- name: weavedb
|
|
||||||
hostPath:
|
|
||||||
path: /var/lib/weave
|
|
||||||
- name: cni-bin
|
|
||||||
hostPath:
|
|
||||||
path: /opt
|
|
||||||
- name: cni-bin2
|
|
||||||
hostPath:
|
|
||||||
path: /home
|
|
||||||
- name: cni-conf
|
|
||||||
hostPath:
|
|
||||||
path: /etc
|
|
||||||
- name: dbus
|
|
||||||
hostPath:
|
|
||||||
path: /var/lib/dbus
|
|
||||||
- name: lib-modules
|
|
||||||
hostPath:
|
|
||||||
path: /lib/modules
|
|
||||||
- name: xtables-lock
|
|
||||||
hostPath:
|
|
||||||
path: /run/xtables.lock
|
|
||||||
updateStrategy:
|
|
||||||
type: RollingUpdate
|
|
||||||
@@ -115,11 +115,34 @@ items:
|
|||||||
labels:
|
labels:
|
||||||
name: weave-net
|
name: weave-net
|
||||||
spec:
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: weave-init
|
||||||
|
image: 'weaveworks/weave-kube:latest'
|
||||||
|
imagePullPolicy: Always
|
||||||
|
command:
|
||||||
|
- /home/weave/init.sh
|
||||||
|
env:
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
volumeMounts:
|
||||||
|
- name: cni-bin
|
||||||
|
mountPath: /host/opt
|
||||||
|
- name: cni-bin2
|
||||||
|
mountPath: /host/home
|
||||||
|
- name: cni-conf
|
||||||
|
mountPath: /host/etc
|
||||||
|
- name: lib-modules
|
||||||
|
mountPath: /lib/modules
|
||||||
|
- name: xtables-lock
|
||||||
|
mountPath: /run/xtables.lock
|
||||||
|
readOnly: false
|
||||||
containers:
|
containers:
|
||||||
- name: weave
|
- name: weave
|
||||||
command:
|
command:
|
||||||
- /home/weave/launch.sh
|
- /home/weave/launch.sh
|
||||||
env:
|
env:
|
||||||
|
- name: INIT_CONTAINER
|
||||||
|
value: "true"
|
||||||
- name: HOSTNAME
|
- name: HOSTNAME
|
||||||
valueFrom:
|
valueFrom:
|
||||||
fieldRef:
|
fieldRef:
|
||||||
@@ -140,16 +163,12 @@ items:
|
|||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: weavedb
|
- name: weavedb
|
||||||
mountPath: /weavedb
|
mountPath: /weavedb
|
||||||
- name: cni-bin
|
|
||||||
mountPath: /host/opt
|
|
||||||
- name: cni-bin2
|
|
||||||
mountPath: /host/home
|
|
||||||
- name: cni-conf
|
|
||||||
mountPath: /host/etc
|
|
||||||
- name: dbus
|
- name: dbus
|
||||||
mountPath: /host/var/lib/dbus
|
mountPath: /host/var/lib/dbus
|
||||||
- name: lib-modules
|
readOnly: true
|
||||||
mountPath: /lib/modules
|
- mountPath: /host/etc/machine-id
|
||||||
|
name: cni-machine-id
|
||||||
|
readOnly: true
|
||||||
- name: xtables-lock
|
- name: xtables-lock
|
||||||
mountPath: /run/xtables.lock
|
mountPath: /run/xtables.lock
|
||||||
readOnly: false
|
readOnly: false
|
||||||
@@ -173,7 +192,7 @@ items:
|
|||||||
mountPath: /run/xtables.lock
|
mountPath: /run/xtables.lock
|
||||||
readOnly: false
|
readOnly: false
|
||||||
hostNetwork: true
|
hostNetwork: true
|
||||||
hostPID: true
|
hostPID: false
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
securityContext:
|
securityContext:
|
||||||
seLinuxOptions: {}
|
seLinuxOptions: {}
|
||||||
@@ -196,6 +215,9 @@ items:
|
|||||||
- name: cni-conf
|
- name: cni-conf
|
||||||
hostPath:
|
hostPath:
|
||||||
path: /etc
|
path: /etc
|
||||||
|
- name: cni-machine-id
|
||||||
|
hostPath:
|
||||||
|
path: /etc/machine-id
|
||||||
- name: dbus
|
- name: dbus
|
||||||
hostPath:
|
hostPath:
|
||||||
path: /var/lib/dbus
|
path: /var/lib/dbus
|
||||||
|
|||||||
@@ -118,11 +118,34 @@ items:
|
|||||||
labels:
|
labels:
|
||||||
name: weave-net
|
name: weave-net
|
||||||
spec:
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: weave-init
|
||||||
|
image: 'weaveworks/weave-kube:latest'
|
||||||
|
imagePullPolicy: Always
|
||||||
|
command:
|
||||||
|
- /home/weave/init.sh
|
||||||
|
env:
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
volumeMounts:
|
||||||
|
- name: cni-bin
|
||||||
|
mountPath: /host/opt
|
||||||
|
- name: cni-bin2
|
||||||
|
mountPath: /host/home
|
||||||
|
- name: cni-conf
|
||||||
|
mountPath: /host/etc
|
||||||
|
- name: lib-modules
|
||||||
|
mountPath: /lib/modules
|
||||||
|
- name: xtables-lock
|
||||||
|
mountPath: /run/xtables.lock
|
||||||
|
readOnly: false
|
||||||
containers:
|
containers:
|
||||||
- name: weave
|
- name: weave
|
||||||
command:
|
command:
|
||||||
- /home/weave/launch.sh
|
- /home/weave/launch.sh
|
||||||
env:
|
env:
|
||||||
|
- name: INIT_CONTAINER
|
||||||
|
value: "true"
|
||||||
- name: HOSTNAME
|
- name: HOSTNAME
|
||||||
valueFrom:
|
valueFrom:
|
||||||
fieldRef:
|
fieldRef:
|
||||||
@@ -143,16 +166,12 @@ items:
|
|||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: weavedb
|
- name: weavedb
|
||||||
mountPath: /weavedb
|
mountPath: /weavedb
|
||||||
- name: cni-bin
|
|
||||||
mountPath: /host/opt
|
|
||||||
- name: cni-bin2
|
|
||||||
mountPath: /host/home
|
|
||||||
- name: cni-conf
|
|
||||||
mountPath: /host/etc
|
|
||||||
- name: dbus
|
- name: dbus
|
||||||
mountPath: /host/var/lib/dbus
|
mountPath: /host/var/lib/dbus
|
||||||
- name: lib-modules
|
readOnly: true
|
||||||
mountPath: /lib/modules
|
- mountPath: /host/etc/machine-id
|
||||||
|
name: cni-machine-id
|
||||||
|
readOnly: true
|
||||||
- name: xtables-lock
|
- name: xtables-lock
|
||||||
mountPath: /run/xtables.lock
|
mountPath: /run/xtables.lock
|
||||||
readOnly: false
|
readOnly: false
|
||||||
@@ -177,7 +196,7 @@ items:
|
|||||||
readOnly: false
|
readOnly: false
|
||||||
hostNetwork: true
|
hostNetwork: true
|
||||||
dnsPolicy: ClusterFirstWithHostNet
|
dnsPolicy: ClusterFirstWithHostNet
|
||||||
hostPID: true
|
hostPID: false
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
securityContext:
|
securityContext:
|
||||||
seLinuxOptions: {}
|
seLinuxOptions: {}
|
||||||
@@ -200,6 +219,9 @@ items:
|
|||||||
- name: cni-conf
|
- name: cni-conf
|
||||||
hostPath:
|
hostPath:
|
||||||
path: /etc
|
path: /etc
|
||||||
|
- name: cni-machine-id
|
||||||
|
hostPath:
|
||||||
|
path: /etc/machine-id
|
||||||
- name: dbus
|
- name: dbus
|
||||||
hostPath:
|
hostPath:
|
||||||
path: /var/lib/dbus
|
path: /var/lib/dbus
|
||||||
|
|||||||
+55
-46
@@ -1,8 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
goruntime "runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/coreos/go-iptables/iptables"
|
"github.com/coreos/go-iptables/iptables"
|
||||||
@@ -17,6 +20,7 @@ import (
|
|||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/weaveworks/weave/common"
|
||||||
|
"github.com/weaveworks/weave/common/chains"
|
||||||
"github.com/weaveworks/weave/net"
|
"github.com/weaveworks/weave/net"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/weaveworks/weave/net/ipset"
|
||||||
"github.com/weaveworks/weave/npc"
|
"github.com/weaveworks/weave/npc"
|
||||||
@@ -52,27 +56,27 @@ func makeController(getter cache.Getter, resource string,
|
|||||||
|
|
||||||
func resetIPTables(ipt *iptables.IPTables) error {
|
func resetIPTables(ipt *iptables.IPTables) error {
|
||||||
// Flush chains first so there are no refs to extant ipsets
|
// Flush chains first so there are no refs to extant ipsets
|
||||||
if err := ipt.ClearChain(npc.TableFilter, npc.IngressChain); err != nil {
|
if err := ipt.ClearChain(npc.TableFilter, chains.IngressChain); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ipt.ClearChain(npc.TableFilter, npc.DefaultChain); err != nil {
|
if err := ipt.ClearChain(npc.TableFilter, chains.DefaultChain); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ipt.ClearChain(npc.TableFilter, npc.MainChain); err != nil {
|
if err := ipt.ClearChain(npc.TableFilter, chains.MainChain); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ipt.ClearChain(npc.TableFilter, npc.EgressMarkChain); err != nil {
|
if err := ipt.ClearChain(npc.TableFilter, chains.EgressMarkChain); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ipt.ClearChain(npc.TableFilter, npc.EgressCustomChain); err != nil {
|
if err := ipt.ClearChain(npc.TableFilter, chains.EgressCustomChain); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ipt.ClearChain(npc.TableFilter, npc.EgressDefaultChain); err != nil {
|
if err := ipt.ClearChain(npc.TableFilter, chains.EgressDefaultChain); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,35 +125,35 @@ func resetIPSets(ips ipset.Interface) error {
|
|||||||
|
|
||||||
func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
|
func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
|
||||||
// Configure main chain static rules
|
// Configure main chain static rules
|
||||||
if err := ipt.Append(npc.TableFilter, npc.MainChain,
|
if err := ipt.Append(npc.TableFilter, chains.MainChain,
|
||||||
"-m", "state", "--state", "RELATED,ESTABLISHED", "-j", "ACCEPT"); err != nil {
|
"-m", "state", "--state", "RELATED,ESTABLISHED", "-j", "ACCEPT"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if allowMcast {
|
if allowMcast {
|
||||||
if err := ipt.Append(npc.TableFilter, npc.MainChain,
|
if err := ipt.Append(npc.TableFilter, chains.MainChain,
|
||||||
"-d", "224.0.0.0/4", "-j", "ACCEPT"); err != nil {
|
"-d", "224.0.0.0/4", "-j", "ACCEPT"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the destination address is not any of the local pods, let it through
|
// If the destination address is not any of the local pods, let it through
|
||||||
if err := ipt.Append(npc.TableFilter, npc.MainChain,
|
if err := ipt.Append(npc.TableFilter, chains.MainChain,
|
||||||
"-m", "physdev", "--physdev-is-bridged", "--physdev-out="+bridgePortName, "-j", "ACCEPT"); err != nil {
|
"-m", "physdev", "--physdev-is-bridged", "--physdev-out="+bridgePortName, "-j", "ACCEPT"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ipt.Append(npc.TableFilter, npc.MainChain,
|
if err := ipt.Append(npc.TableFilter, chains.MainChain,
|
||||||
"-m", "state", "--state", "NEW", "-j", string(npc.DefaultChain)); err != nil {
|
"-m", "state", "--state", "NEW", "-j", chains.DefaultChain); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ipt.Append(npc.TableFilter, npc.MainChain,
|
if err := ipt.Append(npc.TableFilter, chains.MainChain,
|
||||||
"-m", "state", "--state", "NEW", "-j", string(npc.IngressChain)); err != nil {
|
"-m", "state", "--state", "NEW", "-j", chains.IngressChain); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ipt.Append(npc.TableFilter, npc.EgressMarkChain,
|
if err := ipt.Append(npc.TableFilter, chains.EgressMarkChain,
|
||||||
"-j", "MARK", "--set-xmark", npc.EgressMark); err != nil {
|
"-j", "MARK", "--set-xmark", npc.EgressMark); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -187,16 +191,15 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
|
|||||||
ruleSpecs = append(ruleSpecs, []string{"-d", "224.0.0.0/4", "-j", "RETURN"})
|
ruleSpecs = append(ruleSpecs, []string{"-d", "224.0.0.0/4", "-j", "RETURN"})
|
||||||
}
|
}
|
||||||
ruleSpecs = append(ruleSpecs, [][]string{
|
ruleSpecs = append(ruleSpecs, [][]string{
|
||||||
{"-m", "state", "--state", "NEW", "-j", string(npc.EgressDefaultChain)},
|
{"-m", "state", "--state", "NEW", "-j", chains.EgressDefaultChain},
|
||||||
{"-m", "state", "--state", "NEW", "-m", "mark", "!", "--mark", npc.EgressMark, "-j", string(npc.EgressCustomChain)},
|
{"-m", "state", "--state", "NEW", "-m", "mark", "!", "--mark", npc.EgressMark, "-j", chains.EgressCustomChain},
|
||||||
{"-m", "state", "--state", "NEW", "-m", "mark", "!", "--mark", npc.EgressMark, "-j", "NFLOG", "--nflog-group", "86"},
|
|
||||||
}...)
|
}...)
|
||||||
if err := net.AddChainWithRules(ipt, npc.TableFilter, npc.EgressChain, ruleSpecs); err != nil {
|
if err := net.AddChainWithRules(ipt, npc.TableFilter, chains.EgressChain, ruleSpecs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete `weave-local-pods` ipset which is no longer used by weave-npc
|
// delete `weave-local-pods` ipset which is no longer used by weave-npc
|
||||||
weaveLocalPodExist, err := ipsetExist(ips, npc.LocalIpset)
|
weaveLocalPodExist, err := ips.Exists(npc.LocalIpset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.Log.Errorf("Failed to look if ipset '%s' exists", npc.LocalIpset)
|
common.Log.Errorf("Failed to look if ipset '%s' exists", npc.LocalIpset)
|
||||||
} else if weaveLocalPodExist {
|
} else if weaveLocalPodExist {
|
||||||
@@ -209,20 +212,17 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dummy way to check whether a given ipset exists.
|
// Indirection in case we come up with a more interesting requirement
|
||||||
// TODO(brb) Use "ipset -exist create <..>" for our purpose instead (for some reasons
|
func hCtx() context.Context {
|
||||||
// creating an ipset with -exist fails).
|
return context.Background()
|
||||||
func ipsetExist(ips ipset.Interface, name ipset.Name) (bool, error) {
|
}
|
||||||
sets, err := ips.List(string(name))
|
|
||||||
if err != nil {
|
func stopOnPanicRecover() {
|
||||||
return false, err
|
if r := recover(); r != nil {
|
||||||
|
buf := make([]byte, 1<<20)
|
||||||
|
stacklen := goruntime.Stack(buf, false)
|
||||||
|
handleFatal(fmt.Errorf("panic: %v \n%s", r, buf[:stacklen]))
|
||||||
}
|
}
|
||||||
for _, s := range sets {
|
|
||||||
if s == name {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func root(cmd *cobra.Command, args []string) {
|
func root(cmd *cobra.Command, args []string) {
|
||||||
@@ -263,63 +263,72 @@ func root(cmd *cobra.Command, args []string) {
|
|||||||
|
|
||||||
npc := npc.New(nodeName, ipt, ips, client)
|
npc := npc.New(nodeName, ipt, ips, client)
|
||||||
|
|
||||||
nsController := makeController(client.Core().RESTClient(), "namespaces", &coreapi.Namespace{},
|
nsController := makeController(client.CoreV1().RESTClient(), "namespaces", &coreapi.Namespace{},
|
||||||
cache.ResourceEventHandlerFuncs{
|
cache.ResourceEventHandlerFuncs{
|
||||||
AddFunc: func(obj interface{}) {
|
AddFunc: func(obj interface{}) {
|
||||||
handleError(npc.AddNamespace(obj.(*coreapi.Namespace)))
|
defer stopOnPanicRecover()
|
||||||
|
handleError(npc.AddNamespace(hCtx(), obj.(*coreapi.Namespace)))
|
||||||
},
|
},
|
||||||
DeleteFunc: func(obj interface{}) {
|
DeleteFunc: func(obj interface{}) {
|
||||||
|
defer stopOnPanicRecover()
|
||||||
switch obj := obj.(type) {
|
switch obj := obj.(type) {
|
||||||
case *coreapi.Namespace:
|
case *coreapi.Namespace:
|
||||||
handleError(npc.DeleteNamespace(obj))
|
handleError(npc.DeleteNamespace(hCtx(), obj))
|
||||||
case cache.DeletedFinalStateUnknown:
|
case cache.DeletedFinalStateUnknown:
|
||||||
// We know this object has gone away, but its final state is no longer
|
// We know this object has gone away, but its final state is no longer
|
||||||
// available from the API server. Instead we use the last copy of it
|
// available from the API server. Instead we use the last copy of it
|
||||||
// that we have, which is good enough for our cleanup.
|
// that we have, which is good enough for our cleanup.
|
||||||
handleError(npc.DeleteNamespace(obj.Obj.(*coreapi.Namespace)))
|
handleError(npc.DeleteNamespace(hCtx(), obj.Obj.(*coreapi.Namespace)))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UpdateFunc: func(old, new interface{}) {
|
UpdateFunc: func(old, new interface{}) {
|
||||||
handleError(npc.UpdateNamespace(old.(*coreapi.Namespace), new.(*coreapi.Namespace)))
|
defer stopOnPanicRecover()
|
||||||
|
handleError(npc.UpdateNamespace(hCtx(), old.(*coreapi.Namespace), new.(*coreapi.Namespace)))
|
||||||
}})
|
}})
|
||||||
|
|
||||||
podController := makeController(client.Core().RESTClient(), "pods", &coreapi.Pod{},
|
podController := makeController(client.CoreV1().RESTClient(), "pods", &coreapi.Pod{},
|
||||||
cache.ResourceEventHandlerFuncs{
|
cache.ResourceEventHandlerFuncs{
|
||||||
AddFunc: func(obj interface{}) {
|
AddFunc: func(obj interface{}) {
|
||||||
handleError(npc.AddPod(obj.(*coreapi.Pod)))
|
defer stopOnPanicRecover()
|
||||||
|
handleError(npc.AddPod(hCtx(), obj.(*coreapi.Pod)))
|
||||||
},
|
},
|
||||||
DeleteFunc: func(obj interface{}) {
|
DeleteFunc: func(obj interface{}) {
|
||||||
|
defer stopOnPanicRecover()
|
||||||
switch obj := obj.(type) {
|
switch obj := obj.(type) {
|
||||||
case *coreapi.Pod:
|
case *coreapi.Pod:
|
||||||
handleError(npc.DeletePod(obj))
|
handleError(npc.DeletePod(hCtx(), obj))
|
||||||
case cache.DeletedFinalStateUnknown:
|
case cache.DeletedFinalStateUnknown:
|
||||||
// We know this object has gone away, but its final state is no longer
|
// We know this object has gone away, but its final state is no longer
|
||||||
// available from the API server. Instead we use the last copy of it
|
// available from the API server. Instead we use the last copy of it
|
||||||
// that we have, which is good enough for our cleanup.
|
// that we have, which is good enough for our cleanup.
|
||||||
handleError(npc.DeletePod(obj.Obj.(*coreapi.Pod)))
|
handleError(npc.DeletePod(hCtx(), obj.Obj.(*coreapi.Pod)))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UpdateFunc: func(old, new interface{}) {
|
UpdateFunc: func(old, new interface{}) {
|
||||||
handleError(npc.UpdatePod(old.(*coreapi.Pod), new.(*coreapi.Pod)))
|
defer stopOnPanicRecover()
|
||||||
|
handleError(npc.UpdatePod(hCtx(), old.(*coreapi.Pod), new.(*coreapi.Pod)))
|
||||||
}})
|
}})
|
||||||
|
|
||||||
npHandlers := cache.ResourceEventHandlerFuncs{
|
npHandlers := cache.ResourceEventHandlerFuncs{
|
||||||
AddFunc: func(obj interface{}) {
|
AddFunc: func(obj interface{}) {
|
||||||
handleError(npc.AddNetworkPolicy(obj))
|
defer stopOnPanicRecover()
|
||||||
|
handleError(npc.AddNetworkPolicy(hCtx(), obj))
|
||||||
},
|
},
|
||||||
DeleteFunc: func(obj interface{}) {
|
DeleteFunc: func(obj interface{}) {
|
||||||
|
defer stopOnPanicRecover()
|
||||||
switch obj := obj.(type) {
|
switch obj := obj.(type) {
|
||||||
case cache.DeletedFinalStateUnknown:
|
case cache.DeletedFinalStateUnknown:
|
||||||
// We know this object has gone away, but its final state is no longer
|
// We know this object has gone away, but its final state is no longer
|
||||||
// available from the API server. Instead we use the last copy of it
|
// available from the API server. Instead we use the last copy of it
|
||||||
// that we have, which is good enough for our cleanup.
|
// that we have, which is good enough for our cleanup.
|
||||||
handleError(npc.DeleteNetworkPolicy(obj.Obj))
|
handleError(npc.DeleteNetworkPolicy(hCtx(), obj.Obj))
|
||||||
default:
|
default:
|
||||||
handleError(npc.DeleteNetworkPolicy(obj))
|
handleError(npc.DeleteNetworkPolicy(hCtx(), obj))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UpdateFunc: func(old, new interface{}) {
|
UpdateFunc: func(old, new interface{}) {
|
||||||
handleError(npc.UpdateNetworkPolicy(old, new))
|
defer stopOnPanicRecover()
|
||||||
|
handleError(npc.UpdateNetworkPolicy(hCtx(), old, new))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
npController = makeController(client.NetworkingV1().RESTClient(), "networkpolicies", &networkingv1.NetworkPolicy{}, npHandlers)
|
npController = makeController(client.NetworkingV1().RESTClient(), "networkpolicies", &networkingv1.NetworkPolicy{}, npHandlers)
|
||||||
|
|||||||
@@ -21,11 +21,9 @@ CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/
|
|||||||
|
|
||||||
RUN apk add --update \
|
RUN apk add --update \
|
||||||
curl \
|
curl \
|
||||||
ethtool \
|
|
||||||
iptables \
|
iptables \
|
||||||
ipset \
|
ipset \
|
||||||
iproute2 \
|
iproute2 \
|
||||||
util-linux \
|
|
||||||
conntrack-tools \
|
conntrack-tools \
|
||||||
bind-tools \
|
bind-tools \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
|
|||||||
+10
-37
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -9,9 +10,6 @@ import (
|
|||||||
|
|
||||||
checkpoint "github.com/weaveworks/go-checkpoint"
|
checkpoint "github.com/weaveworks/go-checkpoint"
|
||||||
weave "github.com/weaveworks/weave/router"
|
weave "github.com/weaveworks/weave/router"
|
||||||
api "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/client-go/kubernetes"
|
|
||||||
"k8s.io/client-go/rest"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var checker *checkpoint.Checker
|
var checker *checkpoint.Checker
|
||||||
@@ -19,9 +17,7 @@ var newVersion atomic.Value
|
|||||||
var success atomic.Value
|
var success atomic.Value
|
||||||
|
|
||||||
const (
|
const (
|
||||||
updateCheckPeriod = 6 * time.Hour
|
updateCheckPeriod = 6 * time.Hour
|
||||||
configMapName = "weave-net"
|
|
||||||
configMapNamespace = "kube-system"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func checkForUpdates(dockerVersion string, router *weave.NetworkRouter, clusterSize uint) {
|
func checkForUpdates(dockerVersion string, router *weave.NetworkRouter, clusterSize uint) {
|
||||||
@@ -60,7 +56,7 @@ func checkForUpdates(dockerVersion string, router *weave.NetworkRouter, clusterS
|
|||||||
"kernel-version": kernelVersion,
|
"kernel-version": kernelVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
checkpointKubernetes(flags, clusterSize)
|
checkpointKubernetes(context.Background(), flags, clusterSize)
|
||||||
|
|
||||||
// Start background version checking
|
// Start background version checking
|
||||||
params := checkpoint.CheckParams{
|
params := checkpoint.CheckParams{
|
||||||
@@ -87,36 +83,13 @@ func checkpointFlags(router *weave.NetworkRouter) []checkpoint.Flag {
|
|||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkpoint Kubernetes specific details
|
// checkpoint Kubernetes specific details, passed in from launch script
|
||||||
func checkpointKubernetes(flags map[string]string, clusterSize uint) {
|
func checkpointKubernetes(ctx context.Context, flags map[string]string, clusterSize uint) {
|
||||||
// checks if weaver is running in Kubernetes
|
version := os.Getenv("WEAVE_KUBERNETES_VERSION")
|
||||||
host := os.Getenv("KUBERNETES_SERVICE_HOST")
|
if len(version) == 0 {
|
||||||
if len(host) == 0 {
|
return // not running under Kubernetes
|
||||||
return
|
|
||||||
}
|
}
|
||||||
config, err := rest.InClusterConfig()
|
flags["kubernetes-version"] = version
|
||||||
if err != nil {
|
flags["kubernetes-cluster-uid"] = string(os.Getenv("WEAVE_KUBERNETES_UID"))
|
||||||
Log.Printf("Could not get Kubernetes in-cluster config: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c, err := kubernetes.NewForConfig(config)
|
|
||||||
if err != nil {
|
|
||||||
Log.Printf("Could not make Kubernetes client: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
k8sVersion, err := c.Discovery().ServerVersion()
|
|
||||||
if err != nil {
|
|
||||||
Log.Printf("Could not get Kubernetes version: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
flags["kubernetes-version"] = k8sVersion.String()
|
|
||||||
|
|
||||||
// use UID of `weave-net` configmap as unique ID of the Kubenerets cluster
|
|
||||||
cm, err := c.CoreV1().ConfigMaps(configMapNamespace).Get(configMapName, api.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
Log.Printf("Unable to fetch ConfigMap %s/%s to infer unique cluster ID", configMapNamespace, configMapName)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
flags["kubernetes-cluster-uid"] = string(cm.ObjectMeta.UID)
|
|
||||||
flags["kubernetes-cluster-size"] = fmt.Sprint(clusterSize)
|
flags["kubernetes-cluster-size"] = fmt.Sprint(clusterSize)
|
||||||
}
|
}
|
||||||
+22
-7
@@ -55,10 +55,7 @@ type dnsConfig struct {
|
|||||||
|
|
||||||
// return the address part of the DNS listen address, without ":53" on the end
|
// return the address part of the DNS listen address, without ":53" on the end
|
||||||
func (c dnsConfig) addressOnly() string {
|
func (c dnsConfig) addressOnly() string {
|
||||||
addr, _, err := net.SplitHostPort(c.ListenAddress)
|
addr, _, _ := net.SplitHostPort(c.ListenAddress)
|
||||||
if err != nil {
|
|
||||||
Log.Fatalf("Error when parsing DNS listen address %q: %s", c.ListenAddress, err)
|
|
||||||
}
|
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,8 +310,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ips := ipset.New(common.LogLogger(), 0)
|
ips := ipset.New(common.LogLogger(), 0)
|
||||||
|
err = weavenet.ResetIPTables(&bridgeConfig, ips)
|
||||||
|
checkFatal(err)
|
||||||
bridgeType, err := weavenet.EnsureBridge(procPath, &bridgeConfig, Log, ips)
|
bridgeType, err := weavenet.EnsureBridge(procPath, &bridgeConfig, Log, ips)
|
||||||
checkFatal(err)
|
checkFatal(err)
|
||||||
|
|
||||||
Log.Println("Bridge type is", bridgeType)
|
Log.Println("Bridge type is", bridgeType)
|
||||||
|
|
||||||
config.Password = determinePassword(password)
|
config.Password = determinePassword(password)
|
||||||
@@ -461,6 +461,8 @@ func main() {
|
|||||||
pluginConfig.ProcPath = procPath
|
pluginConfig.ProcPath = procPath
|
||||||
plugin := plugin.NewPlugin(pluginConfig)
|
plugin := plugin.NewPlugin(pluginConfig)
|
||||||
|
|
||||||
|
metricsHandler := metricsHandler(router, allocator, ns, dnsserver)
|
||||||
|
|
||||||
// The weave script always waits for a status call to succeed,
|
// The weave script always waits for a status call to succeed,
|
||||||
// so there is no point in doing "weave launch --http-addr ''".
|
// so there is no point in doing "weave launch --http-addr ''".
|
||||||
// This is here to support stand-alone use of weaver.
|
// This is here to support stand-alone use of weaver.
|
||||||
@@ -471,11 +473,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
if ns != nil {
|
if ns != nil {
|
||||||
ns.HandleHTTP(muxRouter, dockerCli)
|
ns.HandleHTTP(muxRouter, dockerCli)
|
||||||
|
dnsserver.HandleHTTP(muxRouter)
|
||||||
}
|
}
|
||||||
router.HandleHTTP(muxRouter)
|
router.HandleHTTP(muxRouter)
|
||||||
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, proxy, plugin, &waitReady)
|
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, proxy, plugin, &waitReady)
|
||||||
HandleHTTPPeer(muxRouter, allocator, discoveryEndpoint, token, name.String())
|
HandleHTTPPeer(muxRouter, allocator, discoveryEndpoint, token, name.String())
|
||||||
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver))
|
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler)
|
||||||
if proxy != nil {
|
if proxy != nil {
|
||||||
muxRouter.Methods("GET").Path("/proxyaddrs").HandlerFunc(proxy.StatusHTTP)
|
muxRouter.Methods("GET").Path("/proxyaddrs").HandlerFunc(proxy.StatusHTTP)
|
||||||
}
|
}
|
||||||
@@ -487,7 +490,7 @@ func main() {
|
|||||||
if statusAddr != "" {
|
if statusAddr != "" {
|
||||||
muxRouter := mux.NewRouter()
|
muxRouter := mux.NewRouter()
|
||||||
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, proxy, plugin, &waitReady)
|
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, proxy, plugin, &waitReady)
|
||||||
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver))
|
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler)
|
||||||
statusMux := http.NewServeMux()
|
statusMux := http.NewServeMux()
|
||||||
statusMux.Handle("/", muxRouter)
|
statusMux.Handle("/", muxRouter)
|
||||||
Log.Println("Listening for status+metrics requests on", statusAddr)
|
Log.Println("Listening for status+metrics requests on", statusAddr)
|
||||||
@@ -496,7 +499,7 @@ func main() {
|
|||||||
|
|
||||||
if metricsAddr != "" {
|
if metricsAddr != "" {
|
||||||
metricsMux := http.NewServeMux()
|
metricsMux := http.NewServeMux()
|
||||||
metricsMux.Handle("/metrics", metricsHandler(router, allocator, ns, dnsserver))
|
metricsMux.Handle("/metrics", metricsHandler)
|
||||||
Log.Println("Listening for metrics requests on", metricsAddr)
|
Log.Println("Listening for metrics requests on", metricsAddr)
|
||||||
go listenAndServeHTTP(metricsAddr, metricsMux)
|
go listenAndServeHTTP(metricsAddr, metricsMux)
|
||||||
}
|
}
|
||||||
@@ -512,6 +515,18 @@ func main() {
|
|||||||
go exposeForAWSVPC(allocator, defaultSubnet, bridgeConfig.WeaveBridgeName, waitReady.Add())
|
go exposeForAWSVPC(allocator, defaultSubnet, bridgeConfig.WeaveBridgeName, waitReady.Add())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applyIPTables := func() {
|
||||||
|
Log.Info("Re-configuring iptables")
|
||||||
|
err := weavenet.ConfigureIPTables(&bridgeConfig, ips)
|
||||||
|
if err != nil {
|
||||||
|
Log.Errorf("Error configuring iptables: %s", err)
|
||||||
|
}
|
||||||
|
weavenet.Reexpose(&bridgeConfig, Log)
|
||||||
|
}
|
||||||
|
stopChan := make(chan struct{})
|
||||||
|
go weavenet.MonitorForIptablesFlush(Log, "WEAVE-CANARY", []string{"mangle", "nat", "filter"}, applyIPTables, 10*time.Second, stopChan)
|
||||||
|
defer close(stopChan)
|
||||||
|
|
||||||
signals.SignalHandlerLoop(common.Log, router)
|
signals.SignalHandlerLoop(common.Log, router)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+24
-10
@@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
@@ -14,10 +13,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func metricsHandler(router *weave.NetworkRouter, allocator *ipam.Allocator, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer) http.Handler {
|
func metricsHandler(router *weave.NetworkRouter, allocator *ipam.Allocator, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer) http.Handler {
|
||||||
reg := prometheus.NewRegistry()
|
reg := prometheus.DefaultRegisterer
|
||||||
reg.MustRegister(prometheus.NewProcessCollector(os.Getpid(), ""))
|
|
||||||
reg.MustRegister(newMetrics(router, allocator, ns, dnsserver))
|
reg.MustRegister(newMetrics(router, allocator, ns, dnsserver))
|
||||||
return promhttp.HandlerFor(reg, promhttp.HandlerOpts{})
|
return promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{})
|
||||||
}
|
}
|
||||||
|
|
||||||
type collector struct {
|
type collector struct {
|
||||||
@@ -44,14 +42,30 @@ func uint64Counter(desc *prometheus.Desc, val uint64, labels ...string) promethe
|
|||||||
}
|
}
|
||||||
|
|
||||||
var metrics = []metric{
|
var metrics = []metric{
|
||||||
{desc("weave_connections", "Number of peer-to-peer connections.", "state"),
|
{desc("weave_connections", "Number of peer-to-peer connections.", "state", "type", "encryption"),
|
||||||
func(s WeaveStatus, desc *prometheus.Desc, ch chan<- prometheus.Metric) {
|
func(s WeaveStatus, desc *prometheus.Desc, ch chan<- prometheus.Metric) {
|
||||||
counts := make(map[string]int)
|
counts := make(map[ /*state*/ string]map[ /*type*/ string]struct{ encrypted, unencrypted int })
|
||||||
for _, conn := range s.Router.Connections {
|
|
||||||
counts[conn.State]++
|
|
||||||
}
|
|
||||||
for _, state := range allConnectionStates {
|
for _, state := range allConnectionStates {
|
||||||
ch <- intGauge(desc, counts[state], state)
|
counts[state] = make(map[string]struct{ encrypted, unencrypted int })
|
||||||
|
}
|
||||||
|
for _, conn := range s.Router.Connections {
|
||||||
|
typeName := "unknown"
|
||||||
|
if t, ok := conn.Attrs["name"]; ok {
|
||||||
|
typeName = t.(string)
|
||||||
|
}
|
||||||
|
c := counts[conn.State][typeName]
|
||||||
|
if e, ok := conn.Attrs["encrypted"]; ok && e.(bool) {
|
||||||
|
c.encrypted++
|
||||||
|
} else {
|
||||||
|
c.unencrypted++
|
||||||
|
}
|
||||||
|
counts[conn.State][typeName] = c
|
||||||
|
}
|
||||||
|
for state, stateCounts := range counts {
|
||||||
|
for connType, count := range stateCounts {
|
||||||
|
ch <- intGauge(desc, count.encrypted, state, connType, "yes")
|
||||||
|
ch <- intGauge(desc, count.unencrypted, state, connType, "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
{desc("weave_connection_terminations_total", "Number of peer-to-peer connections terminated."),
|
{desc("weave_connection_terminations_total", "Number of peer-to-peer connections terminated."),
|
||||||
|
|||||||
+1
-3
@@ -15,10 +15,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
containerIDRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/([^/]*)/.*")
|
containerIDRegexp = regexp.MustCompile(`^(/v[0-9.]*)?/containers/([^/]*)/.*`)
|
||||||
weaveWaitEntrypoint = []string{"/w/w"}
|
weaveWaitEntrypoint = []string{"/w/w"}
|
||||||
weaveEntrypoint = "/home/weave/weaver"
|
|
||||||
weaveContainerName = "/weave"
|
|
||||||
|
|
||||||
Log = common.Log
|
Log = common.Log
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -334,13 +334,13 @@ func (fwd *overlaySwitchForwarder) healthCheck(index int, healthy bool) {
|
|||||||
fwd.lock.Lock()
|
fwd.lock.Lock()
|
||||||
defer fwd.lock.Unlock()
|
defer fwd.lock.Unlock()
|
||||||
|
|
||||||
if healthy == true && fwd.forwarders[index].onHold {
|
if healthy && fwd.forwarders[index].onHold {
|
||||||
log.Debug(fwd.logPrefix(), "Adding "+fwd.forwarders[index].overlayName+" to the list of forwarders")
|
log.Debug(fwd.logPrefix(), "Adding "+fwd.forwarders[index].overlayName+" to the list of forwarders")
|
||||||
fwd.forwarders[index].onHold = false
|
fwd.forwarders[index].onHold = false
|
||||||
fwd.chooseBest()
|
fwd.chooseBest()
|
||||||
}
|
}
|
||||||
|
|
||||||
if healthy == false && !fwd.forwarders[index].onHold {
|
if !healthy && !fwd.forwarders[index].onHold {
|
||||||
log.Debug(fwd.logPrefix(), "Removing "+fwd.forwarders[index].overlayName+" from the list of forwarders")
|
log.Debug(fwd.logPrefix(), "Removing "+fwd.forwarders[index].overlayName+" from the list of forwarders")
|
||||||
fwd.forwarders[index].onHold = true
|
fwd.forwarders[index].onHold = true
|
||||||
fwd.chooseBest()
|
fwd.chooseBest()
|
||||||
@@ -452,6 +452,7 @@ func (fwd *overlaySwitchForwarder) Stop() {
|
|||||||
fwd.lock.Lock()
|
fwd.lock.Lock()
|
||||||
defer fwd.lock.Unlock()
|
defer fwd.lock.Unlock()
|
||||||
fwd.stopFrom(0)
|
fwd.stopFrom(0)
|
||||||
|
close(fwd.stopChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fwd *overlaySwitchForwarder) ControlMessage(tag byte, msg []byte) {
|
func (fwd *overlaySwitchForwarder) ControlMessage(tag byte, msg []byte) {
|
||||||
|
|||||||
+1
-1
@@ -147,7 +147,7 @@ func (p *Pcap) sniff(readHandle *pcap.Handle, consumer Consumer) {
|
|||||||
// in order to prevent the next capture from
|
// in order to prevent the next capture from
|
||||||
// overwriting the data
|
// overwriting the data
|
||||||
pktLen := len(pkt)
|
pktLen := len(pkt)
|
||||||
pktCopy := make([]byte, pktLen, pktLen)
|
pktCopy := make([]byte, pktLen)
|
||||||
copy(pktCopy, pkt)
|
copy(pktCopy, pkt)
|
||||||
|
|
||||||
fop.Process(pktCopy, dec, false)
|
fop.Process(pktCopy, dec, false)
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ This is a prerequisite to use use role-based access control on GKE. Please see t
|
|||||||
EKS by default installs `amazon-vpc-cni-k8s` CNI. Please follow below steps to use Weave-net as CNI
|
EKS by default installs `amazon-vpc-cni-k8s` CNI. Please follow below steps to use Weave-net as CNI
|
||||||
|
|
||||||
- create EKS cluster in any of [prescribed](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html) way
|
- create EKS cluster in any of [prescribed](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html) way
|
||||||
- delete `amazon-vpc-cni-k8s` deamonset by running `kubectl delete ds aws-node -n kube-system` command
|
- delete `amazon-vpc-cni-k8s` daemonset by running `kubectl delete ds aws-node -n kube-system` command
|
||||||
- delete `/etc/cni/net.d/10-aws.conflist` on each of the node
|
- delete `/etc/cni/net.d/10-aws.conflist` on each of the node
|
||||||
- edit instance security group to allow TCP 6783 and UDP 6783/6784 ports
|
- edit instance security group to allow TCP 6783 and UDP 6783/6784 ports
|
||||||
- flush iptables nat, mangle, filter tables to clear any iptables configurations done by `amazon-vpc-cni-k8s`
|
- flush iptables nat, mangle, filter tables to clear any iptables configurations done by `amazon-vpc-cni-k8s`
|
||||||
@@ -421,9 +421,9 @@ The list of variables you can set is:
|
|||||||
a larger size for better performance if your network supports jumbo
|
a larger size for better performance if your network supports jumbo
|
||||||
frames - see [here](/site/tasks/manage/fastdp.md#mtu) for more
|
frames - see [here](/site/tasks/manage/fastdp.md#mtu) for more
|
||||||
details.
|
details.
|
||||||
* `NO_MASQ_LOCAL` - set to 1 to preserve the client source IP address when
|
* `NO_MASQ_LOCAL` - set to 0 to disable preserving the client source IP address when
|
||||||
accessing Service annotated with `service.spec.externalTrafficPolicy=Local`.
|
accessing Service annotated with `service.spec.externalTrafficPolicy=Local`.
|
||||||
The feature works only with Weave IPAM (default).
|
This feature works only with Weave IPAM (default).
|
||||||
* `IPTABLES_BACKEND` - set to `nft` to use `nftables` backend for `iptables` (default is `iptables`)
|
* `IPTABLES_BACKEND` - set to `nft` to use `nftables` backend for `iptables` (default is `iptables`)
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: Monitoring with Prometheus
|
title: Monitoring Weave Net with Prometheus
|
||||||
menu_order: 90
|
menu_order: 90
|
||||||
search_type: Documentation
|
search_type: Documentation
|
||||||
---
|
---
|
||||||
@@ -51,107 +51,103 @@ Set it to an empty string to disable.
|
|||||||
You can also pass the parameter `--metrics-addr=X.X.X.X:PORT` to
|
You can also pass the parameter `--metrics-addr=X.X.X.X:PORT` to
|
||||||
`weave launch` to specify an address to listen for metrics only.
|
`weave launch` to specify an address to listen for metrics only.
|
||||||
|
|
||||||
# Static Configuration for Weave Net
|
# Weave Net Monitoring Setup in Kubernetes using kube-prometheus
|
||||||
|
|
||||||
The following YAML fragment can be used in your Prometheus configuration to
|
Weave Net monitoring can be setup in Kubernetes using the kube-prometheus [library](https://github.com/coreos/kube-prometheus/blob/master/jsonnet/kube-prometheus/kube-prometheus-weave-net.libsonnet) for Weave Net. You can read about the example document [here](https://github.com/coreos/kube-prometheus/blob/master/docs/weave-net-support.md).
|
||||||
scrape the router metrics endpoint:
|
|
||||||
|
|
||||||
|
Let's setup weave monitoring using [kube-prometheus](https://github.com/coreos/kube-prometheus).
|
||||||
|
|
||||||
|
#### Install golang
|
||||||
|
Follow this [document](https://golang.org/doc/install/source)
|
||||||
|
|
||||||
|
#### Install jssonet builder
|
||||||
```
|
```
|
||||||
scrape_configs:
|
go get github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb
|
||||||
- job_name: 'weave'
|
|
||||||
scrape_interval: 15s
|
|
||||||
static_configs:
|
|
||||||
- targets: ['localhost:6782']
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Discovery Configuration for Kubernetes
|
#### Install jsonnet
|
||||||
|
Follow this [document](https://github.com/google/jsonnet#building-jsonnet)
|
||||||
|
|
||||||
If you're running Weave in conjunction with Kubernetes, it is possible
|
#### Install gojsonyaml
|
||||||
to discover the endpoints for all nodes automatically. The following
|
```
|
||||||
Kubernetes config will install and configure Prometheus 1.3 on your
|
go get github.com/brancz/gojsontoyaml
|
||||||
cluster and configure it to discover and scrape the Weave endpoints:
|
```
|
||||||
|
|
||||||
|
#### Update dependencies
|
||||||
```
|
```
|
||||||
---
|
jb update
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: prometheus
|
|
||||||
data:
|
|
||||||
prometheus.yml: |-
|
|
||||||
global:
|
|
||||||
scrape_interval: 15s
|
|
||||||
scrape_configs:
|
|
||||||
- job_name: 'weave'
|
|
||||||
kubernetes_sd_configs:
|
|
||||||
- api_server:
|
|
||||||
role: pod
|
|
||||||
relabel_configs:
|
|
||||||
- source_labels: [__meta_kubernetes_namespace,__meta_kubernetes_pod_label_name]
|
|
||||||
action: keep
|
|
||||||
regex: ^kube-system;weave-net$
|
|
||||||
- source_labels: [__meta_kubernetes_pod_container_name,__address__]
|
|
||||||
action: replace
|
|
||||||
target_label: __address__
|
|
||||||
regex: ^weave;(.+?)(?::\d+)?$
|
|
||||||
replacement: $1:6782
|
|
||||||
- source_labels: [__meta_kubernetes_pod_container_name,__address__]
|
|
||||||
action: replace
|
|
||||||
target_label: __address__
|
|
||||||
regex: ^weave-npc;(.+?)(?::\d+)?$
|
|
||||||
replacement: $1:6781
|
|
||||||
- source_labels: [__meta_kubernetes_pod_container_name]
|
|
||||||
action: replace
|
|
||||||
target_label: job
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
name: prometheus
|
|
||||||
name: prometheus
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app: prometheus
|
|
||||||
type: NodePort
|
|
||||||
ports:
|
|
||||||
- name: prometheus
|
|
||||||
protocol: TCP
|
|
||||||
port: 9090
|
|
||||||
nodePort: 30900
|
|
||||||
---
|
|
||||||
apiVersion: extensions/v1beta1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: prometheus
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: prometheus
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
name: prometheus
|
|
||||||
labels:
|
|
||||||
app: prometheus
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: prometheus
|
|
||||||
image: prom/prometheus:v1.3.0
|
|
||||||
args:
|
|
||||||
- '-config.file=/etc/prometheus/prometheus.yml'
|
|
||||||
ports:
|
|
||||||
- name: web
|
|
||||||
containerPort: 9090
|
|
||||||
volumeMounts:
|
|
||||||
- name: config-volume
|
|
||||||
mountPath: /etc/prometheus
|
|
||||||
volumes:
|
|
||||||
- name: config-volume
|
|
||||||
configMap:
|
|
||||||
name: prometheus
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Create weave-net.jsonnet
|
||||||
|
**Note:** Some alert configurations are environment specific and may require modifications of alert thresholds.
|
||||||
|
```
|
||||||
|
cat << EOF > weave-net.jsonnet
|
||||||
|
local kp = (import 'kube-prometheus/kube-prometheus.libsonnet') +
|
||||||
|
(import 'kube-prometheus/kube-prometheus-weave-net.libsonnet') + {
|
||||||
|
_config+:: {
|
||||||
|
namespace: 'monitoring',
|
||||||
|
},
|
||||||
|
prometheusAlerts+:: {
|
||||||
|
groups: std.map(
|
||||||
|
function(group)
|
||||||
|
if group.name == 'weave-net' then
|
||||||
|
group {
|
||||||
|
rules: std.map(function(rule)
|
||||||
|
if rule.alert == "WeaveNetFastDPFlowsLow" then
|
||||||
|
rule {
|
||||||
|
expr: "sum(weave_flows) < 20000"
|
||||||
|
}
|
||||||
|
else if rule.alert == "WeaveNetIPAMUnreachable" then
|
||||||
|
rule {
|
||||||
|
expr: "weave_ipam_unreachable_percentage > 25"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rule
|
||||||
|
,
|
||||||
|
group.rules
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
group,
|
||||||
|
super.groups
|
||||||
|
),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
{ ['00namespace-' + name]: kp.kubePrometheus[name] for name in std.objectFields(kp.kubePrometheus) } +
|
||||||
|
{ ['0prometheus-operator-' + name]: kp.prometheusOperator[name] for name in std.objectFields(kp.prometheusOperator) } +
|
||||||
|
{ ['node-exporter-' + name]: kp.nodeExporter[name] for name in std.objectFields(kp.nodeExporter) } +
|
||||||
|
{ ['kube-state-metrics-' + name]: kp.kubeStateMetrics[name] for name in std.objectFields(kp.kubeStateMetrics) } +
|
||||||
|
{ ['prometheus-' + name]: kp.prometheus[name] for name in std.objectFields(kp.prometheus) } +
|
||||||
|
{ ['prometheus-adapter-' + name]: kp.prometheusAdapter[name] for name in std.objectFields(kp.prometheusAdapter) } +
|
||||||
|
{ ['grafana-' + name]: kp.grafana[name] for name in std.objectFields(kp.grafana) }
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Create manifests
|
||||||
|
```
|
||||||
|
jsonnet -J vendor -m manifests weave-net.jsonnet | xargs -I{} sh -c 'cat $1 | gojsontoyaml > $1.yaml; rm -f $1' -- {}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Apply manifests
|
||||||
|
Applying the created manifests will install the following components in your Kubernetes cluster:
|
||||||
|
- [Namespace](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) "monitoring"
|
||||||
|
- [Prometheus](https://github.com/prometheus/prometheus)
|
||||||
|
- [Kube State Metrics](https://github.com/kubernetes/kube-state-metrics)
|
||||||
|
- [Prometheus Operator](https://github.com/coreos/prometheus-operator) Operator to manage prometheus
|
||||||
|
- [Grafana](https://grafana.com) Dashboards on top of Prometheus metrics.
|
||||||
|
- [Weave Net ServiceMonitor](https://github.com/coreos/kube-prometheus/blob/7a85d7d8a6a81eda1db090846759fd6ca6532884/jsonnet/kube-prometheus/kube-prometheus-weave-net.libsonnet#L12-L43) ServiceMonitor brings the weave net metrics to prometheus.
|
||||||
|
- [Weave Net Service](https://github.com/coreos/kube-prometheus/blob/7a85d7d8a6a81eda1db090846759fd6ca6532884/jsonnet/kube-prometheus/kube-prometheus-weave-net.libsonnet#L7-L11) Weave Net Service which the ServiceMonitor scrapes.
|
||||||
|
- [Weave Net Grafana Dashboard](https://grafana.com/grafana/dashboards/11789)
|
||||||
|
- [Weave Net (Cluster) Grafana Dashboard](https://grafana.com/grafana/dashboards/11804)
|
||||||
|
```
|
||||||
|
cd manifests
|
||||||
|
ls *.yaml | grep -e ^prometheus -e ^node -e ^grafana -e ^kube | xargs -I {} kubectl create -f {} -n monitoring
|
||||||
|
kubectl create -f prometheus-serviceWeaveNet.yaml -n kube-system
|
||||||
|
kubectl create -f prometheus-serviceMonitorWeaveNet.yaml -n monitoring
|
||||||
|
```
|
||||||
|
**Note:** If you want to make changes to the created yamls, please modify the weave-net.jsonnet and recreate the manifests before applying.
|
||||||
|
|
||||||
# Weave Cloud Integration
|
# Weave Cloud Integration
|
||||||
|
|
||||||
Finally, you can configure your local Prometheus instance to push
|
Finally, you can configure your local Prometheus instance to push
|
||||||
|
|||||||
@@ -34,11 +34,26 @@ root@ubuntu:/# ping pingme
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Moreover, weaveDNS always register all network aliases (--network-alias option to docker run).
|
||||||
|
|
||||||
|
```
|
||||||
|
host1$ docker run --network weave --network-alias pingme --network-alias pingme2 -dti weaveworks/ubuntu
|
||||||
|
host1$ docker run --network weave --hostname=ubuntu.weave.local -ti weaveworks/ubuntu
|
||||||
|
root@ubuntu:/# ping pingme
|
||||||
|
...
|
||||||
|
root@ubuntu:/# ping pingme2
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
> **Note** If both hostname and container name are specified at
|
> **Note** If both hostname and container name are specified at
|
||||||
the same time, the hostname takes precedence. In this circumstance, if
|
the same time, the hostname takes precedence. In this circumstance, if
|
||||||
the hostname is not in the weaveDNS domain, the container is *not*
|
the hostname is not in the weaveDNS domain, the container is *not*
|
||||||
registered, but it will still use weaveDNS for resolution.
|
registered, but it will still use weaveDNS for resolution.
|
||||||
|
|
||||||
|
By default, weaveDNS will listen on port 53 on the address of the
|
||||||
|
Docker bridge. To make it listen on a different address or port use
|
||||||
|
`weave launch --dns-listen-address <address>:<port>`
|
||||||
|
|
||||||
To disable an application container's use of weaveDNS, add the
|
To disable an application container's use of weaveDNS, add the
|
||||||
`--without-dns` option to `weave launch`. To
|
`--without-dns` option to `weave launch`. To
|
||||||
disable weaveDNS itself, launch weave with the `--no-dns` option.
|
disable weaveDNS itself, launch weave with the `--no-dns` option.
|
||||||
|
|||||||
@@ -335,3 +335,4 @@ and the container image versions as git hashes.
|
|||||||
* [Troubleshooting the Kubernetes Addon](/site/kubernetes/kube-addon.md#troubleshooting)
|
* [Troubleshooting the Kubernetes Addon](/site/kubernetes/kube-addon.md#troubleshooting)
|
||||||
* [Troubleshooting IPAM](/site/tasks/ipam/troubleshooting-ipam.md)
|
* [Troubleshooting IPAM](/site/tasks/ipam/troubleshooting-ipam.md)
|
||||||
* [Troubleshooting the Proxy](/site/tasks/weave-docker-api/using-proxy.md)
|
* [Troubleshooting the Proxy](/site/tasks/weave-docker-api/using-proxy.md)
|
||||||
|
* [Weave Net monitoring setup in Kubernetes using kube-prometheus](https://github.com/weaveworks/weave/blob/master/site/tasks/manage/metrics.md#weave-net-monitoring-setup-in-kubernetes-using-kube-prometheus)
|
||||||
@@ -24,5 +24,6 @@ weave_on $HOST2 attach $C2/24 c2
|
|||||||
|
|
||||||
wait_for_x network_tester_status "network tester status"
|
wait_for_x network_tester_status "network tester status"
|
||||||
assert "echo $status" "pass"
|
assert "echo $status" "pass"
|
||||||
|
assert "connections_metric $HOST1 encryption=\\\"\\\",state=\\\"established\\\"" "1"
|
||||||
|
|
||||||
end_suite
|
end_suite
|
||||||
@@ -16,5 +16,6 @@ assert_raises "exec_on $HOST1 c1 $PING $C2"
|
|||||||
|
|
||||||
assert_raises "weave_on $HOST1 status connections | grep -P 'encrypted *sleeve'"
|
assert_raises "weave_on $HOST1 status connections | grep -P 'encrypted *sleeve'"
|
||||||
assert_raises "weave_on $HOST2 status connections | grep -P 'encrypted *sleeve'"
|
assert_raises "weave_on $HOST2 status connections | grep -P 'encrypted *sleeve'"
|
||||||
|
assert "connections_metric $HOST1 encryption=\\\"yes\\\"",state=\\\"established\\\" "1"
|
||||||
|
|
||||||
end_suite
|
end_suite
|
||||||
@@ -44,6 +44,7 @@ weave_on $HOST2 launch --password wfvAwt7sj $HOST1
|
|||||||
|
|
||||||
assert_raises "weave_on $HOST1 status connections | grep -P 'encrypted *fastdp'"
|
assert_raises "weave_on $HOST1 status connections | grep -P 'encrypted *fastdp'"
|
||||||
assert_raises "weave_on $HOST2 status connections | grep -P 'encrypted *fastdp'"
|
assert_raises "weave_on $HOST2 status connections | grep -P 'encrypted *fastdp'"
|
||||||
|
assert "connections_metric $HOST1 encryption=\\\"yes\\\"",state=\\\"established\\\" "1"
|
||||||
|
|
||||||
PCAP1=$(mktemp)
|
PCAP1=$(mktemp)
|
||||||
PCAP2=$(mktemp)
|
PCAP2=$(mktemp)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ weave_on $HOST1 launch --password wfvAwt7sj --trusted-subnets $HOST2_CIDR
|
|||||||
weave_on $HOST2 launch --password wfvAwt7sj $HOST1
|
weave_on $HOST2 launch --password wfvAwt7sj $HOST1
|
||||||
assert_raises "weave_on $HOST1 status connections | grep encrypted"
|
assert_raises "weave_on $HOST1 status connections | grep encrypted"
|
||||||
assert_raises "weave_on $HOST2 status connections | grep encrypted"
|
assert_raises "weave_on $HOST2 status connections | grep encrypted"
|
||||||
|
assert "connections_metric $HOST1 encryption=\\\"yes\\\"",state=\\\"established\\\" "1"
|
||||||
|
|
||||||
weave_on $HOST1 stop
|
weave_on $HOST1 stop
|
||||||
weave_on $HOST2 stop
|
weave_on $HOST2 stop
|
||||||
@@ -26,5 +27,6 @@ weave_on $HOST1 launch --password wfvAwt7sj --trusted-subnets $HOST2_CIDR
|
|||||||
weave_on $HOST2 launch --password wfvAwt7sj --trusted-subnets $HOST1_CIDR $HOST1
|
weave_on $HOST2 launch --password wfvAwt7sj --trusted-subnets $HOST1_CIDR $HOST1
|
||||||
assert_raises "weave_on $HOST1 status connections | grep unencrypted"
|
assert_raises "weave_on $HOST1 status connections | grep unencrypted"
|
||||||
assert_raises "weave_on $HOST2 status connections | grep unencrypted"
|
assert_raises "weave_on $HOST2 status connections | grep unencrypted"
|
||||||
|
assert "connections_metric $HOST1 encryption=\\\"\\\"",state=\\\"established\\\" "1"
|
||||||
|
|
||||||
end_suite
|
end_suite
|
||||||
Executable
+47
@@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
. "$(dirname "$0")/config.sh"
|
||||||
|
|
||||||
|
run_on1() {
|
||||||
|
assert_raises "run_on $HOST1 $@"
|
||||||
|
}
|
||||||
|
|
||||||
|
weave_on1() {
|
||||||
|
assert_raises "weave_on $HOST1 $@"
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_weave_on1() {
|
||||||
|
assert_raises "stop_weave_on $HOST1 $@"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_weave_iptable_rules() {
|
||||||
|
get_command_output_on $HOST1 "sudo iptables-save | grep -i weave"
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_iptable_refresh() {
|
||||||
|
# Canary is checked every 10s
|
||||||
|
sleep 12
|
||||||
|
}
|
||||||
|
|
||||||
|
start_suite "exposing weave network to host"
|
||||||
|
|
||||||
|
# Launch
|
||||||
|
weave_on1 "launch"
|
||||||
|
IPT_BEFORE=$(get_weave_iptable_rules)
|
||||||
|
run_on1 "sudo iptables -t nat -X WEAVE-CANARY"
|
||||||
|
wait_for_iptable_refresh
|
||||||
|
IPT_AFTER=$(get_weave_iptable_rules)
|
||||||
|
assert_raises "diff <(echo $IPT_BEFORE) <(echo $IPT_AFTER)" 0
|
||||||
|
stop_weave_on1
|
||||||
|
|
||||||
|
# After exposing
|
||||||
|
weave_on1 "launch"
|
||||||
|
weave_on1 "expose"
|
||||||
|
IPT_BEFORE=$(get_weave_iptable_rules)
|
||||||
|
run_on1 "sudo iptables -t nat -X WEAVE-CANARY"
|
||||||
|
wait_for_iptable_refresh
|
||||||
|
IPT_AFTER=$(get_weave_iptable_rules)
|
||||||
|
assert_raises "diff <(echo $IPT_BEFORE) <(echo $IPT_AFTER)" 0
|
||||||
|
stop_weave_on1
|
||||||
|
|
||||||
|
end_suite
|
||||||
@@ -13,9 +13,9 @@ start_suite "Resolve names in custom domain with subdomains"
|
|||||||
|
|
||||||
weave_on $HOST1 launch --log-level=debug --dns-domain $DOMAIN.
|
weave_on $HOST1 launch --log-level=debug --dns-domain $DOMAIN.
|
||||||
|
|
||||||
start_container_with_dns $HOST1 $C1/24 --name=c1 -h foo.$SUBDOMAIN1
|
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C1/24 --name=c1 -h foo.$SUBDOMAIN1
|
||||||
start_container_with_dns $HOST1 $C2/24 --name=c2 -h foo.$SUBDOMAIN2
|
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C2/24 --name=c2 -h foo.$SUBDOMAIN2
|
||||||
start_container_with_dns $HOST1 $C3/24 --name=c3 -h tre.$SUBDOMAIN1 --dns-search=$SUBDOMAIN2
|
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C3/24 --name=c3 -h tre.$SUBDOMAIN1 --dns-search=$SUBDOMAIN2
|
||||||
|
|
||||||
assert_dns_record $HOST1 c1 foo.$SUBDOMAIN2 $C2
|
assert_dns_record $HOST1 c1 foo.$SUBDOMAIN2 $C2
|
||||||
assert_dns_a_record $HOST1 c3 foo $C2 foo.$SUBDOMAIN2
|
assert_dns_a_record $HOST1 c3 foo $C2 foo.$SUBDOMAIN2
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ start_suite "Resolve unqualified names"
|
|||||||
|
|
||||||
weave_on $HOST1 launch
|
weave_on $HOST1 launch
|
||||||
|
|
||||||
start_container $HOST1 $C1/24 --name=c1 -h $NAME
|
proxy_start_container $HOST1 -e WEAVE_CIDR=$C1/24 --name=c1 -h $NAME
|
||||||
start_container_with_dns $HOST1 $C2/24 --name=c2 -h seetwo.$DOMAIN
|
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C2/24 --name=c2 -h seetwo.$DOMAIN
|
||||||
start_container_with_dns $HOST1 $C3/24 --name=c3 --dns-search=$DOMAIN
|
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C3/24 --name=c3 --dns-search=$DOMAIN
|
||||||
container=$(start_container_with_dns $HOST1 $C4/24)
|
container=$(start_container_with_dns $HOST1 $C4/24)
|
||||||
|
|
||||||
assert_dns_a_record $HOST1 c2 seeone $C1 $NAME
|
assert_dns_a_record $HOST1 c2 seeone $C1 $NAME
|
||||||
|
|||||||
@@ -7,14 +7,15 @@ TARGET=seetwo.weave.local
|
|||||||
TARGET_IP=10.2.0.78
|
TARGET_IP=10.2.0.78
|
||||||
STATIC=static.name
|
STATIC=static.name
|
||||||
STATIC_IP=10.9.9.9
|
STATIC_IP=10.9.9.9
|
||||||
|
ATTACH_ARGS="--rewrite-hosts --add-host=$STATIC:$STATIC_IP"
|
||||||
|
|
||||||
check_dns() {
|
check_dns() {
|
||||||
chk=$1
|
chk=$1
|
||||||
shift
|
shift
|
||||||
|
|
||||||
container=$(docker_on $HOST1 run $(dns_args $HOST1 "$@") -dt $DNS_IMAGE /bin/sh)
|
container=$(start_container_with_dns $HOST1 "$@" $IP/24)
|
||||||
weave_on $HOST1 attach $IP/24 "$@" --rewrite-hosts --add-host=$STATIC:$STATIC_IP $container
|
|
||||||
$chk $HOST1 $container $TARGET
|
$chk $HOST1 $container $TARGET
|
||||||
|
# --add-host adds to /etc/hosts so should work even when DNS is off.
|
||||||
assert_dns_record $HOST1 $container $STATIC $STATIC_IP
|
assert_dns_record $HOST1 $container $STATIC $STATIC_IP
|
||||||
rm_containers $HOST1 $container
|
rm_containers $HOST1 $container
|
||||||
}
|
}
|
||||||
@@ -22,10 +23,18 @@ check_dns() {
|
|||||||
start_suite "With or without DNS test"
|
start_suite "With or without DNS test"
|
||||||
|
|
||||||
# Assert behaviour without weaveDNS running
|
# Assert behaviour without weaveDNS running
|
||||||
weave_on $HOST1 launch
|
weave_on $HOST1 launch --no-dns
|
||||||
|
|
||||||
start_container $HOST1 $TARGET_IP/24 --name c2 -h $TARGET
|
start_container $HOST1 $TARGET_IP/24 --name c2 -h $TARGET
|
||||||
|
|
||||||
|
check_dns assert_no_dns_record --without-dns
|
||||||
|
check_dns assert_no_dns_record
|
||||||
|
|
||||||
|
weave_on $HOST1 stop
|
||||||
|
|
||||||
|
# Assert behaviour with weaveDNS
|
||||||
|
weave_on $HOST1 launch
|
||||||
|
|
||||||
check_dns assert_no_dns_record --without-dns
|
check_dns assert_no_dns_record --without-dns
|
||||||
check_dns assert_dns_record
|
check_dns assert_dns_record
|
||||||
|
|
||||||
|
|||||||
@@ -44,20 +44,8 @@ assert_raises "exec_on $HOST1 c1 $PING $C3"
|
|||||||
stop_weave_on $HOST1
|
stop_weave_on $HOST1
|
||||||
stop_weave_on $HOST2
|
stop_weave_on $HOST2
|
||||||
|
|
||||||
delete_persistence $HOST1 $HOST2
|
|
||||||
|
|
||||||
# Now make host1 attempt to claim from host2, when host2 is stopped
|
# Now make host1 attempt to claim from host2, when host2 is stopped
|
||||||
# the point being to check whether host1 will hang trying to talk to host2
|
# the point being to check whether host1 will hang trying to talk to host2
|
||||||
weave_on $HOST2 launch --ipalloc-range $UNIVERSE
|
|
||||||
weave_on $HOST2 prime
|
|
||||||
# Introduce host3 to remember the IPAM CRDT when we stop host2
|
|
||||||
weave_on $HOST3 launch --ipalloc-range $UNIVERSE $HOST2
|
|
||||||
weave_on $HOST3 prime
|
|
||||||
stop_weave_on $HOST2
|
|
||||||
weave_on $HOST1 launch --ipalloc-range $UNIVERSE $HOST3
|
|
||||||
|
|
||||||
stop_weave_on $HOST1
|
|
||||||
stop_weave_on $HOST3
|
|
||||||
|
|
||||||
# Delete persistence data on host1, so that host1 would try to establish a ring.
|
# Delete persistence data on host1, so that host1 would try to establish a ring.
|
||||||
delete_persistence $HOST1
|
delete_persistence $HOST1
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
. "$(dirname "$0")/config.sh"
|
. "$(dirname "$0")/config.sh"
|
||||||
|
|
||||||
IMAGE="weaveworks/docker-py:1.9.0-prime"
|
IMAGE="weaveworks/docker-py3:1.9.0-prime"
|
||||||
|
|
||||||
docker_py_test() {
|
docker_py_test() {
|
||||||
SHARD=$1
|
SHARD=$1
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ start_suite "Abuse of 'start' operation"
|
|||||||
|
|
||||||
weave_on $HOST1 launch
|
weave_on $HOST1 launch
|
||||||
docker_bridge_ip=$(weave_on $HOST1 docker-bridge-ip)
|
docker_bridge_ip=$(weave_on $HOST1 docker-bridge-ip)
|
||||||
proxy_start_container $HOST1 --name=c1
|
id1=$(proxy_start_container $HOST1 --name=c1)
|
||||||
|
|
||||||
check_hostconfig() {
|
check_hostconfig() {
|
||||||
docker_on $HOST1 attach $1 >/dev/null 2>&1 || true # Wait for container to exit
|
docker_on $HOST1 attach $1 >/dev/null 2>&1 || true # Wait for container to exit
|
||||||
@@ -16,12 +16,12 @@ check_hostconfig() {
|
|||||||
# Start c2 with a sneaky HostConfig
|
# Start c2 with a sneaky HostConfig
|
||||||
proxy docker_on $HOST1 create --name=c2 $SMALL_IMAGE $CHECK_ETHWE_UP
|
proxy docker_on $HOST1 create --name=c2 $SMALL_IMAGE $CHECK_ETHWE_UP
|
||||||
proxy docker_api_on $HOST1 POST /containers/c2/start '{"NetworkMode": "container:c1"}'
|
proxy docker_api_on $HOST1 POST /containers/c2/start '{"NetworkMode": "container:c1"}'
|
||||||
check_hostconfig c2 container:c1
|
check_hostconfig c2 "container:$id1"
|
||||||
|
|
||||||
# Start c5 with a differently sneaky HostConfig
|
# Start c5 with a differently sneaky HostConfig
|
||||||
proxy docker_on $HOST1 create --name=c5 $SMALL_IMAGE $CHECK_ETHWE_UP
|
proxy docker_on $HOST1 create --name=c5 $SMALL_IMAGE $CHECK_ETHWE_UP
|
||||||
proxy docker_api_on $HOST1 POST /containers/c5/start '{"HostConfig": {"NetworkMode": "container:c1"}}'
|
proxy docker_api_on $HOST1 POST /containers/c5/start '{"HostConfig": {"NetworkMode": "container:c1"}}'
|
||||||
check_hostconfig c5 container:c1
|
check_hostconfig c5 "container:$id1"
|
||||||
|
|
||||||
# Start c3 with HostConfig having empty binds and null dns/networking settings
|
# Start c3 with HostConfig having empty binds and null dns/networking settings
|
||||||
proxy docker_on $HOST1 create --name=c3 -v /tmp:/hosttmp $SMALL_IMAGE $CHECK_ETHWE_UP
|
proxy docker_on $HOST1 create --name=c3 -v /tmp:/hosttmp $SMALL_IMAGE $CHECK_ETHWE_UP
|
||||||
@@ -41,7 +41,7 @@ assert "docker_on $HOST1 inspect -f '{{.HostConfig.MemorySwap}}' c4b" "-1"
|
|||||||
# Start c6 with both named and unnamed HostConfig
|
# Start c6 with both named and unnamed HostConfig
|
||||||
proxy docker_on $HOST1 create --name=c6 $SMALL_IMAGE $CHECK_ETHWE_UP
|
proxy docker_on $HOST1 create --name=c6 $SMALL_IMAGE $CHECK_ETHWE_UP
|
||||||
proxy docker_api_on $HOST1 POST /containers/c6/start '{"NetworkMode": "container:c2", "HostConfig": {"NetworkMode": "container:c1"}}'
|
proxy docker_api_on $HOST1 POST /containers/c6/start '{"NetworkMode": "container:c2", "HostConfig": {"NetworkMode": "container:c1"}}'
|
||||||
check_hostconfig c6 container:c1
|
check_hostconfig c6 "container:$id1"
|
||||||
|
|
||||||
# Start c7 with an empty HostConfig and check this removes previous parameters, but still attaches to weave
|
# Start c7 with an empty HostConfig and check this removes previous parameters, but still attaches to weave
|
||||||
proxy docker_on $HOST1 create --name=c7 --memory-swap -1 $SMALL_IMAGE $CHECK_ETHWE_UP
|
proxy docker_on $HOST1 create --name=c7 --memory-swap -1 $SMALL_IMAGE $CHECK_ETHWE_UP
|
||||||
@@ -55,9 +55,9 @@ proxy docker_api_on $HOST1 POST /containers/c8/start '{"HostConfig": {"NetworkMo
|
|||||||
check_hostconfig c8 host
|
check_hostconfig c8 host
|
||||||
|
|
||||||
# Start c10 in network of host container
|
# Start c10 in network of host container
|
||||||
proxy_start_container $HOST1 --name=c9 --net=host
|
id9=$(proxy_start_container $HOST1 --name=c9 --net=host)
|
||||||
proxy docker_on $HOST1 create --name=c10 $SMALL_IMAGE $CHECK_ETHWE_MISSING
|
proxy docker_on $HOST1 create --name=c10 $SMALL_IMAGE $CHECK_ETHWE_MISSING
|
||||||
proxy docker_api_on $HOST1 POST /containers/c10/start '{"HostConfig": {"NetworkMode": "container:c9"}}'
|
proxy docker_api_on $HOST1 POST /containers/c10/start '{"HostConfig": {"NetworkMode": "container:c9"}}'
|
||||||
check_hostconfig c10 container:c9
|
check_hostconfig c10 "container:$id9"
|
||||||
|
|
||||||
end_suite
|
end_suite
|
||||||
@@ -37,7 +37,7 @@ k8s_version="$(run_on $HOST1 "kubelet --version" | grep -oP "(?<=Kubernetes )v[\
|
|||||||
|
|
||||||
for host in $HOSTS; do
|
for host in $HOSTS; do
|
||||||
if [ $host = $HOST1 ] ; then
|
if [ $host = $HOST1 ] ; then
|
||||||
run_on $host "sudo systemctl start kubelet && sudo kubeadm init --kubernetes-version=$k8s_version --token=$TOKEN --pod-network-cidr=$WEAVE_NETWORK"
|
run_on $host "sudo systemctl start kubelet && sudo kubeadm init --ignore-preflight-errors=NumCPU --kubernetes-version=$k8s_version --token=$TOKEN --pod-network-cidr=$WEAVE_NETWORK"
|
||||||
else
|
else
|
||||||
run_on $host "sudo systemctl start kubelet && sudo kubeadm join --token=$TOKEN --discovery-token-unsafe-skip-ca-verification $HOST1IP:$KUBE_PORT"
|
run_on $host "sudo systemctl start kubelet && sudo kubeadm join --token=$TOKEN --discovery-token-unsafe-skip-ca-verification $HOST1IP:$KUBE_PORT"
|
||||||
fi
|
fi
|
||||||
@@ -52,9 +52,9 @@ fi
|
|||||||
# Ensure Kubernetes uses locally built container images and inject code coverage environment variable (or do nothing depending on $COVERAGE):
|
# Ensure Kubernetes uses locally built container images and inject code coverage environment variable (or do nothing depending on $COVERAGE):
|
||||||
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
|
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
|
||||||
-e "s%env:%$WEAVE_ENV_VARS%" \
|
-e "s%env:%$WEAVE_ENV_VARS%" \
|
||||||
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.9.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
|
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.11.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
|
||||||
|
|
||||||
sleep 5
|
sleep 2
|
||||||
|
|
||||||
check_connections() {
|
check_connections() {
|
||||||
run_on $HOST1 "curl -sS http://127.0.0.1:6784/status | grep \"$SUCCESS\""
|
run_on $HOST1 "curl -sS http://127.0.0.1:6784/status | grep \"$SUCCESS\""
|
||||||
@@ -247,6 +247,9 @@ spec:
|
|||||||
- namespaceSelector: {}
|
- namespaceSelector: {}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Allow some time for the policy change to take effect
|
||||||
|
sleep 2
|
||||||
|
|
||||||
# Should be able to access from the "deny" pod now
|
# Should be able to access from the "deny" pod now
|
||||||
assert_raises "$SSH $HOST1 $KUBECTL exec $denyPodName -- curl -s -S -f -m 2 http://$DOMAIN:8080/status >/dev/null"
|
assert_raises "$SSH $HOST1 $KUBECTL exec $denyPodName -- curl -s -S -f -m 2 http://$DOMAIN:8080/status >/dev/null"
|
||||||
|
|
||||||
@@ -270,6 +273,7 @@ spec:
|
|||||||
cidr: $HOST1EXPIP/32
|
cidr: $HOST1EXPIP/32
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Allow some time for the policy change to take effect
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
assert_raises "$SSH $HOST1 curl -s -S -f -m 2 http://$VIRTUAL_IP/status >/dev/null"
|
assert_raises "$SSH $HOST1 curl -s -S -f -m 2 http://$VIRTUAL_IP/status >/dev/null"
|
||||||
@@ -289,6 +293,9 @@ spec:
|
|||||||
- {}
|
- {}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Allow some time for the policy change to take effect
|
||||||
|
sleep 2
|
||||||
|
|
||||||
# Virtual IP and NodePort should now work
|
# Virtual IP and NodePort should now work
|
||||||
assert_raises "$SSH $HOST1 curl -s -S -f -m 2 http://$VIRTUAL_IP/status >/dev/null"
|
assert_raises "$SSH $HOST1 curl -s -S -f -m 2 http://$VIRTUAL_IP/status >/dev/null"
|
||||||
assert_raises "$SSH $HOST1 curl -s -S -f -m 2 http://$HOST2:31138/status >/dev/null"
|
assert_raises "$SSH $HOST1 curl -s -S -f -m 2 http://$HOST2:31138/status >/dev/null"
|
||||||
@@ -314,6 +321,9 @@ spec:
|
|||||||
- 8.8.8.4/32
|
- 8.8.8.4/32
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Allow some time for the policy change to take effect
|
||||||
|
sleep 2
|
||||||
|
|
||||||
assert_raises "! $SSH $HOST1 $KUBECTL exec $denyPodName -- curl -s -S -f -m 2 http://$DOMAIN:8080/status >/dev/null"
|
assert_raises "! $SSH $HOST1 $KUBECTL exec $denyPodName -- curl -s -S -f -m 2 http://$DOMAIN:8080/status >/dev/null"
|
||||||
assert_raises "! $SSH $HOST1 $KUBECTL exec $denyPodName -- dig @8.8.8.4 google.com >/dev/null"
|
assert_raises "! $SSH $HOST1 $KUBECTL exec $denyPodName -- dig @8.8.8.4 google.com >/dev/null"
|
||||||
assert_raises "$SSH $HOST1 $KUBECTL exec $denyPodName -- dig @8.8.8.8 google.com >/dev/null"
|
assert_raises "$SSH $HOST1 $KUBECTL exec $denyPodName -- dig @8.8.8.8 google.com >/dev/null"
|
||||||
@@ -346,23 +356,18 @@ spec:
|
|||||||
name: kube-system
|
name: kube-system
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Allow some time for the policy change to take effect
|
||||||
|
sleep 2
|
||||||
|
|
||||||
assert_raises "$SSH $HOST1 $KUBECTL exec $denyPodName -- curl -s -S -f -m 2 http://$DOMAIN:8080/status >/dev/null"
|
assert_raises "$SSH $HOST1 $KUBECTL exec $denyPodName -- curl -s -S -f -m 2 http://$DOMAIN:8080/status >/dev/null"
|
||||||
|
|
||||||
# Passing --no-masq-local and setting externalTrafficPolicy to Local must preserve
|
# Setting externalTrafficPolicy to Local must preserve the client source IP addr
|
||||||
# the client source IP addr
|
|
||||||
|
|
||||||
CLIENT_IP_MASQ="$($SSH $HOST1 curl -sS http://$HOST2:31138/client_ip)"
|
CLIENT_IP_MASQ="$($SSH $HOST1 curl -sS http://$HOST2:31138/client_ip)"
|
||||||
|
|
||||||
WEAVE_ENV_VARS="${WEAVE_ENV_VARS}\\n - name: NO_MASQ_LOCAL\\n value: \"1\""
|
|
||||||
$SSH $HOST1 "$KUBECTL delete ds weave-net -n=kube-system"
|
|
||||||
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
|
|
||||||
-e "s%env:%$WEAVE_ENV_VARS%" \
|
|
||||||
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.9.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
|
|
||||||
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
run_on $HOST1 "$KUBECTL patch svc netvirt -p '{\"spec\":{\"externalTrafficPolicy\":\"Local\"}}'"
|
run_on $HOST1 "$KUBECTL patch svc netvirt -p '{\"spec\":{\"externalTrafficPolicy\":\"Local\"}}'"
|
||||||
|
|
||||||
|
sleep 2
|
||||||
CLIENT_IP_NO_MASQ="$($SSH $HOST1 curl -sS http://$HOST2:31138/client_ip)"
|
CLIENT_IP_NO_MASQ="$($SSH $HOST1 curl -sS http://$HOST2:31138/client_ip)"
|
||||||
|
|
||||||
assert_raises "[ $CLIENT_IP_NO_MASQ != $CLIENT_IP_MASQ ]"
|
assert_raises "[ $CLIENT_IP_NO_MASQ != $CLIENT_IP_MASQ ]"
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ function setup_kubernetes_cluster {
|
|||||||
|
|
||||||
for host in $HOSTS; do
|
for host in $HOSTS; do
|
||||||
if [ $host = $HOST1 ] ; then
|
if [ $host = $HOST1 ] ; then
|
||||||
run_on $host "sudo systemctl start kubelet && sudo kubeadm init --kubernetes-version=$k8s_version --token=$TOKEN"
|
run_on $host "sudo systemctl start kubelet && sudo kubeadm init --ignore-preflight-errors=NumCPU --kubernetes-version=$k8s_version --token=$TOKEN"
|
||||||
else
|
else
|
||||||
run_on $host "sudo systemctl start kubelet && sudo kubeadm join --token=$TOKEN --discovery-token-unsafe-skip-ca-verification $HOST1IP:$KUBE_PORT"
|
run_on $host "sudo systemctl start kubelet && sudo kubeadm join --token=$TOKEN --discovery-token-unsafe-skip-ca-verification $HOST1IP:$KUBE_PORT"
|
||||||
fi
|
fi
|
||||||
@@ -50,7 +50,7 @@ function setup_kubernetes_cluster {
|
|||||||
# Ensure Kubernetes uses locally built container images and inject code coverage environment variable (or do nothing depending on $COVERAGE):
|
# Ensure Kubernetes uses locally built container images and inject code coverage environment variable (or do nothing depending on $COVERAGE):
|
||||||
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
|
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
|
||||||
-e "s%env:%$COVERAGE_ARGS%" \
|
-e "s%env:%$COVERAGE_ARGS%" \
|
||||||
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.7.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
|
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.11.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
|
||||||
}
|
}
|
||||||
|
|
||||||
function weave_connected {
|
function weave_connected {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ function setup_kubernetes_cluster {
|
|||||||
|
|
||||||
for host in $HOSTS; do
|
for host in $HOSTS; do
|
||||||
if [ $host = $HOST1 ] ; then
|
if [ $host = $HOST1 ] ; then
|
||||||
run_on $host "sudo systemctl start kubelet && sudo kubeadm init --kubernetes-version=$k8s_version --token=$TOKEN"
|
run_on $host "sudo systemctl start kubelet && sudo kubeadm init --ignore-preflight-errors=NumCPU --kubernetes-version=$k8s_version --token=$TOKEN"
|
||||||
else
|
else
|
||||||
run_on $host "sudo systemctl start kubelet && sudo kubeadm join --token=$TOKEN --discovery-token-unsafe-skip-ca-verification $HOST1IP:$KUBE_PORT"
|
run_on $host "sudo systemctl start kubelet && sudo kubeadm join --token=$TOKEN --discovery-token-unsafe-skip-ca-verification $HOST1IP:$KUBE_PORT"
|
||||||
fi
|
fi
|
||||||
@@ -50,7 +50,7 @@ function setup_kubernetes_cluster {
|
|||||||
# Ensure Kubernetes uses locally built container images and inject code coverage environment variable (or do nothing depending on $COVERAGE):
|
# Ensure Kubernetes uses locally built container images and inject code coverage environment variable (or do nothing depending on $COVERAGE):
|
||||||
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
|
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
|
||||||
-e "s%env:%$COVERAGE_ARGS%" \
|
-e "s%env:%$COVERAGE_ARGS%" \
|
||||||
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.7.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
|
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.11.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
|
||||||
}
|
}
|
||||||
|
|
||||||
function force_drop_node {
|
function force_drop_node {
|
||||||
|
|||||||
+5
-1
@@ -189,7 +189,7 @@ start_container_image() {
|
|||||||
fi
|
fi
|
||||||
is_cidr "$1" && { cidr=$1; shift; }
|
is_cidr "$1" && { cidr=$1; shift; }
|
||||||
container=$(docker_on $host run $weave_dns_args $name_args "$@" -dt $image /bin/sh)
|
container=$(docker_on $host run $weave_dns_args $name_args "$@" -dt $image /bin/sh)
|
||||||
if ! weave_on $host attach $cidr $container >/dev/null ; then
|
if ! weave_on $host attach $cidr $ATTACH_ARGS $container >/dev/null ; then
|
||||||
docker_on $host rm -f $container
|
docker_on $host rm -f $container
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -267,6 +267,10 @@ wait_for_attached() {
|
|||||||
wait_for_x "check_attached $1 $2" "$2 on $1 to be attached"
|
wait_for_x "check_attached $1 $2" "$2 on $1 to be attached"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connections_metric() {
|
||||||
|
$SSH $1 curl -sS http://127.0.0.1:6784/metrics | awk -e "/^weave_connections.*$2/ { print \$2 }"
|
||||||
|
}
|
||||||
|
|
||||||
# assert_dns_record <host> <container> <name> [<ip> ...]
|
# assert_dns_record <host> <container> <name> [<ip> ...]
|
||||||
assert_dns_record() {
|
assert_dns_record() {
|
||||||
local host=$1
|
local host=$1
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ func (s *State) serveClientIP(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(w, host)
|
fmt.Fprintln(w, host)
|
||||||
}
|
}
|
||||||
|
|
||||||
// serveRead writes our json encoded state
|
// serveRead writes our json encoded state
|
||||||
|
|||||||
@@ -156,7 +156,8 @@ function create_image() {
|
|||||||
greenly echo "> Creating GCP image $IMAGE_NAME..."
|
greenly echo "> Creating GCP image $IMAGE_NAME..."
|
||||||
local begin_img=$(date +%s)
|
local begin_img=$(date +%s)
|
||||||
local num_hosts=1
|
local num_hosts=1
|
||||||
terraform apply -input=false -var "app=$APP" -var "name=$NAME" -var "num_hosts=$num_hosts" "$DIR/../tools/provisioning/gcp"
|
terraform init "$DIR/../tools/provisioning/gcp"
|
||||||
|
terraform apply -auto-approve -input=false -var "app=$APP" -var "name=$NAME" -var "num_hosts=$num_hosts" "$DIR/../tools/provisioning/gcp"
|
||||||
configure_with_ansible "$(terraform output username)" "$(terraform output public_ips)," "$(terraform output private_key_path)" $num_hosts
|
configure_with_ansible "$(terraform output username)" "$(terraform output public_ips)," "$(terraform output private_key_path)" $num_hosts
|
||||||
local zone=$(terraform output zone)
|
local zone=$(terraform output zone)
|
||||||
local name=$(terraform output instances_names)
|
local name=$(terraform output instances_names)
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ const (
|
|||||||
caCertPath = "ca.pem"
|
caCertPath = "ca.pem"
|
||||||
clientKeyPath = "key.pem"
|
clientKeyPath = "key.pem"
|
||||||
clientCertPath = "cert.pem"
|
clientCertPath = "cert.pem"
|
||||||
serverKeyPath = "server-key.pem"
|
|
||||||
serverCertPath = "server.pem"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -29,12 +28,6 @@ func AssertErrorType(t *testing.T, expected interface{}, actual error, desc stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func stackTrace(all bool) string {
|
|
||||||
buf := make([]byte, 1<<20)
|
|
||||||
stacklen := runtime.Stack(buf, all)
|
|
||||||
return string(buf[:stacklen])
|
|
||||||
}
|
|
||||||
|
|
||||||
// TrimTestArgs finds the first -- in os.Args and trim all args before
|
// TrimTestArgs finds the first -- in os.Args and trim all args before
|
||||||
// that, returning true when a -- was in fact found.
|
// that, returning true when a -- was in fact found.
|
||||||
func TrimTestArgs() bool {
|
func TrimTestArgs() bool {
|
||||||
|
|||||||
+1
-1
Submodule tools updated: 2a2df52789...7c2f120b0e.
+8
@@ -0,0 +1,8 @@
|
|||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- "1.x"
|
||||||
|
- master
|
||||||
|
env:
|
||||||
|
- TAGS=""
|
||||||
|
- TAGS="-tags purego"
|
||||||
|
script: go test $TAGS -v ./...
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
Copyright (c) 2016 Caleb Spare
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
# xxhash
|
||||||
|
|
||||||
|
[](https://godoc.org/github.com/cespare/xxhash)
|
||||||
|
[](https://travis-ci.org/cespare/xxhash)
|
||||||
|
|
||||||
|
xxhash is a Go implementation of the 64-bit
|
||||||
|
[xxHash](http://cyan4973.github.io/xxHash/) algorithm, XXH64. This is a
|
||||||
|
high-quality hashing algorithm that is much faster than anything in the Go
|
||||||
|
standard library.
|
||||||
|
|
||||||
|
This package provides a straightforward API:
|
||||||
|
|
||||||
|
```
|
||||||
|
func Sum64(b []byte) uint64
|
||||||
|
func Sum64String(s string) uint64
|
||||||
|
type Digest struct{ ... }
|
||||||
|
func New() *Digest
|
||||||
|
```
|
||||||
|
|
||||||
|
The `Digest` type implements hash.Hash64. Its key methods are:
|
||||||
|
|
||||||
|
```
|
||||||
|
func (*Digest) Write([]byte) (int, error)
|
||||||
|
func (*Digest) WriteString(string) (int, error)
|
||||||
|
func (*Digest) Sum64() uint64
|
||||||
|
```
|
||||||
|
|
||||||
|
This implementation provides a fast pure-Go implementation and an even faster
|
||||||
|
assembly implementation for amd64.
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
This package is in a module and the latest code is in version 2 of the module.
|
||||||
|
You need a version of Go with at least "minimal module compatibility" to use
|
||||||
|
github.com/cespare/xxhash/v2:
|
||||||
|
|
||||||
|
* 1.9.7+ for Go 1.9
|
||||||
|
* 1.10.3+ for Go 1.10
|
||||||
|
* Go 1.11 or later
|
||||||
|
|
||||||
|
I recommend using the latest release of Go.
|
||||||
|
|
||||||
|
## Benchmarks
|
||||||
|
|
||||||
|
Here are some quick benchmarks comparing the pure-Go and assembly
|
||||||
|
implementations of Sum64.
|
||||||
|
|
||||||
|
| input size | purego | asm |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 5 B | 979.66 MB/s | 1291.17 MB/s |
|
||||||
|
| 100 B | 7475.26 MB/s | 7973.40 MB/s |
|
||||||
|
| 4 KB | 17573.46 MB/s | 17602.65 MB/s |
|
||||||
|
| 10 MB | 17131.46 MB/s | 17142.16 MB/s |
|
||||||
|
|
||||||
|
These numbers were generated on Ubuntu 18.04 with an Intel i7-8700K CPU using
|
||||||
|
the following commands under Go 1.11.2:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go test -tags purego -benchtime 10s -bench '/xxhash,direct,bytes'
|
||||||
|
$ go test -benchtime 10s -bench '/xxhash,direct,bytes'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Projects using this package
|
||||||
|
|
||||||
|
- [InfluxDB](https://github.com/influxdata/influxdb)
|
||||||
|
- [Prometheus](https://github.com/prometheus/prometheus)
|
||||||
|
- [FreeCache](https://github.com/coocood/freecache)
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
module github.com/cespare/xxhash/v2
|
||||||
|
|
||||||
|
go 1.11
|
||||||
Whitespace-only changes.
+236
@@ -0,0 +1,236 @@
|
|||||||
|
// Package xxhash implements the 64-bit variant of xxHash (XXH64) as described
|
||||||
|
// at http://cyan4973.github.io/xxHash/.
|
||||||
|
package xxhash
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"math/bits"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
prime1 uint64 = 11400714785074694791
|
||||||
|
prime2 uint64 = 14029467366897019727
|
||||||
|
prime3 uint64 = 1609587929392839161
|
||||||
|
prime4 uint64 = 9650029242287828579
|
||||||
|
prime5 uint64 = 2870177450012600261
|
||||||
|
)
|
||||||
|
|
||||||
|
// NOTE(caleb): I'm using both consts and vars of the primes. Using consts where
|
||||||
|
// possible in the Go code is worth a small (but measurable) performance boost
|
||||||
|
// by avoiding some MOVQs. Vars are needed for the asm and also are useful for
|
||||||
|
// convenience in the Go code in a few places where we need to intentionally
|
||||||
|
// avoid constant arithmetic (e.g., v1 := prime1 + prime2 fails because the
|
||||||
|
// result overflows a uint64).
|
||||||
|
var (
|
||||||
|
prime1v = prime1
|
||||||
|
prime2v = prime2
|
||||||
|
prime3v = prime3
|
||||||
|
prime4v = prime4
|
||||||
|
prime5v = prime5
|
||||||
|
)
|
||||||
|
|
||||||
|
// Digest implements hash.Hash64.
|
||||||
|
type Digest struct {
|
||||||
|
v1 uint64
|
||||||
|
v2 uint64
|
||||||
|
v3 uint64
|
||||||
|
v4 uint64
|
||||||
|
total uint64
|
||||||
|
mem [32]byte
|
||||||
|
n int // how much of mem is used
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new Digest that computes the 64-bit xxHash algorithm.
|
||||||
|
func New() *Digest {
|
||||||
|
var d Digest
|
||||||
|
d.Reset()
|
||||||
|
return &d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset clears the Digest's state so that it can be reused.
|
||||||
|
func (d *Digest) Reset() {
|
||||||
|
d.v1 = prime1v + prime2
|
||||||
|
d.v2 = prime2
|
||||||
|
d.v3 = 0
|
||||||
|
d.v4 = -prime1v
|
||||||
|
d.total = 0
|
||||||
|
d.n = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size always returns 8 bytes.
|
||||||
|
func (d *Digest) Size() int { return 8 }
|
||||||
|
|
||||||
|
// BlockSize always returns 32 bytes.
|
||||||
|
func (d *Digest) BlockSize() int { return 32 }
|
||||||
|
|
||||||
|
// Write adds more data to d. It always returns len(b), nil.
|
||||||
|
func (d *Digest) Write(b []byte) (n int, err error) {
|
||||||
|
n = len(b)
|
||||||
|
d.total += uint64(n)
|
||||||
|
|
||||||
|
if d.n+n < 32 {
|
||||||
|
// This new data doesn't even fill the current block.
|
||||||
|
copy(d.mem[d.n:], b)
|
||||||
|
d.n += n
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.n > 0 {
|
||||||
|
// Finish off the partial block.
|
||||||
|
copy(d.mem[d.n:], b)
|
||||||
|
d.v1 = round(d.v1, u64(d.mem[0:8]))
|
||||||
|
d.v2 = round(d.v2, u64(d.mem[8:16]))
|
||||||
|
d.v3 = round(d.v3, u64(d.mem[16:24]))
|
||||||
|
d.v4 = round(d.v4, u64(d.mem[24:32]))
|
||||||
|
b = b[32-d.n:]
|
||||||
|
d.n = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b) >= 32 {
|
||||||
|
// One or more full blocks left.
|
||||||
|
nw := writeBlocks(d, b)
|
||||||
|
b = b[nw:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store any remaining partial block.
|
||||||
|
copy(d.mem[:], b)
|
||||||
|
d.n = len(b)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum appends the current hash to b and returns the resulting slice.
|
||||||
|
func (d *Digest) Sum(b []byte) []byte {
|
||||||
|
s := d.Sum64()
|
||||||
|
return append(
|
||||||
|
b,
|
||||||
|
byte(s>>56),
|
||||||
|
byte(s>>48),
|
||||||
|
byte(s>>40),
|
||||||
|
byte(s>>32),
|
||||||
|
byte(s>>24),
|
||||||
|
byte(s>>16),
|
||||||
|
byte(s>>8),
|
||||||
|
byte(s),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum64 returns the current hash.
|
||||||
|
func (d *Digest) Sum64() uint64 {
|
||||||
|
var h uint64
|
||||||
|
|
||||||
|
if d.total >= 32 {
|
||||||
|
v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4
|
||||||
|
h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
|
||||||
|
h = mergeRound(h, v1)
|
||||||
|
h = mergeRound(h, v2)
|
||||||
|
h = mergeRound(h, v3)
|
||||||
|
h = mergeRound(h, v4)
|
||||||
|
} else {
|
||||||
|
h = d.v3 + prime5
|
||||||
|
}
|
||||||
|
|
||||||
|
h += d.total
|
||||||
|
|
||||||
|
i, end := 0, d.n
|
||||||
|
for ; i+8 <= end; i += 8 {
|
||||||
|
k1 := round(0, u64(d.mem[i:i+8]))
|
||||||
|
h ^= k1
|
||||||
|
h = rol27(h)*prime1 + prime4
|
||||||
|
}
|
||||||
|
if i+4 <= end {
|
||||||
|
h ^= uint64(u32(d.mem[i:i+4])) * prime1
|
||||||
|
h = rol23(h)*prime2 + prime3
|
||||||
|
i += 4
|
||||||
|
}
|
||||||
|
for i < end {
|
||||||
|
h ^= uint64(d.mem[i]) * prime5
|
||||||
|
h = rol11(h) * prime1
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
h ^= h >> 33
|
||||||
|
h *= prime2
|
||||||
|
h ^= h >> 29
|
||||||
|
h *= prime3
|
||||||
|
h ^= h >> 32
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
magic = "xxh\x06"
|
||||||
|
marshaledSize = len(magic) + 8*5 + 32
|
||||||
|
)
|
||||||
|
|
||||||
|
// MarshalBinary implements the encoding.BinaryMarshaler interface.
|
||||||
|
func (d *Digest) MarshalBinary() ([]byte, error) {
|
||||||
|
b := make([]byte, 0, marshaledSize)
|
||||||
|
b = append(b, magic...)
|
||||||
|
b = appendUint64(b, d.v1)
|
||||||
|
b = appendUint64(b, d.v2)
|
||||||
|
b = appendUint64(b, d.v3)
|
||||||
|
b = appendUint64(b, d.v4)
|
||||||
|
b = appendUint64(b, d.total)
|
||||||
|
b = append(b, d.mem[:d.n]...)
|
||||||
|
b = b[:len(b)+len(d.mem)-d.n]
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
|
||||||
|
func (d *Digest) UnmarshalBinary(b []byte) error {
|
||||||
|
if len(b) < len(magic) || string(b[:len(magic)]) != magic {
|
||||||
|
return errors.New("xxhash: invalid hash state identifier")
|
||||||
|
}
|
||||||
|
if len(b) != marshaledSize {
|
||||||
|
return errors.New("xxhash: invalid hash state size")
|
||||||
|
}
|
||||||
|
b = b[len(magic):]
|
||||||
|
b, d.v1 = consumeUint64(b)
|
||||||
|
b, d.v2 = consumeUint64(b)
|
||||||
|
b, d.v3 = consumeUint64(b)
|
||||||
|
b, d.v4 = consumeUint64(b)
|
||||||
|
b, d.total = consumeUint64(b)
|
||||||
|
copy(d.mem[:], b)
|
||||||
|
b = b[len(d.mem):]
|
||||||
|
d.n = int(d.total % uint64(len(d.mem)))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendUint64(b []byte, x uint64) []byte {
|
||||||
|
var a [8]byte
|
||||||
|
binary.LittleEndian.PutUint64(a[:], x)
|
||||||
|
return append(b, a[:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func consumeUint64(b []byte) ([]byte, uint64) {
|
||||||
|
x := u64(b)
|
||||||
|
return b[8:], x
|
||||||
|
}
|
||||||
|
|
||||||
|
func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) }
|
||||||
|
func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) }
|
||||||
|
|
||||||
|
func round(acc, input uint64) uint64 {
|
||||||
|
acc += input * prime2
|
||||||
|
acc = rol31(acc)
|
||||||
|
acc *= prime1
|
||||||
|
return acc
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeRound(acc, val uint64) uint64 {
|
||||||
|
val = round(0, val)
|
||||||
|
acc ^= val
|
||||||
|
acc = acc*prime1 + prime4
|
||||||
|
return acc
|
||||||
|
}
|
||||||
|
|
||||||
|
func rol1(x uint64) uint64 { return bits.RotateLeft64(x, 1) }
|
||||||
|
func rol7(x uint64) uint64 { return bits.RotateLeft64(x, 7) }
|
||||||
|
func rol11(x uint64) uint64 { return bits.RotateLeft64(x, 11) }
|
||||||
|
func rol12(x uint64) uint64 { return bits.RotateLeft64(x, 12) }
|
||||||
|
func rol18(x uint64) uint64 { return bits.RotateLeft64(x, 18) }
|
||||||
|
func rol23(x uint64) uint64 { return bits.RotateLeft64(x, 23) }
|
||||||
|
func rol27(x uint64) uint64 { return bits.RotateLeft64(x, 27) }
|
||||||
|
func rol31(x uint64) uint64 { return bits.RotateLeft64(x, 31) }
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
// +build !appengine
|
||||||
|
// +build gc
|
||||||
|
// +build !purego
|
||||||
|
|
||||||
|
package xxhash
|
||||||
|
|
||||||
|
// Sum64 computes the 64-bit xxHash digest of b.
|
||||||
|
//
|
||||||
|
//go:noescape
|
||||||
|
func Sum64(b []byte) uint64
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func writeBlocks(d *Digest, b []byte) int
|
||||||
+215
@@ -0,0 +1,215 @@
|
|||||||
|
// +build !appengine
|
||||||
|
// +build gc
|
||||||
|
// +build !purego
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// Register allocation:
|
||||||
|
// AX h
|
||||||
|
// CX pointer to advance through b
|
||||||
|
// DX n
|
||||||
|
// BX loop end
|
||||||
|
// R8 v1, k1
|
||||||
|
// R9 v2
|
||||||
|
// R10 v3
|
||||||
|
// R11 v4
|
||||||
|
// R12 tmp
|
||||||
|
// R13 prime1v
|
||||||
|
// R14 prime2v
|
||||||
|
// R15 prime4v
|
||||||
|
|
||||||
|
// round reads from and advances the buffer pointer in CX.
|
||||||
|
// It assumes that R13 has prime1v and R14 has prime2v.
|
||||||
|
#define round(r) \
|
||||||
|
MOVQ (CX), R12 \
|
||||||
|
ADDQ $8, CX \
|
||||||
|
IMULQ R14, R12 \
|
||||||
|
ADDQ R12, r \
|
||||||
|
ROLQ $31, r \
|
||||||
|
IMULQ R13, r
|
||||||
|
|
||||||
|
// mergeRound applies a merge round on the two registers acc and val.
|
||||||
|
// It assumes that R13 has prime1v, R14 has prime2v, and R15 has prime4v.
|
||||||
|
#define mergeRound(acc, val) \
|
||||||
|
IMULQ R14, val \
|
||||||
|
ROLQ $31, val \
|
||||||
|
IMULQ R13, val \
|
||||||
|
XORQ val, acc \
|
||||||
|
IMULQ R13, acc \
|
||||||
|
ADDQ R15, acc
|
||||||
|
|
||||||
|
// func Sum64(b []byte) uint64
|
||||||
|
TEXT ·Sum64(SB), NOSPLIT, $0-32
|
||||||
|
// Load fixed primes.
|
||||||
|
MOVQ ·prime1v(SB), R13
|
||||||
|
MOVQ ·prime2v(SB), R14
|
||||||
|
MOVQ ·prime4v(SB), R15
|
||||||
|
|
||||||
|
// Load slice.
|
||||||
|
MOVQ b_base+0(FP), CX
|
||||||
|
MOVQ b_len+8(FP), DX
|
||||||
|
LEAQ (CX)(DX*1), BX
|
||||||
|
|
||||||
|
// The first loop limit will be len(b)-32.
|
||||||
|
SUBQ $32, BX
|
||||||
|
|
||||||
|
// Check whether we have at least one block.
|
||||||
|
CMPQ DX, $32
|
||||||
|
JLT noBlocks
|
||||||
|
|
||||||
|
// Set up initial state (v1, v2, v3, v4).
|
||||||
|
MOVQ R13, R8
|
||||||
|
ADDQ R14, R8
|
||||||
|
MOVQ R14, R9
|
||||||
|
XORQ R10, R10
|
||||||
|
XORQ R11, R11
|
||||||
|
SUBQ R13, R11
|
||||||
|
|
||||||
|
// Loop until CX > BX.
|
||||||
|
blockLoop:
|
||||||
|
round(R8)
|
||||||
|
round(R9)
|
||||||
|
round(R10)
|
||||||
|
round(R11)
|
||||||
|
|
||||||
|
CMPQ CX, BX
|
||||||
|
JLE blockLoop
|
||||||
|
|
||||||
|
MOVQ R8, AX
|
||||||
|
ROLQ $1, AX
|
||||||
|
MOVQ R9, R12
|
||||||
|
ROLQ $7, R12
|
||||||
|
ADDQ R12, AX
|
||||||
|
MOVQ R10, R12
|
||||||
|
ROLQ $12, R12
|
||||||
|
ADDQ R12, AX
|
||||||
|
MOVQ R11, R12
|
||||||
|
ROLQ $18, R12
|
||||||
|
ADDQ R12, AX
|
||||||
|
|
||||||
|
mergeRound(AX, R8)
|
||||||
|
mergeRound(AX, R9)
|
||||||
|
mergeRound(AX, R10)
|
||||||
|
mergeRound(AX, R11)
|
||||||
|
|
||||||
|
JMP afterBlocks
|
||||||
|
|
||||||
|
noBlocks:
|
||||||
|
MOVQ ·prime5v(SB), AX
|
||||||
|
|
||||||
|
afterBlocks:
|
||||||
|
ADDQ DX, AX
|
||||||
|
|
||||||
|
// Right now BX has len(b)-32, and we want to loop until CX > len(b)-8.
|
||||||
|
ADDQ $24, BX
|
||||||
|
|
||||||
|
CMPQ CX, BX
|
||||||
|
JG fourByte
|
||||||
|
|
||||||
|
wordLoop:
|
||||||
|
// Calculate k1.
|
||||||
|
MOVQ (CX), R8
|
||||||
|
ADDQ $8, CX
|
||||||
|
IMULQ R14, R8
|
||||||
|
ROLQ $31, R8
|
||||||
|
IMULQ R13, R8
|
||||||
|
|
||||||
|
XORQ R8, AX
|
||||||
|
ROLQ $27, AX
|
||||||
|
IMULQ R13, AX
|
||||||
|
ADDQ R15, AX
|
||||||
|
|
||||||
|
CMPQ CX, BX
|
||||||
|
JLE wordLoop
|
||||||
|
|
||||||
|
fourByte:
|
||||||
|
ADDQ $4, BX
|
||||||
|
CMPQ CX, BX
|
||||||
|
JG singles
|
||||||
|
|
||||||
|
MOVL (CX), R8
|
||||||
|
ADDQ $4, CX
|
||||||
|
IMULQ R13, R8
|
||||||
|
XORQ R8, AX
|
||||||
|
|
||||||
|
ROLQ $23, AX
|
||||||
|
IMULQ R14, AX
|
||||||
|
ADDQ ·prime3v(SB), AX
|
||||||
|
|
||||||
|
singles:
|
||||||
|
ADDQ $4, BX
|
||||||
|
CMPQ CX, BX
|
||||||
|
JGE finalize
|
||||||
|
|
||||||
|
singlesLoop:
|
||||||
|
MOVBQZX (CX), R12
|
||||||
|
ADDQ $1, CX
|
||||||
|
IMULQ ·prime5v(SB), R12
|
||||||
|
XORQ R12, AX
|
||||||
|
|
||||||
|
ROLQ $11, AX
|
||||||
|
IMULQ R13, AX
|
||||||
|
|
||||||
|
CMPQ CX, BX
|
||||||
|
JL singlesLoop
|
||||||
|
|
||||||
|
finalize:
|
||||||
|
MOVQ AX, R12
|
||||||
|
SHRQ $33, R12
|
||||||
|
XORQ R12, AX
|
||||||
|
IMULQ R14, AX
|
||||||
|
MOVQ AX, R12
|
||||||
|
SHRQ $29, R12
|
||||||
|
XORQ R12, AX
|
||||||
|
IMULQ ·prime3v(SB), AX
|
||||||
|
MOVQ AX, R12
|
||||||
|
SHRQ $32, R12
|
||||||
|
XORQ R12, AX
|
||||||
|
|
||||||
|
MOVQ AX, ret+24(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// writeBlocks uses the same registers as above except that it uses AX to store
|
||||||
|
// the d pointer.
|
||||||
|
|
||||||
|
// func writeBlocks(d *Digest, b []byte) int
|
||||||
|
TEXT ·writeBlocks(SB), NOSPLIT, $0-40
|
||||||
|
// Load fixed primes needed for round.
|
||||||
|
MOVQ ·prime1v(SB), R13
|
||||||
|
MOVQ ·prime2v(SB), R14
|
||||||
|
|
||||||
|
// Load slice.
|
||||||
|
MOVQ b_base+8(FP), CX
|
||||||
|
MOVQ b_len+16(FP), DX
|
||||||
|
LEAQ (CX)(DX*1), BX
|
||||||
|
SUBQ $32, BX
|
||||||
|
|
||||||
|
// Load vN from d.
|
||||||
|
MOVQ d+0(FP), AX
|
||||||
|
MOVQ 0(AX), R8 // v1
|
||||||
|
MOVQ 8(AX), R9 // v2
|
||||||
|
MOVQ 16(AX), R10 // v3
|
||||||
|
MOVQ 24(AX), R11 // v4
|
||||||
|
|
||||||
|
// We don't need to check the loop condition here; this function is
|
||||||
|
// always called with at least one block of data to process.
|
||||||
|
blockLoop:
|
||||||
|
round(R8)
|
||||||
|
round(R9)
|
||||||
|
round(R10)
|
||||||
|
round(R11)
|
||||||
|
|
||||||
|
CMPQ CX, BX
|
||||||
|
JLE blockLoop
|
||||||
|
|
||||||
|
// Copy vN back to d.
|
||||||
|
MOVQ R8, 0(AX)
|
||||||
|
MOVQ R9, 8(AX)
|
||||||
|
MOVQ R10, 16(AX)
|
||||||
|
MOVQ R11, 24(AX)
|
||||||
|
|
||||||
|
// The number of bytes written is CX minus the old base pointer.
|
||||||
|
SUBQ b_base+8(FP), CX
|
||||||
|
MOVQ CX, ret+32(FP)
|
||||||
|
|
||||||
|
RET
|
||||||
+76
@@ -0,0 +1,76 @@
|
|||||||
|
// +build !amd64 appengine !gc purego
|
||||||
|
|
||||||
|
package xxhash
|
||||||
|
|
||||||
|
// Sum64 computes the 64-bit xxHash digest of b.
|
||||||
|
func Sum64(b []byte) uint64 {
|
||||||
|
// A simpler version would be
|
||||||
|
// d := New()
|
||||||
|
// d.Write(b)
|
||||||
|
// return d.Sum64()
|
||||||
|
// but this is faster, particularly for small inputs.
|
||||||
|
|
||||||
|
n := len(b)
|
||||||
|
var h uint64
|
||||||
|
|
||||||
|
if n >= 32 {
|
||||||
|
v1 := prime1v + prime2
|
||||||
|
v2 := prime2
|
||||||
|
v3 := uint64(0)
|
||||||
|
v4 := -prime1v
|
||||||
|
for len(b) >= 32 {
|
||||||
|
v1 = round(v1, u64(b[0:8:len(b)]))
|
||||||
|
v2 = round(v2, u64(b[8:16:len(b)]))
|
||||||
|
v3 = round(v3, u64(b[16:24:len(b)]))
|
||||||
|
v4 = round(v4, u64(b[24:32:len(b)]))
|
||||||
|
b = b[32:len(b):len(b)]
|
||||||
|
}
|
||||||
|
h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
|
||||||
|
h = mergeRound(h, v1)
|
||||||
|
h = mergeRound(h, v2)
|
||||||
|
h = mergeRound(h, v3)
|
||||||
|
h = mergeRound(h, v4)
|
||||||
|
} else {
|
||||||
|
h = prime5
|
||||||
|
}
|
||||||
|
|
||||||
|
h += uint64(n)
|
||||||
|
|
||||||
|
i, end := 0, len(b)
|
||||||
|
for ; i+8 <= end; i += 8 {
|
||||||
|
k1 := round(0, u64(b[i:i+8:len(b)]))
|
||||||
|
h ^= k1
|
||||||
|
h = rol27(h)*prime1 + prime4
|
||||||
|
}
|
||||||
|
if i+4 <= end {
|
||||||
|
h ^= uint64(u32(b[i:i+4:len(b)])) * prime1
|
||||||
|
h = rol23(h)*prime2 + prime3
|
||||||
|
i += 4
|
||||||
|
}
|
||||||
|
for ; i < end; i++ {
|
||||||
|
h ^= uint64(b[i]) * prime5
|
||||||
|
h = rol11(h) * prime1
|
||||||
|
}
|
||||||
|
|
||||||
|
h ^= h >> 33
|
||||||
|
h *= prime2
|
||||||
|
h ^= h >> 29
|
||||||
|
h *= prime3
|
||||||
|
h ^= h >> 32
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeBlocks(d *Digest, b []byte) int {
|
||||||
|
v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4
|
||||||
|
n := len(b)
|
||||||
|
for len(b) >= 32 {
|
||||||
|
v1 = round(v1, u64(b[0:8:len(b)]))
|
||||||
|
v2 = round(v2, u64(b[8:16:len(b)]))
|
||||||
|
v3 = round(v3, u64(b[16:24:len(b)]))
|
||||||
|
v4 = round(v4, u64(b[24:32:len(b)]))
|
||||||
|
b = b[32:len(b):len(b)]
|
||||||
|
}
|
||||||
|
d.v1, d.v2, d.v3, d.v4 = v1, v2, v3, v4
|
||||||
|
return n - len(b)
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// +build appengine
|
||||||
|
|
||||||
|
// This file contains the safe implementations of otherwise unsafe-using code.
|
||||||
|
|
||||||
|
package xxhash
|
||||||
|
|
||||||
|
// Sum64String computes the 64-bit xxHash digest of s.
|
||||||
|
func Sum64String(s string) uint64 {
|
||||||
|
return Sum64([]byte(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteString adds more data to d. It always returns len(s), nil.
|
||||||
|
func (d *Digest) WriteString(s string) (n int, err error) {
|
||||||
|
return d.Write([]byte(s))
|
||||||
|
}
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
// +build !appengine
|
||||||
|
|
||||||
|
// This file encapsulates usage of unsafe.
|
||||||
|
// xxhash_safe.go contains the safe implementations.
|
||||||
|
|
||||||
|
package xxhash
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Notes:
|
||||||
|
//
|
||||||
|
// See https://groups.google.com/d/msg/golang-nuts/dcjzJy-bSpw/tcZYBzQqAQAJ
|
||||||
|
// for some discussion about these unsafe conversions.
|
||||||
|
//
|
||||||
|
// In the future it's possible that compiler optimizations will make these
|
||||||
|
// unsafe operations unnecessary: https://golang.org/issue/2205.
|
||||||
|
//
|
||||||
|
// Both of these wrapper functions still incur function call overhead since they
|
||||||
|
// will not be inlined. We could write Go/asm copies of Sum64 and Digest.Write
|
||||||
|
// for strings to squeeze out a bit more speed. Mid-stack inlining should
|
||||||
|
// eventually fix this.
|
||||||
|
|
||||||
|
// Sum64String computes the 64-bit xxHash digest of s.
|
||||||
|
// It may be faster than Sum64([]byte(s)) by avoiding a copy.
|
||||||
|
func Sum64String(s string) uint64 {
|
||||||
|
var b []byte
|
||||||
|
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||||
|
bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
|
||||||
|
bh.Len = len(s)
|
||||||
|
bh.Cap = len(s)
|
||||||
|
return Sum64(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteString adds more data to d. It always returns len(s), nil.
|
||||||
|
// It may be faster than Write([]byte(s)) by avoiding a copy.
|
||||||
|
func (d *Digest) WriteString(s string) (n int, err error) {
|
||||||
|
var b []byte
|
||||||
|
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||||
|
bh.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data
|
||||||
|
bh.Len = len(s)
|
||||||
|
bh.Cap = len(s)
|
||||||
|
return d.Write(b)
|
||||||
|
}
|
||||||
+1
-1
@@ -2,7 +2,7 @@ ISC License
|
|||||||
|
|
||||||
Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
|
Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
copyright notice and this permission notice appear in all copies.
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
|||||||
+90
-97
@@ -16,7 +16,9 @@
|
|||||||
// when the code is not running on Google App Engine, compiled by GopherJS, and
|
// when the code is not running on Google App Engine, compiled by GopherJS, and
|
||||||
// "-tags safe" is not added to the go build command line. The "disableunsafe"
|
// "-tags safe" is not added to the go build command line. The "disableunsafe"
|
||||||
// tag is deprecated and thus should not be used.
|
// tag is deprecated and thus should not be used.
|
||||||
// +build !js,!appengine,!safe,!disableunsafe
|
// Go versions prior to 1.4 are disabled because they use a different layout
|
||||||
|
// for interfaces which make the implementation of unsafeReflectValue more complex.
|
||||||
|
// +build !js,!appengine,!safe,!disableunsafe,go1.4
|
||||||
|
|
||||||
package spew
|
package spew
|
||||||
|
|
||||||
@@ -34,80 +36,49 @@ const (
|
|||||||
ptrSize = unsafe.Sizeof((*byte)(nil))
|
ptrSize = unsafe.Sizeof((*byte)(nil))
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
type flag uintptr
|
||||||
// offsetPtr, offsetScalar, and offsetFlag are the offsets for the
|
|
||||||
// internal reflect.Value fields. These values are valid before golang
|
|
||||||
// commit ecccf07e7f9d which changed the format. The are also valid
|
|
||||||
// after commit 82f48826c6c7 which changed the format again to mirror
|
|
||||||
// the original format. Code in the init function updates these offsets
|
|
||||||
// as necessary.
|
|
||||||
offsetPtr = uintptr(ptrSize)
|
|
||||||
offsetScalar = uintptr(0)
|
|
||||||
offsetFlag = uintptr(ptrSize * 2)
|
|
||||||
|
|
||||||
// flagKindWidth and flagKindShift indicate various bits that the
|
var (
|
||||||
// reflect package uses internally to track kind information.
|
// flagRO indicates whether the value field of a reflect.Value
|
||||||
//
|
// is read-only.
|
||||||
// flagRO indicates whether or not the value field of a reflect.Value is
|
flagRO flag
|
||||||
// read-only.
|
|
||||||
//
|
// flagAddr indicates whether the address of the reflect.Value's
|
||||||
// flagIndir indicates whether the value field of a reflect.Value is
|
// value may be taken.
|
||||||
// the actual data or a pointer to the data.
|
flagAddr flag
|
||||||
//
|
|
||||||
// These values are valid before golang commit 90a7c3c86944 which
|
|
||||||
// changed their positions. Code in the init function updates these
|
|
||||||
// flags as necessary.
|
|
||||||
flagKindWidth = uintptr(5)
|
|
||||||
flagKindShift = uintptr(flagKindWidth - 1)
|
|
||||||
flagRO = uintptr(1 << 0)
|
|
||||||
flagIndir = uintptr(1 << 1)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
// flagKindMask holds the bits that make up the kind
|
||||||
// Older versions of reflect.Value stored small integers directly in the
|
// part of the flags field. In all the supported versions,
|
||||||
// ptr field (which is named val in the older versions). Versions
|
// it is in the lower 5 bits.
|
||||||
// between commits ecccf07e7f9d and 82f48826c6c7 added a new field named
|
const flagKindMask = flag(0x1f)
|
||||||
// scalar for this purpose which unfortunately came before the flag
|
|
||||||
// field, so the offset of the flag field is different for those
|
|
||||||
// versions.
|
|
||||||
//
|
|
||||||
// This code constructs a new reflect.Value from a known small integer
|
|
||||||
// and checks if the size of the reflect.Value struct indicates it has
|
|
||||||
// the scalar field. When it does, the offsets are updated accordingly.
|
|
||||||
vv := reflect.ValueOf(0xf00)
|
|
||||||
if unsafe.Sizeof(vv) == (ptrSize * 4) {
|
|
||||||
offsetScalar = ptrSize * 2
|
|
||||||
offsetFlag = ptrSize * 3
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commit 90a7c3c86944 changed the flag positions such that the low
|
// Different versions of Go have used different
|
||||||
// order bits are the kind. This code extracts the kind from the flags
|
// bit layouts for the flags type. This table
|
||||||
// field and ensures it's the correct type. When it's not, the flag
|
// records the known combinations.
|
||||||
// order has been changed to the newer format, so the flags are updated
|
var okFlags = []struct {
|
||||||
// accordingly.
|
ro, addr flag
|
||||||
upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag)
|
}{{
|
||||||
upfv := *(*uintptr)(upf)
|
// From Go 1.4 to 1.5
|
||||||
flagKindMask := uintptr((1<<flagKindWidth - 1) << flagKindShift)
|
ro: 1 << 5,
|
||||||
if (upfv&flagKindMask)>>flagKindShift != uintptr(reflect.Int) {
|
addr: 1 << 7,
|
||||||
flagKindShift = 0
|
}, {
|
||||||
flagRO = 1 << 5
|
// Up to Go tip.
|
||||||
flagIndir = 1 << 6
|
ro: 1<<5 | 1<<6,
|
||||||
|
addr: 1 << 8,
|
||||||
|
}}
|
||||||
|
|
||||||
// Commit adf9b30e5594 modified the flags to separate the
|
var flagValOffset = func() uintptr {
|
||||||
// flagRO flag into two bits which specifies whether or not the
|
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
|
||||||
// field is embedded. This causes flagIndir to move over a bit
|
if !ok {
|
||||||
// and means that flagRO is the combination of either of the
|
panic("reflect.Value has no flag field")
|
||||||
// original flagRO bit and the new bit.
|
|
||||||
//
|
|
||||||
// This code detects the change by extracting what used to be
|
|
||||||
// the indirect bit to ensure it's set. When it's not, the flag
|
|
||||||
// order has been changed to the newer format, so the flags are
|
|
||||||
// updated accordingly.
|
|
||||||
if upfv&flagIndir == 0 {
|
|
||||||
flagRO = 3 << 5
|
|
||||||
flagIndir = 1 << 7
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return field.Offset
|
||||||
|
}()
|
||||||
|
|
||||||
|
// flagField returns a pointer to the flag field of a reflect.Value.
|
||||||
|
func flagField(v *reflect.Value) *flag {
|
||||||
|
return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset))
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
|
// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
|
||||||
@@ -119,34 +90,56 @@ func init() {
|
|||||||
// This allows us to check for implementations of the Stringer and error
|
// This allows us to check for implementations of the Stringer and error
|
||||||
// interfaces to be used for pretty printing ordinarily unaddressable and
|
// interfaces to be used for pretty printing ordinarily unaddressable and
|
||||||
// inaccessible values such as unexported struct fields.
|
// inaccessible values such as unexported struct fields.
|
||||||
func unsafeReflectValue(v reflect.Value) (rv reflect.Value) {
|
func unsafeReflectValue(v reflect.Value) reflect.Value {
|
||||||
indirects := 1
|
if !v.IsValid() || (v.CanInterface() && v.CanAddr()) {
|
||||||
vt := v.Type()
|
return v
|
||||||
upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr)
|
}
|
||||||
rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag))
|
flagFieldPtr := flagField(&v)
|
||||||
if rvf&flagIndir != 0 {
|
*flagFieldPtr &^= flagRO
|
||||||
vt = reflect.PtrTo(v.Type())
|
*flagFieldPtr |= flagAddr
|
||||||
indirects++
|
return v
|
||||||
} else if offsetScalar != 0 {
|
}
|
||||||
// The value is in the scalar field when it's not one of the
|
|
||||||
// reference types.
|
// Sanity checks against future reflect package changes
|
||||||
switch vt.Kind() {
|
// to the type or semantics of the Value.flag field.
|
||||||
case reflect.Uintptr:
|
func init() {
|
||||||
case reflect.Chan:
|
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
|
||||||
case reflect.Func:
|
if !ok {
|
||||||
case reflect.Map:
|
panic("reflect.Value has no flag field")
|
||||||
case reflect.Ptr:
|
}
|
||||||
case reflect.UnsafePointer:
|
if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() {
|
||||||
default:
|
panic("reflect.Value flag field has changed kind")
|
||||||
upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) +
|
}
|
||||||
offsetScalar)
|
type t0 int
|
||||||
|
var t struct {
|
||||||
|
A t0
|
||||||
|
// t0 will have flagEmbedRO set.
|
||||||
|
t0
|
||||||
|
// a will have flagStickyRO set
|
||||||
|
a t0
|
||||||
|
}
|
||||||
|
vA := reflect.ValueOf(t).FieldByName("A")
|
||||||
|
va := reflect.ValueOf(t).FieldByName("a")
|
||||||
|
vt0 := reflect.ValueOf(t).FieldByName("t0")
|
||||||
|
|
||||||
|
// Infer flagRO from the difference between the flags
|
||||||
|
// for the (otherwise identical) fields in t.
|
||||||
|
flagPublic := *flagField(&vA)
|
||||||
|
flagWithRO := *flagField(&va) | *flagField(&vt0)
|
||||||
|
flagRO = flagPublic ^ flagWithRO
|
||||||
|
|
||||||
|
// Infer flagAddr from the difference between a value
|
||||||
|
// taken from a pointer and not.
|
||||||
|
vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A")
|
||||||
|
flagNoPtr := *flagField(&vA)
|
||||||
|
flagPtr := *flagField(&vPtrA)
|
||||||
|
flagAddr = flagNoPtr ^ flagPtr
|
||||||
|
|
||||||
|
// Check that the inferred flags tally with one of the known versions.
|
||||||
|
for _, f := range okFlags {
|
||||||
|
if flagRO == f.ro && flagAddr == f.addr {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
panic("reflect.Value read-only flag has changed semantics")
|
||||||
pv := reflect.NewAt(vt, upv)
|
|
||||||
rv = pv
|
|
||||||
for i := 0; i < indirects; i++ {
|
|
||||||
rv = rv.Elem()
|
|
||||||
}
|
|
||||||
return rv
|
|
||||||
}
|
}
|
||||||
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
// when the code is running on Google App Engine, compiled by GopherJS, or
|
// when the code is running on Google App Engine, compiled by GopherJS, or
|
||||||
// "-tags safe" is added to the go build command line. The "disableunsafe"
|
// "-tags safe" is added to the go build command line. The "disableunsafe"
|
||||||
// tag is deprecated and thus should not be used.
|
// tag is deprecated and thus should not be used.
|
||||||
// +build js appengine safe disableunsafe
|
// +build js appengine safe disableunsafe !go1.4
|
||||||
|
|
||||||
package spew
|
package spew
|
||||||
|
|
||||||
|
|||||||
Loaded 100 of 2410 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user