Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d08787902a | ||
|
|
a752f65658 | ||
|
|
e50040883f | ||
|
|
55a46992d4 | ||
|
|
7b087168cf | ||
|
|
a9d663438f | ||
|
|
0e7b15b329 | ||
|
|
c1d3107418 | ||
|
|
962bb57b60 | ||
|
|
ea27069eb9 | ||
|
|
00f8afd743 | ||
|
|
6093383cb3 | ||
|
|
0d58e17954 | ||
|
|
1ceeca80e6 | ||
|
|
126f3ab928 | ||
|
|
65cbea0505 | ||
|
|
6365328d04 | ||
|
|
c085ebed05 | ||
|
|
668bbcf4ed | ||
|
|
4b47fc607c | ||
|
|
cdf761b8a3 | ||
|
|
559027b4f0 | ||
|
|
901e889ace | ||
|
|
e84a000b92 | ||
|
|
88d8bb648f | ||
|
|
1bb1f02b1d | ||
|
|
2f49b8455a | ||
|
|
df2240acbd | ||
|
|
c241c455c5 | ||
|
|
90a5d945c2 | ||
|
|
273c611d43 | ||
|
|
ee3b7ce368 | ||
|
|
7140e40477 | ||
|
|
8c8476381d | ||
|
|
25ccf44179 | ||
|
|
d30828a3f2 | ||
|
|
6d7a29ade6 | ||
|
|
1686ded5d5 | ||
|
|
9a5e1e333d | ||
|
|
e3712152d2 | ||
|
|
53b12b6c23 | ||
|
|
5367e0efb1 | ||
|
|
77445d0d9e | ||
|
|
34de0b10a6 | ||
|
|
344a4835e5 | ||
|
|
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 | ||
|
|
c7a235a54a | ||
|
|
bef50d3730 | ||
|
|
9d669c3312 | ||
|
|
d45579bf82 | ||
|
|
a46d18da0c | ||
|
|
95c020fbe0 | ||
|
|
7c2084b9af | ||
|
|
ac54cfb753 | ||
|
|
f78c4dacc5 | ||
|
|
9245b73913 | ||
|
|
6ee961b068 | ||
|
|
0d4099bba5 | ||
|
|
21c7bb3ff6 | ||
|
|
1f920513de | ||
|
|
15f21f1899 | ||
|
|
09a204b978 | ||
|
|
77fbb2c12b | ||
|
|
6ad3e69faf | ||
|
|
e2088ef401 | ||
|
|
0f3864968e | ||
|
|
ff9bcdf561 | ||
|
|
2f235daa1c | ||
|
|
438a5f5fd1 | ||
|
|
b051ef0878 | ||
|
|
48015aa7be | ||
|
|
0c4659c3b5 | ||
|
|
14730f8572 | ||
|
|
06b0a82465 | ||
|
|
e7a24eaf0a | ||
|
|
15ad210bec | ||
|
|
6bc0e5e71c | ||
|
|
0ca831f50b | ||
|
|
6e1770d24d | ||
|
|
57bca8e955 | ||
|
|
733df28a65 | ||
|
|
709f820ab6 | ||
|
|
6a1fbec5e2 | ||
|
|
35d8465376 | ||
|
|
9f00f78d3b | ||
|
|
599b99a6c4 | ||
|
|
4e3acfdc02 | ||
|
|
11915948a2 | ||
|
|
bb51a4f36d | ||
|
|
5d0e44bb6f | ||
|
|
6e7a469a62 | ||
|
|
ca0498b860 | ||
|
|
bbfa682083 | ||
|
|
f763c40c10 | ||
|
|
6a458d0712 | ||
|
|
67037b43b0 | ||
|
|
861395011c | ||
|
|
8bdfcd3042 | ||
|
|
83024b946f | ||
|
|
4f48670345 | ||
|
|
4b30d97d4e | ||
|
|
c9e813cfcb | ||
|
|
7c97bb5d30 | ||
|
|
c97c50b76e | ||
|
|
f919d06e2c | ||
|
|
cee6929cb9 | ||
|
|
526538d9d1 | ||
|
|
f43f3fc2e8 | ||
|
|
8b220f6383 | ||
|
|
d44e34584a | ||
|
|
6d2366ca4c | ||
|
|
7c1b615c98 | ||
|
|
390a4099d0 | ||
|
|
01237446eb | ||
|
|
18deb42df1 | ||
|
|
5c508f837e | ||
|
|
e000472af7 | ||
|
|
6d70284c21 | ||
|
|
4529d1587c | ||
|
|
b0d05f5e37 | ||
|
|
4a5d203e58 | ||
|
|
640c5c346c | ||
|
|
3780ce4dfb | ||
|
|
b871c1eecb | ||
|
|
9a6d0c9cf5 | ||
|
|
02ecea4576 | ||
|
|
6876507641 | ||
|
|
d2c78d3196 | ||
|
|
5b8365687e | ||
|
|
a43bd88ddd | ||
|
|
e8fcd21baa | ||
|
|
6a48da60ec | ||
|
|
886dea9b10 | ||
|
|
80e9dee9b2 | ||
|
|
5110a604f8 | ||
|
|
404f1bbef3 | ||
|
|
56491b35f1 | ||
|
|
dd70668b89 | ||
|
|
e5441b44e9 | ||
|
|
4da2501d7a | ||
|
|
04680fc52c | ||
|
|
cb4a8769a8 | ||
|
|
62c1d28524 | ||
|
|
92b21ccd44 | ||
|
|
88cd86a5f2 | ||
|
|
b18c88524d | ||
|
|
90e0c43bf2 | ||
|
|
4215618177 | ||
|
|
cb5798f94d | ||
|
|
79e032c984 | ||
|
|
821b787774 | ||
|
|
3ed7894e39 | ||
|
|
30ed34bd2c | ||
|
|
f5c2f51964 | ||
|
|
4d7f0f5014 | ||
|
|
d1ed6c5747 | ||
|
|
44f91950cb | ||
|
|
d2f0287fa3 | ||
|
|
9c09e36135 | ||
|
|
cb8e06c994 | ||
|
|
753c7cce1e | ||
|
|
30b2bada28 | ||
|
|
eeec3833a3 | ||
|
|
ee47f0c3ee | ||
|
|
36a2146ed8 | ||
|
|
6afedb881c | ||
|
|
05ab1139db | ||
|
|
e90cbf290b | ||
|
|
1e0431f6b2 | ||
|
|
9971fc3dac | ||
|
|
7aa7e3c00d | ||
|
|
a4dd7fa198 | ||
|
|
e2157a5d04 | ||
|
|
fc199d0df5 | ||
|
|
cc6d10c9b1 | ||
|
|
ace2c12608 | ||
|
|
57c464d60e | ||
|
|
65b3894a8e | ||
|
|
77bfa6a7e4 | ||
|
|
9d485d0f21 | ||
|
|
991945081a | ||
|
|
123762ec8d | ||
|
|
b07db6479a | ||
|
|
d3f62905b7 | ||
|
|
22b3393cfd | ||
|
|
c8e7dbd600 | ||
|
|
ef26b306e4 | ||
|
|
1588a7259d | ||
|
|
3a92050ebb | ||
|
|
04c63879b8 | ||
|
|
96291d1de4 | ||
|
|
9090fddd9f | ||
|
|
5bcd33c930 | ||
|
|
959d0bf2e2 | ||
|
|
a547d4571c | ||
|
|
b05c5f63c8 | ||
|
|
309a85b29c | ||
|
|
90ccc4a014 | ||
|
|
a6f2ee5ccc | ||
|
|
dcadc0f8cc | ||
|
|
332808c524 | ||
|
|
db006060e6 | ||
|
|
7a6ba40982 | ||
|
|
75e106b667 | ||
|
|
b28e2ee384 | ||
|
|
785b6b4584 | ||
|
|
391613d015 | ||
|
|
7334869134 | ||
|
|
bb4f51499d | ||
|
|
cc88aa2145 | ||
|
|
802ede1cd3 | ||
|
|
5e69e8a7b4 | ||
|
|
2d912263b1 | ||
|
|
51d7f455c9 | ||
|
|
89db74338e | ||
|
|
4c6879679d | ||
|
|
d35f2236e1 | ||
|
|
27848992b1 | ||
|
|
ea2084d871 | ||
|
|
20d55fe47a | ||
|
|
4a1fbc7c38 | ||
|
|
11c55a3a07 | ||
|
|
a400d43df7 | ||
|
|
189cfa995c | ||
|
|
06e0e6ace0 | ||
|
|
fdf881420c | ||
|
|
2c2a074a83 | ||
|
|
698e1b6d87 | ||
|
|
0d481ef0e9 | ||
|
|
0c2e046c86 | ||
|
|
21bc724632 | ||
|
|
16051a89b6 | ||
|
|
6130699ae5 | ||
|
|
9654df4d50 | ||
|
|
6f39a15b53 | ||
|
|
e8f35a848e | ||
|
|
43d3339b39 | ||
|
|
13644ee1b0 | ||
|
|
54d24e65ef | ||
|
|
e1e4a7887a | ||
|
|
17b45d9efa | ||
|
|
1bf07d86aa | ||
|
|
bba7b44248 | ||
|
|
d4d9ba1e35 | ||
|
|
d2a9a51296 | ||
|
|
81b17469f4 | ||
|
|
1c81fcb693 | ||
|
|
4a22dda13f |
No files matched your search
@@ -1,7 +1,7 @@
|
|||||||
version: 2
|
version: 2
|
||||||
defaults: &defaults
|
defaults: &defaults
|
||||||
docker:
|
docker:
|
||||||
- image: weaveworks/weavebuild:circle20-2e6504d3
|
- image: weaveworks/weavebuild:master-1dfe1f3b
|
||||||
working_directory: /go/src/github.com/weaveworks/weave
|
working_directory: /go/src/github.com/weaveworks/weave
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Git status should be ignored
|
||||||
|
.git
|
||||||
|
|
||||||
|
# .dockerignore should be ignored
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# Almost all of the reweave directory
|
||||||
|
# should be ignored
|
||||||
|
reweave/build/Dockerfile
|
||||||
|
reweave/tools/
|
||||||
|
reweave/scans/
|
||||||
|
reweave/Makefile
|
||||||
|
reweave/*.md
|
||||||
@@ -73,6 +73,3 @@ test/images/network-tester/webserver
|
|||||||
terraform.tfstate
|
terraform.tfstate
|
||||||
terraform.tfstate.backup
|
terraform.tfstate.backup
|
||||||
prog/net-plugin/rootfs/
|
prog/net-plugin/rootfs/
|
||||||
|
|
||||||
# Website
|
|
||||||
site-build
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
2.3.0
|
|
||||||
+179
@@ -1,3 +1,182 @@
|
|||||||
|
## Release 2.8.3
|
||||||
|
|
||||||
|
The docker API client version, used by the proxy package and the weaveutil command, was bumped from 1.18 to 1.24. As of March 2024, Docker API versions below 1.24 are deprecated. This means that the minimum supported Docker version is now 1.12.0.
|
||||||
|
|
||||||
|
Provision was made in weaveutil program and the weave script to override the API version used, via the environment variable `DOCKER_API_VERSION`. The same variable is used by standard docker clients.
|
||||||
|
|
||||||
|
## Release 2.8.2
|
||||||
|
|
||||||
|
This is the first release since forking from weaveworks/weave. While no new functionality has been added, there have been many changes.
|
||||||
|
|
||||||
|
* Build with Go version 1.21.6
|
||||||
|
* Dependencies, especially ones with associated CVEs, have been updated
|
||||||
|
* libCNI has been upgraded to v1.1.2
|
||||||
|
* A new, Docker-only build process has been created, which produces proper multi-arch images
|
||||||
|
* A vulnerability scanning process has been created using [grype](https://github.com/anchore/grype)
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
Improves the iptables rule added in 2.6.3 to block just the Weave Net
|
||||||
|
control port and avoid blocking other uses of 127.0.0.1. #3811
|
||||||
|
|
||||||
|
|
||||||
|
## Release 2.6.3
|
||||||
|
|
||||||
|
This release has a couple of security improvements, and some other fixes.
|
||||||
|
|
||||||
|
* Block non-local traffic to the Weave control port #3805
|
||||||
|
* Tell Linux not to accept router advisory messages #3801
|
||||||
|
* Network Policy Controller: add a metric to show errors while operating #3804
|
||||||
|
* Network Policy Controller: don't treat named port as a fatal error #3790
|
||||||
|
|
||||||
|
## Release 2.6.2
|
||||||
|
|
||||||
|
This release fixes a regression found in 2.6.1 release and removes a possible case
|
||||||
|
of CPU spinning when pcap is used in sleeve mode
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
* Weave Net can not be used in fastdp mode and always falls back to sleeve mode #3781, #3783
|
||||||
|
* Restrict timeout value passed to pcap library to a value less than 2^31 microseconds to
|
||||||
|
prevent CPU spinning #3782
|
||||||
|
|
||||||
|
## Release 2.6.1
|
||||||
|
|
||||||
|
This release fixes a bug discovered since the release of Weave Net 2.6.0 and
|
||||||
|
an improvement to support iptables 1.8
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
* Weave Net on node restart unable to form connections to peers and connections get stuck in
|
||||||
|
pending state and stops responding to API endpoint #3762 #3763
|
||||||
|
|
||||||
|
### Other improvements
|
||||||
|
|
||||||
|
* Weave Net Kubernetes images by default uses iptables 1.8 with legacy (netfilter) backend with
|
||||||
|
option to choose netfilter as backend #3465, #3747
|
||||||
|
|
||||||
|
|
||||||
|
## Release 2.6.0
|
||||||
|
|
||||||
|
This release reduces CPU and memory usage in larger clusters, by
|
||||||
|
sending notifications to a smaller set of peers and coalescing updates
|
||||||
|
to reduce topology recalculation. #3715, #3732
|
||||||
|
|
||||||
|
The default soft limit on connections has been raised from 100 to 200.
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
* Fix a race condition in Kubernetes addon when reclaiming IP
|
||||||
|
addresses after node deletion #3724, #3716
|
||||||
|
* Buffer events so Docker won't drop them, and Weave Net can clean up
|
||||||
|
after dead containers #3432, #3705
|
||||||
|
* Weave reconnect occasionally fails after network interface
|
||||||
|
disconnect #3666, #3669, #3676
|
||||||
|
* Ingress NetworkPolicy would accepts all traffic when specifying both
|
||||||
|
IPBlock and port #3653, #3654
|
||||||
|
|
||||||
|
### Kubernetes improvements
|
||||||
|
|
||||||
|
* Support both podSelector and namespaceSelector in NetworkPolicy #3312, #3647
|
||||||
|
* Only add default-drop egress rule if network policies are in use #3639
|
||||||
|
* Manifests use 'apps/v1' rather than deprecated 'apps/v1beta1' #3660
|
||||||
|
* Avoid Weave Net pods being evicted by setting priorityClassName: system-node-critical #3697
|
||||||
|
* Manifests use recommended DNS policy ClusterFirstWithHostNet #3692
|
||||||
|
* Weave Net now tolerates 'NoExecute' taint #3655
|
||||||
|
* Allow extra arguments to NetworkPolicy controller to be set in an environment variable #3683
|
||||||
|
* Stop reporting a failure to connect to self #3454, #3585
|
||||||
|
* Minor reduction in log noise when reclaiming IPs #3710
|
||||||
|
|
||||||
|
### Other improvements
|
||||||
|
|
||||||
|
* Avoid isolating nodes which have restarted by automatically
|
||||||
|
repairing inconsistencies in IP allocation data #1962, #3637, #3708
|
||||||
|
* Build Weave Net for the s390x architecture #3685
|
||||||
|
* When a IP address is requested that may be in use, make several
|
||||||
|
attempts to claim it before returning an error #3725
|
||||||
|
* Improve logging for IP allocation updates #3627, #3630
|
||||||
|
* Improve 'expecting PMTU update' log message on initial connection #3603
|
||||||
|
|
||||||
|
### Build and test
|
||||||
|
|
||||||
|
* Shut down Kubernetes on node when testing node deletion #3716
|
||||||
|
* Update the base 'Alpine' container image to version 3.8 #3701
|
||||||
|
* Update Go to version 1.13.3 #3712
|
||||||
|
* Update gopacket library #3590
|
||||||
|
* Pin busybox version to 1.28 to avoid CI failure in Python test #3689
|
||||||
|
* Remove obsolete weave-daemonset.yaml file #3674
|
||||||
|
|
||||||
|
Thanks to contributors @christian-2, @hpdvanwyk, @guirish, @kitt1987,
|
||||||
|
@mmerrill3, @Pensu, @scritchley, @sidharthsurana, @tanishq-dubey
|
||||||
|
|
||||||
|
[Full list of changes](https://github.com/weaveworks/weave/milestone/78?closed=1)
|
||||||
|
|
||||||
|
|
||||||
## Release 2.5.2
|
## Release 2.5.2
|
||||||
|
|
||||||
|
|||||||
+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
|
||||||
Generated
+16
-9
@@ -316,7 +316,7 @@
|
|||||||
revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
|
revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:a1b2a09d080e0229db471efc7f030b6d3931cd54989f6a1a4d676e085139cc2d"
|
digest = "1:b23296076e13a960263285b98907623e5d45f12fc405b14da19c6afa2a113deb"
|
||||||
name = "github.com/google/gopacket"
|
name = "github.com/google/gopacket"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
@@ -325,8 +325,8 @@
|
|||||||
"pcapgo",
|
"pcapgo",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "11c65f1ca9081dfea43b4f9643f5c155583b73ba"
|
revision = "7f3fc6cbbb499248dca53da7fe3ed6c25a78d22f"
|
||||||
version = "v1.1.14"
|
version = "v1.1.16"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:5e031a35b76ee001fa9ca9d598298054a123d080e00d13a8dafcfc5e3ecd5b58"
|
digest = "1:5e031a35b76ee001fa9ca9d598298054a123d080e00d13a8dafcfc5e3ecd5b58"
|
||||||
@@ -441,6 +441,14 @@
|
|||||||
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
|
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
|
||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
digest = "1:450f3a64f7a76d3f229ff33a30f0a889629dde46b0f82ece7c53404528316665"
|
||||||
|
name = "github.com/mdlayher/raw"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "fa5ef3332ca961deab5782da07b1616fea8a9dd8"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:2b32af4d2a529083275afc192d1067d8126b578c7a9613b26600e4df9c735155"
|
digest = "1:2b32af4d2a529083275afc192d1067d8126b578c7a9613b26600e4df9c735155"
|
||||||
@@ -678,12 +686,12 @@
|
|||||||
revision = "6b0aa22550d9325eb8f43418185859e13dc0de1d"
|
revision = "6b0aa22550d9325eb8f43418185859e13dc0de1d"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:277e090a58afaeb00fb9fd04e2b2f3466ff8fb327a331e0e531a3399a72697e3"
|
digest = "1:dfa8458da99855b0f0e13f580e6107b46311db15dc7f76cb80c131b937f7f8aa"
|
||||||
name = "github.com/weaveworks/mesh"
|
name = "github.com/weaveworks/mesh"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "38e8100dfbc7b28ae8ffde5a2bbeceec57ffa52a"
|
revision = "58dbcc3e8e63eed7dd77f3a6286855ae8c8876c1"
|
||||||
version = "v0.1"
|
version = "v0.4"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@@ -728,14 +736,14 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:5045bd5ed8083958e27c933e665c38b4de5d7d966146a074d541f691a56d8bc4"
|
digest = "1:653cc9ff57cf744d21f74e811af4f330415284bfc291d28f716833618c02c876"
|
||||||
name = "golang.org/x/sys"
|
name = "golang.org/x/sys"
|
||||||
packages = [
|
packages = [
|
||||||
"unix",
|
"unix",
|
||||||
"windows",
|
"windows",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "13d03a9a82fba647c21a0ef8fba44a795d0f0835"
|
revision = "afcc84fd7533758f95a6e93ae710aa945a0b7e73"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
|
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
|
||||||
@@ -1100,7 +1108,6 @@
|
|||||||
"github.com/weaveworks/mesh",
|
"github.com/weaveworks/mesh",
|
||||||
"golang.org/x/crypto/hkdf",
|
"golang.org/x/crypto/hkdf",
|
||||||
"golang.org/x/crypto/nacl/secretbox",
|
"golang.org/x/crypto/nacl/secretbox",
|
||||||
"golang.org/x/net/context",
|
|
||||||
"golang.org/x/sys/unix",
|
"golang.org/x/sys/unix",
|
||||||
"golang.org/x/tools/cover",
|
"golang.org/x/tools/cover",
|
||||||
"k8s.io/api/core/v1",
|
"k8s.io/api/core/v1",
|
||||||
|
|||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
# History of the ReWeave project
|
||||||
|
|
||||||
|
## How it started
|
||||||
|
|
||||||
|
In June 2022, Weave Net had not been updated for a year. Problems were starting to appear in the field. In particular, the last published images on the Docker Hub ([weaveworks/weave-kube](https://hub.docker.com/r/weaveworks/weave-kube) and [weaveworks/weave-npc](https://hub.docker.com/r/weaveworks/weave-npc), v2.8.1) had issues supporting multiple processor architectures, and security scanners showed multiple vulnerabilities.
|
||||||
|
|
||||||
|
A call went out from Weaveworks to get the community more involved in maintaining it. After some discussion on GitHub issues and e-mail, and even a few online meetings, things were not moving forward.
|
||||||
|
|
||||||
|
## ReWeave begins
|
||||||
|
|
||||||
|
Finally, in March 2023, this fork was created, with the following goals in mind:
|
||||||
|
|
||||||
|
* Update dependencies, especially ones with security vulnerabilities
|
||||||
|
* Make minimal code changes _only_ when required by updating dependencies
|
||||||
|
* Create true multi-arch images using modern tools
|
||||||
|
* Create a new build process to automate all this
|
||||||
|
* Do all this with _minimal_ changes to the existing codebase. Keep all new things in the `reweave` folder.
|
||||||
|
|
||||||
|
These goals were achieved. Details can be found in the [reweave](reweave/README.md) directory. A [pull request](https://github.com/weaveworks/weave/pull/3996) was submitted on the weaveworks repo, with the aim of getting a new official release out.
|
||||||
|
|
||||||
|
## Weaveworks ends
|
||||||
|
|
||||||
|
On February 5th, 2024, Weaveworks CEO Alexis Richardson announced via [LinkedIn](https://www.linkedin.com/posts/richardsonalexis_hi-everyone-i-am-very-sad-to-announce-activity-7160295096825860096-ZS67/) and [Twitter](https://twitter.com/monadic/status/1754530336120140116) that Weaveworks is winding down.
|
||||||
|
|
||||||
|
So, a decision was taken to maintain this fork independently.
|
||||||
|
|
||||||
|
## We're forked
|
||||||
|
|
||||||
|
Two major changes were introduced at this point:
|
||||||
|
|
||||||
|
* The module name was changed to `github.com/rajch/weave` (previously `github.com/weaveworks/weave`)
|
||||||
|
* The default registry account for publishing images was changed to `docker.io/rajchaudhuri` (previously `docker.io/weaveworks`)
|
||||||
|
|
||||||
|
In addition, the old repo structure and codebase is not longer sacrosanct. Things can be moved around, new code can be added outside the `reweave` directory, old code can be modified or deleted as necessary.
|
||||||
|
|
||||||
|
The version numbers will continue from where Weaveworks left off.
|
||||||
|
|
||||||
|
## New Goals
|
||||||
|
|
||||||
|
The old goals, listed above (except the last one), remain the priority. In addition, this project aims to:
|
||||||
|
|
||||||
|
* Remove dependencies on Weaveworks infrastructure, starting with telemetry (what weaveworks called checkpoint)
|
||||||
|
* Publish new releases regularly, duly security scanned
|
||||||
|
* Provide supporting infrastructure, such as weave's famous one-line installation, where possible
|
||||||
@@ -17,15 +17,15 @@ QEMU_VERSION=v2.7.0
|
|||||||
|
|
||||||
# A list of all supported architectures here. Should be named as Go is naming platforms
|
# A list of all supported architectures here. Should be named as Go is naming platforms
|
||||||
# All supported architectures must have an "ifeq" block below that customizes the parameters
|
# All supported architectures must have an "ifeq" block below that customizes the parameters
|
||||||
ALL_ARCHITECTURES=amd64 arm arm64 ppc64le
|
ALL_ARCHITECTURES=amd64 arm arm64 ppc64le s390x
|
||||||
ML_PLATFORMS=linux/amd64,linux/arm,linux/arm64,linux/ppc64le
|
ML_PLATFORMS=linux/amd64,linux/arm,linux/arm64,linux/ppc64le,linux/s390x
|
||||||
|
|
||||||
ifeq ($(ARCH),amd64)
|
ifeq ($(ARCH),amd64)
|
||||||
# The architecture to use when downloading the docker binary
|
# The architecture to use when downloading the docker binary
|
||||||
WEAVEEXEC_DOCKER_ARCH?=x86_64
|
WEAVEEXEC_DOCKER_ARCH?=x86_64
|
||||||
|
|
||||||
# The name of the alpine baseimage to use as the base for weave images
|
# The name of the alpine baseimage to use as the base for weave images
|
||||||
ALPINE_BASEIMAGE?=alpine:3.6
|
ALPINE_BASEIMAGE?=alpine:3.10
|
||||||
|
|
||||||
# The extension for the made images
|
# The extension for the made images
|
||||||
# Specifying none means for example weaveworks/weave:latest
|
# Specifying none means for example weaveworks/weave:latest
|
||||||
@@ -42,7 +42,7 @@ ifeq ($(ARCH),arm)
|
|||||||
WEAVEEXEC_DOCKER_ARCH?=armel
|
WEAVEEXEC_DOCKER_ARCH?=armel
|
||||||
|
|
||||||
# Using the (semi-)official alpine image
|
# Using the (semi-)official alpine image
|
||||||
ALPINE_BASEIMAGE?=arm32v6/alpine:3.6
|
ALPINE_BASEIMAGE?=arm32v6/alpine:3.8
|
||||||
|
|
||||||
# arm images have the -arm suffix, for instance weaveworks/weave-arm:latest
|
# arm images have the -arm suffix, for instance weaveworks/weave-arm:latest
|
||||||
ARCH_EXT?=-arm
|
ARCH_EXT?=-arm
|
||||||
@@ -62,7 +62,7 @@ ifeq ($(ARCH),arm64)
|
|||||||
WEAVEEXEC_DOCKER_ARCH?=armel
|
WEAVEEXEC_DOCKER_ARCH?=armel
|
||||||
|
|
||||||
# Using the (semi-)official alpine image
|
# Using the (semi-)official alpine image
|
||||||
ALPINE_BASEIMAGE?=arm64v8/alpine:3.6
|
ALPINE_BASEIMAGE?=arm64v8/alpine:3.8
|
||||||
|
|
||||||
# arm64 images have the -arm64 suffix, for instance weaveworks/weave-arm64:latest
|
# arm64 images have the -arm64 suffix, for instance weaveworks/weave-arm64:latest
|
||||||
ARCH_EXT?=-arm64
|
ARCH_EXT?=-arm64
|
||||||
@@ -82,7 +82,7 @@ ifeq ($(ARCH),ppc64le)
|
|||||||
WEAVEEXEC_DOCKER_ARCH?=ppc64le
|
WEAVEEXEC_DOCKER_ARCH?=ppc64le
|
||||||
|
|
||||||
# Using the (semi-)official alpine image
|
# Using the (semi-)official alpine image
|
||||||
ALPINE_BASEIMAGE?=ppc64le/alpine:3.6
|
ALPINE_BASEIMAGE?=ppc64le/alpine:3.8
|
||||||
|
|
||||||
# ppc64le images have the -ppc64le suffix, for instance weaveworks/weave-ppc64le:latest
|
# ppc64le images have the -ppc64le suffix, for instance weaveworks/weave-ppc64le:latest
|
||||||
ARCH_EXT?=-ppc64le
|
ARCH_EXT?=-ppc64le
|
||||||
@@ -97,6 +97,26 @@ ifeq ($(ARCH),ppc64le)
|
|||||||
# Tell the gcc linker to search for libpcap here
|
# Tell the gcc linker to search for libpcap here
|
||||||
CGO_LDFLAGS="-L/usr/local/lib/$(CC)"
|
CGO_LDFLAGS="-L/usr/local/lib/$(CC)"
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(ARCH),s390x)
|
||||||
|
# The architecture to use when downloading the docker binary
|
||||||
|
WEAVEEXEC_DOCKER_ARCH?=s390x
|
||||||
|
|
||||||
|
# Using the (semi-)official alpine image
|
||||||
|
ALPINE_BASEIMAGE?=s390x/alpine:3.6
|
||||||
|
|
||||||
|
# s390x images have the -s390x suffix, for instance weaveworks/weave-s390x:latest
|
||||||
|
ARCH_EXT?=-s390x
|
||||||
|
|
||||||
|
# The name of the gcc binary
|
||||||
|
CC=s390x-linux-gnu-gcc
|
||||||
|
|
||||||
|
# The architecture name to use when downloading a prebuilt QEMU binary
|
||||||
|
QEMUARCH=s390x
|
||||||
|
|
||||||
|
# In the weaveworks/build image; libpcap libraries for s390x are placed here
|
||||||
|
# Tell the gcc linker to search for libpcap here
|
||||||
|
CGO_LDFLAGS="-L/usr/local/lib/$(CC)"
|
||||||
|
endif
|
||||||
|
|
||||||
# The name of the user that this Makefile should produce image artifacts for. Can/should be overridden
|
# The name of the user that this Makefile should produce image artifacts for. Can/should be overridden
|
||||||
DOCKERHUB_USER?=weaveworks
|
DOCKERHUB_USER?=weaveworks
|
||||||
@@ -156,18 +176,11 @@ PUSH_ML=push_ml_weave push_ml_weaveexec push_ml_weave-kube push_ml_weave-npc
|
|||||||
|
|
||||||
WEAVE_EXPORT=weave$(ARCH_EXT).tar.gz
|
WEAVE_EXPORT=weave$(ARCH_EXT).tar.gz
|
||||||
|
|
||||||
NETGO_CHECK=@strings $@ | grep cgo_stub\\\.go >/dev/null || { \
|
|
||||||
rm $@; \
|
|
||||||
echo "\nYour go standard library was built without the 'netgo' build tag."; \
|
|
||||||
echo "To fix that, run"; \
|
|
||||||
echo " sudo go clean -i net"; \
|
|
||||||
echo " sudo go install -tags netgo std"; \
|
|
||||||
false; \
|
|
||||||
}
|
|
||||||
# The flags we are passing to go build. -extldflags -static for making a static binary,
|
# The flags we are passing to go build. -extldflags -static for making a static binary,
|
||||||
# -linkmode external for linking external C libraries into the binary, -X main.version for telling the
|
# -X main.version for telling the Go binary which version it is,
|
||||||
# Go binary which version it is, -tags netgo for enforcing the native Go DNS resolver
|
# -s -w drop symbol tables used by debuggers (not Go's internal symbol info)
|
||||||
BUILD_FLAGS=-i -ldflags "-linkmode external -extldflags -static -X main.version=$(WEAVE_VERSION)" -tags netgo
|
# -tags "osusergo netgo" to use native Go UID and DNS implementations
|
||||||
|
BUILD_FLAGS=-ldflags "-extldflags -static -X main.version=$(WEAVE_VERSION) -s -w" -tags "osusergo netgo"
|
||||||
|
|
||||||
PACKAGE_BASE=$(shell go list -e ./)
|
PACKAGE_BASE=$(shell go list -e ./)
|
||||||
|
|
||||||
@@ -196,10 +209,8 @@ ifeq ($(BUILD_IN_CONTAINER),true)
|
|||||||
# This make target compiles all binaries inside of the weaveworks/build container
|
# This make target compiles all binaries inside of the weaveworks/build container
|
||||||
# It bind-mounts the source into the container and passes all important variables
|
# It bind-mounts the source into the container and passes all important variables
|
||||||
exes $(EXES) tests lint: $(BUILD_UPTODATE)
|
exes $(EXES) tests lint: $(BUILD_UPTODATE)
|
||||||
@mkdir -p $(shell pwd)/.pkg
|
|
||||||
$(SUDO) docker run $(RM) $(RUN_FLAGS) \
|
$(SUDO) docker run $(RM) $(RUN_FLAGS) \
|
||||||
-v $(shell pwd):/go/src/github.com/weaveworks/weave \
|
-v $(shell pwd):/go/src/github.com/weaveworks/weave \
|
||||||
-v $(shell pwd)/.pkg:/go/pkg \
|
|
||||||
-e GOARCH=$(ARCH) -e CGO_ENABLED=1 -e GOOS=linux -e CIRCLECI -e CIRCLE_BUILD_NUM -e CIRCLE_NODE_TOTAL -e CIRCLE_NODE_INDEX -e COVERDIR -e SLOW -e DEBUG \
|
-e GOARCH=$(ARCH) -e CGO_ENABLED=1 -e GOOS=linux -e CIRCLECI -e CIRCLE_BUILD_NUM -e CIRCLE_NODE_TOTAL -e CIRCLE_NODE_INDEX -e COVERDIR -e SLOW -e DEBUG \
|
||||||
$(BUILD_IMAGE) COVERAGE=$(COVERAGE) WEAVE_VERSION=$(WEAVE_VERSION) CC=$(CC) QEMUARCH=$(QEMUARCH) CGO_LDFLAGS=$(CGO_LDFLAGS) $@
|
$(BUILD_IMAGE) COVERAGE=$(COVERAGE) WEAVE_VERSION=$(WEAVE_VERSION) CC=$(CC) QEMUARCH=$(QEMUARCH) CGO_LDFLAGS=$(CGO_LDFLAGS) $@
|
||||||
touch $@
|
touch $@
|
||||||
@@ -215,19 +226,15 @@ ifeq ($(COVERAGE),true)
|
|||||||
else
|
else
|
||||||
go build $(BUILD_FLAGS) -o $@ ./$(@D)
|
go build $(BUILD_FLAGS) -o $@ ./$(@D)
|
||||||
endif
|
endif
|
||||||
$(NETGO_CHECK)
|
|
||||||
|
|
||||||
$(WEAVEUTIL_EXE) $(KUBEUTILS_EXE) $(WEAVENPC_EXE) $(NETWORKTESTER_EXE):
|
$(WEAVEUTIL_EXE) $(KUBEUTILS_EXE) $(WEAVENPC_EXE) $(NETWORKTESTER_EXE):
|
||||||
go build $(BUILD_FLAGS) -o $@ ./$(@D)
|
go build $(BUILD_FLAGS) -o $@ ./$(@D)
|
||||||
$(NETGO_CHECK)
|
|
||||||
|
|
||||||
$(WEAVEWAIT_EXE):
|
$(WEAVEWAIT_EXE):
|
||||||
go build $(BUILD_FLAGS) -tags "netgo iface mcast" -o $@ ./$(@D)
|
go build $(BUILD_FLAGS) -tags "osusergo netgo iface mcast" -o $@ ./$(@D)
|
||||||
$(NETGO_CHECK)
|
|
||||||
|
|
||||||
$(WEAVEWAIT_NOMCAST_EXE):
|
$(WEAVEWAIT_NOMCAST_EXE):
|
||||||
go build $(BUILD_FLAGS) -tags "netgo iface" -o $@ ./$(@D)
|
go build $(BUILD_FLAGS) -tags "osusergo netgo iface" -o $@ ./$(@D)
|
||||||
$(NETGO_CHECK)
|
|
||||||
|
|
||||||
# These programs need a separate rule as they fail the netgo check in
|
# These programs need a separate rule as they fail the netgo check in
|
||||||
# the main build stanza due to not importing net package
|
# the main build stanza due to not importing net package
|
||||||
@@ -392,15 +399,14 @@ clean-bin:
|
|||||||
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(IMAGES)
|
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(IMAGES)
|
||||||
find prog -type f -name "Dockerfile.*" -not -name "Dockerfile.template" -print | xargs rm -f
|
find prog -type f -name "Dockerfile.*" -not -name "Dockerfile.template" -print | xargs rm -f
|
||||||
find prog -type f -name "*qemu-*" -print | xargs rm -f
|
find prog -type f -name "*qemu-*" -print | xargs rm -f
|
||||||
rm -rf $(EXES) $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE) weave*.tar.gz .pkg
|
go clean ./...
|
||||||
|
rm -rf $(EXES) $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE) weave*.tar.gz .cache
|
||||||
|
|
||||||
clean: clean-bin clean-work-dir
|
clean: clean-bin clean-work-dir
|
||||||
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(BUILD_IMAGE)
|
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(BUILD_IMAGE)
|
||||||
rm -rf test/tls/*.pem test/coverage.* test/coverage $(BUILD_UPTODATE)
|
rm -rf test/tls/*.pem test/coverage.* test/coverage $(BUILD_UPTODATE)
|
||||||
|
|
||||||
build:
|
build:
|
||||||
$(SUDO) go clean -i net
|
|
||||||
$(SUDO) go install -tags netgo std
|
|
||||||
$(MAKE)
|
$(MAKE)
|
||||||
|
|
||||||
run-smoketests: all testrunner
|
run-smoketests: all testrunner
|
||||||
@@ -422,14 +428,3 @@ integration-tests: all testrunner
|
|||||||
# integration-tests
|
# integration-tests
|
||||||
#
|
#
|
||||||
RUNNER_ARGS="-parallel" ./test/run-integration-tests.sh
|
RUNNER_ARGS="-parallel" ./test/run-integration-tests.sh
|
||||||
|
|
||||||
# This target is only intended for use in Netlify CI environment for generating preview pages on feature branches and pull requests.
|
|
||||||
# We need to obtain website repository (checked out under `site-build`) and place `site` directory into the context (`site-build/_weave_net_docs`).
|
|
||||||
# We then run make in `site-build` and Netlify will publish the output (`site-build/_site`).
|
|
||||||
netlify-site-preview:
|
|
||||||
@mkdir -p site-build
|
|
||||||
@curl --user $(WEBSITE_GITHUB_USER) --silent 'https://codeload.github.com/weaveworks/website-next/tar.gz/$(WEBSITE_BRANCH)' \
|
|
||||||
| tar --extract --gunzip --directory site-build --strip 1
|
|
||||||
@cp -r site site-build/_weave_net_docs
|
|
||||||
@$(MAKE) -C site-build netlify_ensure_install
|
|
||||||
@$(MAKE) -C site-build BUILD_ENV=netlify
|
|
||||||
@@ -1,43 +1,30 @@
|
|||||||
# Weave Net - Weaving Containers into Applications
|
# ReWeave - an effort to keep Weave Net alive
|
||||||
|
|
||||||
[](https://circleci.com/gh/weaveworks/weave)
|
This repository contains a fork of Weave Net, the first product developed by Weaveworks. Since Weaveworks has shut down, this repo aims to continue maintaining Weave Net, and to publish releases regularly.
|
||||||
[](https://coveralls.io/r/weaveworks/weave)
|
|
||||||
[](https://goreportcard.com/report/github.com/weaveworks/weave)
|
|
||||||
[](https://hub.docker.com/r/weaveworks/weave/)
|
|
||||||
|
|
||||||
# About Weaveworks
|
[](https://goreportcard.com/report/github.com/rajch/weave)
|
||||||
|
[](https://hub.docker.com/r/rajchaudhuri/weave-kube)
|
||||||
|

|
||||||
|
[](reweave/scans/report.md)
|
||||||
|
|
||||||
[Weaveworks](https://www.weave.works) is the company that delivers the most productive way for developers to connect, observe and control
|
The history of the ReWeave effort can be found in [HISTORY.md](HISTORY.md).
|
||||||
Docker containers.
|
|
||||||
|
|
||||||
This repository contains [Weave Net](https://www.weave.works/products/weave-net/), the first product developed by Weaveworks, and with over 8 million downloads to date, enables you to get started with Docker clusters and portable apps in a fraction of the time compared with other solutions.
|
## Using Weave on Kubernetes
|
||||||
|
|
||||||
## Weave Cloud:
|
On a newly created Kubernetes cluster, the Weave Net CNI pluging can be installed by running the following command:
|
||||||
|
|
||||||
[Weave Cloud](https://www.weave.works/product/cloud/) is software-as-a-service that simplifies deployment, monitoring and management for containers and microservices. It extends and complements popular orchestrators, and enables developers and DevOps to realize faster deployments, insightful monitoring, visualization and networking.
|
```
|
||||||
|
kubectl apply -f https://reweave.azurewebsites.net/k8s/v1.28/net.yaml
|
||||||
|
```
|
||||||
|
|
||||||
Weave Cloud is built using these Open Source projects: [Weave Scope](https://www.weave.works/products/weave-scope/), a powerful container visualization tool that automatically maps Docker containers and their interactions, [Weave Cortex](https://github.com/weaveworks/cortex), a horizontally-scalable version of Prometheus, and [Weave Flux](https://www.weave.works/products/weave-flux/), a continuous deployment tool that works with Kubernetes.
|
Replace `v1.28` with the version on Kubernetes on your cluster.
|
||||||
|
|
||||||
# Weave Net
|
That endpoint is provided by the companion project [weave-endpoint](https://github.com/rajch/weave-endpoint).
|
||||||
|
|
||||||
Weave Net creates a virtual network that connects Docker containers across multiple hosts and enables their automatic discovery. With Weave Net, portable microservices-based applications consisting of multiple containers can run anywhere: on one host, multiple hosts or even across cloud providers and data centers. Applications use the network just as if the containers were all plugged into the same network switch, without having to configure port mappings, ambassadors or links.
|
## Building Weave
|
||||||
|
|
||||||
Services provided by application containers on the Weave network can be exposed to the outside world, regardless of where they are running. Similarly, existing internal systems can be opened to accept connections from application containers irrespective of their location.
|
Details can be found [here](reweave/BUILDING.md).
|
||||||
|
|
||||||
## <a name="help"></a>Getting help
|
## Documentation status
|
||||||
|
|
||||||
If you have any questions about, feedback for or a problem with Weave Net:
|
At this point, any information found in directories other than `reweave`, such as `docs` or `site`, should be considered obsolete. In time, those will be updated.
|
||||||
|
|
||||||
- Read [the Weave Net docs](https://www.weave.works/docs/net/latest/overview).
|
|
||||||
- Invite yourself to the <a href="https://weaveworks.github.io/community-slack/" target="_blank"> #weave-community </a> slack channel.
|
|
||||||
- Ask a question on the <a href="https://weave-community.slack.com/messages/general/"> #weave-community</a> slack channel.
|
|
||||||
- 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.
|
|
||||||
- Send an email to <a href="mailto:weave-users@weave.works">weave-users@weave.works</a>
|
|
||||||
- <a href="https://github.com/weaveworks/weave/issues/new">File an issue.</a>
|
|
||||||
|
|
||||||
Your feedback is always welcome!
|
|
||||||
|
|
||||||
## Further Information
|
|
||||||
|
|
||||||
* [Installing Weave Net](https://www.weave.works/docs/net/latest/install/installing-weave)
|
|
||||||
* [Weave Net Product Overview](https://www.weave.works/products/weave-net)
|
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
# 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.
|
||||||
@@ -10,14 +10,7 @@ function signal_failure() {
|
|||||||
trap signal_failure ERR
|
trap signal_failure ERR
|
||||||
|
|
||||||
function install_terraform() {
|
function install_terraform() {
|
||||||
curl -fsS https://releases.hashicorp.com/terraform/0.8.5/terraform_0.8.5_linux_amd64.zip | gunzip >terraform && chmod +x terraform && sudo mv terraform /usr/bin
|
curl -fsS https://releases.hashicorp.com/terraform/0.11.14/terraform_0.11.14_linux_amd64.zip | gunzip >terraform && chmod +x terraform && sudo mv terraform /usr/bin
|
||||||
}
|
|
||||||
|
|
||||||
function install_ansible() {
|
|
||||||
sudo apt-get update || true
|
|
||||||
sudo apt-get install -qq -y python-pip python-dev libffi-dev libssl-dev \
|
|
||||||
&& pip install --user -U setuptools cffi \
|
|
||||||
&& pip install --user ansible
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[ -n "$SECRET_KEY" ] || {
|
[ -n "$SECRET_KEY" ] || {
|
||||||
@@ -28,7 +21,6 @@ function install_ansible() {
|
|||||||
source "$SRCDIR/bin/circle-env"
|
source "$SRCDIR/bin/circle-env"
|
||||||
|
|
||||||
install_terraform
|
install_terraform
|
||||||
install_ansible
|
|
||||||
|
|
||||||
# Only attempt to create GCP image in first container, wait for it to be created otherwise:
|
# Only attempt to create GCP image in first container, wait for it to be created otherwise:
|
||||||
[ "$CIRCLE_NODE_INDEX" != "0" ] && export CREATE_IMAGE=0
|
[ "$CIRCLE_NODE_INDEX" != "0" ] && export CREATE_IMAGE=0
|
||||||
|
|||||||
+31
-46
@@ -89,10 +89,9 @@ 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.yaml
|
|
||||||
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.11.yaml
|
||||||
make SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER
|
make SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER
|
||||||
|
|
||||||
if make tests; then
|
if make tests; then
|
||||||
@@ -161,34 +160,27 @@ draft() {
|
|||||||
--name "weave" \
|
--name "weave" \
|
||||||
--file "./weave"
|
--file "./weave"
|
||||||
|
|
||||||
github-release upload \
|
|
||||||
--user $GITHUB_USER \
|
|
||||||
--repo weave \
|
|
||||||
--tag $LATEST_TAG \
|
|
||||||
--name "weave-daemonset.yaml" \
|
|
||||||
--file "./prog/weave-kube/weave-daemonset.yaml"
|
|
||||||
|
|
||||||
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 \
|
||||||
--tag $LATEST_TAG \
|
--tag $LATEST_TAG \
|
||||||
--name "weave-daemonset-k8s-1.8.yaml" \
|
--name "weave-daemonset-k8s-1.8.yaml" \
|
||||||
--file "./prog/weave-kube/weave-daemonset-k8s-1.8.yaml"
|
--file "./prog/weave-kube/weave-daemonset-k8s-1.8.yaml"
|
||||||
|
|
||||||
|
github-release upload \
|
||||||
|
--user $GITHUB_USER \
|
||||||
|
--repo weave \
|
||||||
|
--tag $LATEST_TAG \
|
||||||
|
--name "weave-daemonset-k8s-1.9.yaml" \
|
||||||
|
--file "./prog/weave-kube/weave-daemonset-k8s-1.9.yaml"
|
||||||
|
|
||||||
|
github-release upload \
|
||||||
|
--user $GITHUB_USER \
|
||||||
|
--repo weave \
|
||||||
|
--tag $LATEST_TAG \
|
||||||
|
--name "weave-daemonset-k8s-1.11.yaml" \
|
||||||
|
--file "./prog/weave-kube/weave-daemonset-k8s-1.11.yaml"
|
||||||
|
|
||||||
echo "** Draft $TYPE $RELEASE_NAME $VERSION created at"
|
echo "** Draft $TYPE $RELEASE_NAME $VERSION created at"
|
||||||
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
|
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
|
||||||
}
|
}
|
||||||
@@ -276,27 +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.yaml" \
|
|
||||||
--file "./prog/weave-kube/weave-daemonset.yaml"
|
|
||||||
|
|
||||||
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 \
|
||||||
@@ -304,6 +275,20 @@ publish() {
|
|||||||
--name "weave-daemonset-k8s-1.8.yaml" \
|
--name "weave-daemonset-k8s-1.8.yaml" \
|
||||||
--file "./prog/weave-kube/weave-daemonset-k8s-1.8.yaml"
|
--file "./prog/weave-kube/weave-daemonset-k8s-1.8.yaml"
|
||||||
|
|
||||||
|
github-release upload \
|
||||||
|
--user $GITHUB_USER \
|
||||||
|
--repo weave \
|
||||||
|
--tag latest_release \
|
||||||
|
--name "weave-daemonset-k8s-1.9.yaml" \
|
||||||
|
--file "./prog/weave-kube/weave-daemonset-k8s-1.9.yaml"
|
||||||
|
|
||||||
|
github-release upload \
|
||||||
|
--user $GITHUB_USER \
|
||||||
|
--repo weave \
|
||||||
|
--tag latest_release \
|
||||||
|
--name "weave-daemonset-k8s-1.11.yaml" \
|
||||||
|
--file "./prog/weave-kube/weave-daemonset-k8s-1.11.yaml"
|
||||||
|
|
||||||
echo "** Release $RELEASE_NAME $VERSION published at"
|
echo "** Release $RELEASE_NAME $VERSION published at"
|
||||||
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
|
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
|
||||||
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/latest_release"
|
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/latest_release"
|
||||||
|
|||||||
+8
-21
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.10.1-stretch
|
FROM golang:1.15.6-buster
|
||||||
|
|
||||||
# Support Raspberry Pi 2 and newer
|
# Support Raspberry Pi 2 and newer
|
||||||
ENV GOARM 7
|
ENV GOARM 7
|
||||||
@@ -7,25 +7,25 @@ ENV GOARM 7
|
|||||||
ENV DEB_CROSSPLATFORMS \
|
ENV DEB_CROSSPLATFORMS \
|
||||||
armhf \
|
armhf \
|
||||||
arm64 \
|
arm64 \
|
||||||
ppc64el
|
ppc64el \
|
||||||
|
s390x
|
||||||
|
|
||||||
# The go platforms we are supporting to cross-compile
|
# The go platforms we are supporting to cross-compile
|
||||||
ENV GO_CROSSPLATFORMS \
|
ENV GO_CROSSPLATFORMS \
|
||||||
linux/arm \
|
linux/arm \
|
||||||
linux/arm64 \
|
linux/arm64 \
|
||||||
linux/ppc64le
|
linux/ppc64le \
|
||||||
|
linux/s390x
|
||||||
|
|
||||||
# The names of the gcc cross-compilers we have installed
|
# The names of the gcc cross-compilers we have installed
|
||||||
ENV GCC_CROSSCOMPILERS \
|
ENV GCC_CROSSCOMPILERS \
|
||||||
arm-linux-gnueabihf \
|
arm-linux-gnueabihf \
|
||||||
aarch64-linux-gnu \
|
aarch64-linux-gnu \
|
||||||
powerpc64le-linux-gnu
|
powerpc64le-linux-gnu \
|
||||||
|
s390x-linux-gnu
|
||||||
|
|
||||||
# Temporarily add the Debian repositories, because we're going to install gcc cross-compilers from there
|
|
||||||
# Install the build-essential and crossbuild-essential-ARCH packages
|
# Install the build-essential and crossbuild-essential-ARCH packages
|
||||||
RUN echo "deb http://emdebian.org/tools/debian/ jessie main" > /etc/apt/sources.list.d/cgocrosscompiling.list \
|
RUN for platform in ${DEB_CROSSPLATFORMS}; do dpkg --add-architecture $platform; done \
|
||||||
&& curl http://emdebian.org/tools/debian/emdebian-toolchain-archive.key | apt-key add - \
|
|
||||||
&& for platform in ${DEB_CROSSPLATFORMS}; do dpkg --add-architecture $platform; done \
|
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get install -y build-essential \
|
&& apt-get install -y build-essential \
|
||||||
&& for platform in ${DEB_CROSSPLATFORMS}; do apt-get install -y crossbuild-essential-${platform}; done \
|
&& for platform in ${DEB_CROSSPLATFORMS}; do apt-get install -y crossbuild-essential-${platform}; done \
|
||||||
@@ -57,19 +57,6 @@ RUN go get \
|
|||||||
github.com/fatih/hclfmt \
|
github.com/fatih/hclfmt \
|
||||||
github.com/client9/misspell/cmd/misspell
|
github.com/client9/misspell/cmd/misspell
|
||||||
|
|
||||||
# First clean, because we're gonna rebuild the std both with -race enabled and disabled
|
|
||||||
# Running go install std twice is intentional and required, as content is written in two different directories
|
|
||||||
# (/usr/local/go/pkg/linux_amd64 vs /usr/local/go/pkg/linux_amd64_race)
|
|
||||||
# The other architectures do not have support for -race
|
|
||||||
RUN go clean -i net \
|
|
||||||
&& go install -tags netgo std \
|
|
||||||
&& go install -race -tags netgo std
|
|
||||||
|
|
||||||
# Prebuild std for the other architectures
|
|
||||||
RUN for platform in ${GO_CROSSPLATFORMS}; do \
|
|
||||||
GOOS=${platform%/*} GOARCH=${platform##*/} \
|
|
||||||
go install -tags netgo std; done
|
|
||||||
|
|
||||||
# Allow full write access to the Go folders for anyone
|
# Allow full write access to the Go folders for anyone
|
||||||
RUN chmod -R a+w /usr/local/go
|
RUN chmod -R a+w /usr/local/go
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
bab3b4d04263479b3d9f85cf59bd0cad1f2b434f29856b2204f8288f2f3598e4 qemu-s390x-static
|
||||||
@@ -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"
|
||||||
|
)
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
docker "github.com/fsouza/go-dockerclient"
|
docker "github.com/fsouza/go-dockerclient"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -99,7 +99,9 @@ func (c *Client) AddObserver(ob ContainerObserver) error {
|
|||||||
pending := make(pendingStarts)
|
pending := make(pendingStarts)
|
||||||
retryInterval := InitialInterval
|
retryInterval := InitialInterval
|
||||||
for {
|
for {
|
||||||
events := make(chan *docker.APIEvents)
|
// Use a buffered chan so the client library can run ahead of the listener
|
||||||
|
// - Docker will drop an event if it is not collected quickly enough.
|
||||||
|
events := make(chan *docker.APIEvents, 1024)
|
||||||
if err := c.AddEventListener(events); err != nil {
|
if err := c.AddEventListener(events); err != nil {
|
||||||
c.errorf("Unable to add listener to Docker API: %s - retrying in %ds", err, retryInterval/time.Second)
|
c.errorf("Unable to add listener to Docker API: %s - retrying in %ds", err, retryInterval/time.Second)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -54,6 +54,12 @@ func SetLogLevel(levelname string) {
|
|||||||
Log.Level = level
|
Log.Level = level
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckError(e error) {
|
||||||
|
if e != nil {
|
||||||
|
Log.Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func CheckFatal(e error) {
|
func CheckFatal(e error) {
|
||||||
if e != nil {
|
if e != nil {
|
||||||
Log.Fatal(e)
|
Log.Fatal(e)
|
||||||
|
|||||||
+1
-1
@@ -64,7 +64,7 @@ To add new options to how weave should run with each invocation, you would do th
|
|||||||
5. Add a command-line option `--option` to `weaveutil` or `weaver` as appropriate.
|
5. Add a command-line option `--option` to `weaveutil` or `weaver` as appropriate.
|
||||||
6. If the option can be configured for CNI:
|
6. If the option can be configured for CNI:
|
||||||
* have `prog/weave-kube/launch.sh` read it as an environment variable and set inside
|
* have `prog/weave-kube/launch.sh` read it as an environment variable and set inside
|
||||||
* set a default for the environment variable in `prog/weave-kube/weave-daemonset-k8s-1.6.yaml` and `weave-daemonset.yaml`
|
* set a default for the environment variable in `prog/weave-kube/weave-daemonset-k8s-N.N.yaml`
|
||||||
* if it should be set via `weaver` globally on its one-time initialization invocation, pass it on in `launch.sh`
|
* if it should be set via `weaver` globally on its one-time initialization invocation, pass it on in `launch.sh`
|
||||||
* if it needs to be set via `weaveutil` on each invocation of `weave-net`, have `launch.sh` save it as an option in the CNI config file `/etc/cni/net.d/10-weave.conflist` and then have the CNI code in `plugin/net/cni.go` in `weaveutil` read it and use where appropriate
|
* if it needs to be set via `weaveutil` on each invocation of `weave-net`, have `launch.sh` save it as an option in the CNI config file `/etc/cni/net.d/10-weave.conflist` and then have the CNI code in `plugin/net/cni.go` in `weaveutil` read it and use where appropriate
|
||||||
7. Document it!
|
7. Document it!
|
||||||
+2
-2
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
* Weave Net: v2.2.1.
|
* Weave Net: v2.2.1.
|
||||||
* Kubernetes: v1.10.0.
|
* Kubernetes: v1.10.0.
|
||||||
* kube-proxy: iptables mode (default kubeadm options).
|
* kube-proxy: iptables/ipvs mode with `--masquerade-all=false` and `--cluster-cidr` unspecified(default kubeadm options).
|
||||||
* Hosts: `h1` and `h2`.
|
* Hosts: `h1` and `h2`.
|
||||||
|
|
||||||
## Source IP
|
## Source IP
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
1 | Pod_h1 | ip(Pod_h2) | Pod_h2 | ip(Pod_h1) | OK
|
1 | Pod_h1 | ip(Pod_h2) | Pod_h2 | ip(Pod_h1) | OK
|
||||||
2 | h1 | ClusterIP | Pod_h1 | ip(weave_h1) | **NOK**
|
2 | h1 | ClusterIP | Pod_h1 | ip(weave_h1) | **NOK**
|
||||||
3 | h1 | ClusterIP | Pod_h2 | ip(weave_h1) | OK
|
3 | h1 | ClusterIP | Pod_h2 | ip(weave_h1) | OK
|
||||||
4 | Pod_h1 | ClusterIP | Pod_h1 | ip(weave_h1) | **NOK**
|
4 | Pod_h1 | ClusterIP | Pod_h1 | ip(Pod_h1) | OK
|
||||||
5 | Pod_h1 | ClusterIP | Pod_h2 | ip(weave_h1) | OK
|
5 | Pod_h1 | ClusterIP | Pod_h2 | ip(weave_h1) | OK
|
||||||
6 | h1 | ip(h1):NodePort | Pod_h1 | ip(weave_h1) | **NOK**
|
6 | h1 | ip(h1):NodePort | Pod_h1 | ip(weave_h1) | **NOK**
|
||||||
7 | h1 | ip(h1):NodePort | Pod_h2 | ip(weave_h1) | OK
|
7 | h1 | ip(h1):NodePort | Pod_h2 | ip(weave_h1) | OK
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
* Up-to-date versions of `git`, `go` etc
|
* Up-to-date versions of `git`, `go` etc
|
||||||
* Install GitHub release tool `go get github.com/weaveworks/github-release`
|
* Install GitHub release tool `go get github.com/weaveworks/github-release`
|
||||||
|
* Install manifest tool `go get github.com/estesp/manifest-tool`
|
||||||
* Create a [github token for
|
* Create a [github token for
|
||||||
github-release](https://help.github.com/articles/creating-an-access-token-for-command-line-use/); select the `repo` OAuth scope; set and export `$GITHUB_TOKEN` with this value
|
github-release](https://help.github.com/articles/creating-an-access-token-for-command-line-use/); select the `repo` OAuth scope; set and export `$GITHUB_TOKEN` with this value
|
||||||
|
|
||||||
@@ -135,7 +136,7 @@ Now, you can validate whether images were published for all platforms:
|
|||||||
# Published platforms per image:
|
# Published platforms per image:
|
||||||
for img in $(grep '^PUBLISH=' Makefile); do
|
for img in $(grep '^PUBLISH=' Makefile); do
|
||||||
img="weaveworks/$(echo $img | cut -d_ -f2):${TAG#v}"
|
img="weaveworks/$(echo $img | cut -d_ -f2):${TAG#v}"
|
||||||
platforms=$(vendor/github.com/estesp/manifest-tool/manifest-tool \
|
platforms=$(manifest-tool \
|
||||||
inspect --raw "$img" | \
|
inspect --raw "$img" | \
|
||||||
jq '.[].Platform | .os + "/" +.architecture' | \
|
jq '.[].Platform | .os + "/" +.architecture' | \
|
||||||
tr '\n' ' ')
|
tr '\n' ' ')
|
||||||
|
|||||||
+62
-12
@@ -9,7 +9,9 @@ destroyed automatically in response to Pod, Namespace and
|
|||||||
NetworkPolicy object updates from the k8s API server:
|
NetworkPolicy object updates from the k8s API server:
|
||||||
|
|
||||||
* A `hash:ip` set per namespace, containing the IP addresses of all
|
* A `hash:ip` set per namespace, containing the IP addresses of all
|
||||||
pods in that namespace
|
pods in that namespace for which default ingress is allowed
|
||||||
|
* A `hash:ip` set per namespace, containing the IP addresses of all
|
||||||
|
pods in that namespace for which default egress is allowed
|
||||||
* A `list:set` per distinct (across all network policies in all
|
* A `list:set` per distinct (across all network policies in all
|
||||||
namespaces) namespace selector mentioned in a network policy,
|
namespaces) namespace selector mentioned in a network policy,
|
||||||
containing the names of any of the above hash:ip sets whose
|
containing the names of any of the above hash:ip sets whose
|
||||||
@@ -18,6 +20,9 @@ NetworkPolicy object updates from the k8s API server:
|
|||||||
containing network policy's namespace) pod selector mentioned in a
|
containing network policy's namespace) pod selector mentioned in a
|
||||||
network policy, containing the IP addresses of all pods in the
|
network policy, containing the IP addresses of all pods in the
|
||||||
namespace whose labels match that selector
|
namespace whose labels match that selector
|
||||||
|
* A `hash:net` set for each distinct (within the scope of the
|
||||||
|
containing network policy's namespace) `except` list of CIDR's mentioned in
|
||||||
|
the network policies
|
||||||
|
|
||||||
IPsets are implemented by the kernel module `xt_set`, without which
|
IPsets are implemented by the kernel module `xt_set`, without which
|
||||||
weave-npc will not work.
|
weave-npc will not work.
|
||||||
@@ -38,11 +43,21 @@ hashing to avoid clashes.
|
|||||||
|
|
||||||
# iptables chains
|
# iptables chains
|
||||||
|
|
||||||
The policy controller maintains two iptables chains in response to
|
The policy controller maintains several iptables chains in response to
|
||||||
changes to pods, namespaces and network policies. One chain contains
|
changes to pods, namespaces and network policies.
|
||||||
the ingress rules that implement the network policy specifications,
|
|
||||||
and the other is used to bypass the ingress rules for namespaces which
|
## Static `WEAVE-NPC` chain
|
||||||
have an ingress isolation policy of `DefaultAllow`.
|
|
||||||
|
`WEAVE-NPC` chain contains static rules to ACCEPT traffic that is `RELATED,ESTABLISHED`
|
||||||
|
and run `NEW` traffic through `WEAVE-NPC-DEFAULT` followed by `WEAVE-NPC-INGRESS` chains
|
||||||
|
|
||||||
|
Static configuration:
|
||||||
|
|
||||||
|
```
|
||||||
|
iptables -A WEAVE-NPC -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||||
|
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-DEFAULT
|
||||||
|
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-INGRESS
|
||||||
|
```
|
||||||
|
|
||||||
## Dynamically maintained `WEAVE-NPC-DEFAULT` chain
|
## Dynamically maintained `WEAVE-NPC-DEFAULT` chain
|
||||||
|
|
||||||
@@ -63,23 +78,58 @@ For each namespace network policy ingress rule peer/port combination:
|
|||||||
iptables -A WEAVE-NPC-INGRESS -p $PROTO [-m set --match-set $SRCSET] -m set --match-set $DSTSET --dport $DPORT -j ACCEPT
|
iptables -A WEAVE-NPC-INGRESS -p $PROTO [-m set --match-set $SRCSET] -m set --match-set $DSTSET --dport $DPORT -j ACCEPT
|
||||||
```
|
```
|
||||||
|
|
||||||
## Static `WEAVE-NPC` chain
|
## Static `WEAVE-NPC-EGRESS` chain
|
||||||
|
|
||||||
|
`WEAVE-NPC-EGRESS` chain contains static rules to ACCEPT traffic that is `RELATED,ESTABLISHED`
|
||||||
|
and run `NEW` traffic through `WEAVE-NPC-EGRESS-DEFAULT` followed by `WEAVE-NPC-EGRESS-CUSTOM` chains
|
||||||
|
|
||||||
Static configuration:
|
Static configuration:
|
||||||
|
|
||||||
```
|
```
|
||||||
iptables -A WEAVE-NPC -m state --state RELATED,ESTABLISHED -j ACCEPT
|
iptables -A WEAVE-NPC-EGRESS -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||||
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-DEFAULT
|
iptables -A WEAVE-NPC-EGRESS -m state --state NEW -j WEAVE-NPC-EGRESS-DEFAULT
|
||||||
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-INGRESS
|
iptables -A WEAVE-NPC-EGRESS -m state --state NEW -m mark ! --mark 0x40000/0x40000 -j WEAVE-NPC-EGRESS-CUSTOM
|
||||||
|
iptables -A WEAVE-NPC-EGRESS -m mark ! --mark 0x40000/0x40000 -j DROP
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Dynamically maintained `WEAVE-NPC-EGRESS-DEFAULT` chain
|
||||||
|
|
||||||
|
The policy controller maintains a rule in this chain for every
|
||||||
|
namespace whose egress isolation policy is `DefaultAllow`. The
|
||||||
|
purpose of this rule is simply to ACCEPT any traffic originating from such namespace before it reaches the egress chain.
|
||||||
|
|
||||||
|
```
|
||||||
|
iptables -A WEAVE-NPC-EGRESS-DEFAULT -m set --match-set $NSIPSET src -j WEAVE-NPC-EGRESS-ACCEPT
|
||||||
|
iptables -A WEAVE-NPC-EGRESS-DEFAULT -m set --match-set $NSIPSET src -j RETURN
|
||||||
|
```
|
||||||
|
|
||||||
|
## Static `WEAVE-NPC-EGRESS-ACCEPT` chain
|
||||||
|
|
||||||
|
`WEAVE-NPC-EGRESS-ACCEPTS` chain contains static rules to mark traffic
|
||||||
|
|
||||||
|
Static configuration:
|
||||||
|
|
||||||
|
```
|
||||||
|
iptables -A WEAVE-NPC-EGRESS-ACCEPT -j MARK --set-xmark 0x40000/0x40000
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dynamically maintained `WEAVE-NPC-EGRESS-CUSTOM` chain
|
||||||
|
|
||||||
|
For each namespace network policy egress rule peer/port combination:
|
||||||
|
|
||||||
|
```
|
||||||
|
iptables -A WEAVE-NPC-EGRESS-CUSTOM -p $PROTO [-m set --match-set $SRCSET] -m set --match-set $DSTSET --dport $DPORT -j ACCEPT
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
# Steering traffic into the policy engine
|
# Steering traffic into the policy engine
|
||||||
|
|
||||||
To direct traffic into the policy engine:
|
To direct traffic into the policy engine:
|
||||||
|
|
||||||
```
|
```
|
||||||
iptables -A FORWARD -o weave -m physdev ! --physdev-out vethwe-bridge -j WEAVE-NPC
|
iptables -A INPUT -i weave -j WEAVE-NPC-EGRESS
|
||||||
iptables -A FORWARD -o weave -m physdev ! --physdev-out vethwe-bridge -j DROP
|
iptables -A FORWARD -i weave -j WEAVE-NPC-EGRESS
|
||||||
|
iptables -A FORWARD -o weave -j WEAVE-NPC
|
||||||
```
|
```
|
||||||
|
|
||||||
Note this only affects traffic which egresses the bridge on a physical
|
Note this only affects traffic which egresses the bridge on a physical
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
module github.com/rajch/weave
|
||||||
|
|
||||||
|
go 1.21
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/andybalholm/go-bit v1.0.1
|
||||||
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
|
||||||
|
github.com/aws/aws-sdk-go v1.34.0
|
||||||
|
github.com/boltdb/bolt v1.3.1
|
||||||
|
github.com/containernetworking/cni v1.1.2
|
||||||
|
github.com/containernetworking/plugins v1.2.0
|
||||||
|
github.com/coreos/go-iptables v0.6.0
|
||||||
|
github.com/docker/docker v24.0.7+incompatible
|
||||||
|
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.10.0
|
||||||
|
github.com/google/gopacket v1.1.16
|
||||||
|
github.com/gorilla/mux v1.8.0
|
||||||
|
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56
|
||||||
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
|
||||||
|
github.com/miekg/dns v1.1.52
|
||||||
|
github.com/pkg/errors v0.9.1
|
||||||
|
github.com/pkg/profile v1.2.1
|
||||||
|
github.com/prometheus/client_golang v1.14.0
|
||||||
|
github.com/sirupsen/logrus v1.9.3
|
||||||
|
github.com/stretchr/testify v1.8.4
|
||||||
|
github.com/vishvananda/netlink v1.2.1-beta.2
|
||||||
|
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f
|
||||||
|
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.17.0
|
||||||
|
golang.org/x/sys v0.15.0
|
||||||
|
golang.org/x/tools v0.10.0
|
||||||
|
k8s.io/api v0.26.2
|
||||||
|
k8s.io/apimachinery v0.26.2
|
||||||
|
k8s.io/client-go v0.26.2
|
||||||
|
)
|
||||||
|
|
||||||
|
require github.com/spf13/cobra v1.6.1
|
||||||
|
|
||||||
|
require github.com/mattn/go-isatty v0.0.18 // indirect
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||||
|
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
|
github.com/containerd/containerd v1.7.11 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/docker/distribution v2.8.2-beta.1+incompatible // indirect
|
||||||
|
github.com/docker/go-connections v0.4.0 // indirect
|
||||||
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
|
github.com/emicklei/go-restful/v3 v3.10.1 // indirect
|
||||||
|
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||||
|
github.com/go-logr/logr v1.2.4 // indirect
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
|
github.com/go-openapi/jsonreference v0.20.0 // indirect
|
||||||
|
github.com/go-openapi/swag v0.19.14 // indirect
|
||||||
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
|
github.com/google/gnostic v0.5.7-v3refs // indirect
|
||||||
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
|
github.com/hashicorp/go-cleanhttp v0.0.0-20171218145408-d5fe4b57a186 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||||
|
github.com/jmespath/go-jmespath v0.3.0 // indirect
|
||||||
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/klauspost/compress v1.16.0 // indirect
|
||||||
|
github.com/mailru/easyjson v0.7.6 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.0.9 // indirect
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||||
|
github.com/mdlayher/raw v0.0.0-20181016155347-fa5ef3332ca9 // indirect
|
||||||
|
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||||
|
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||||
|
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect
|
||||||
|
github.com/opencontainers/runc v1.1.12 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/prometheus/client_model v0.3.0 // indirect
|
||||||
|
github.com/prometheus/common v0.37.0 // indirect
|
||||||
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
|
github.com/rootless-containers/rootlesskit v1.1.0 // indirect
|
||||||
|
github.com/safchain/ethtool v0.2.0 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
golang.org/x/mod v0.11.0 // indirect
|
||||||
|
golang.org/x/net v0.17.0 // indirect
|
||||||
|
golang.org/x/oauth2 v0.10.0 // indirect
|
||||||
|
golang.org/x/term v0.15.0 // indirect
|
||||||
|
golang.org/x/text v0.14.0 // indirect
|
||||||
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
||||||
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
|
google.golang.org/protobuf v1.31.0 // indirect
|
||||||
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
k8s.io/klog/v2 v2.90.1 // indirect
|
||||||
|
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
|
||||||
|
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect
|
||||||
|
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
|
||||||
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||||
|
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||||
|
)
|
||||||
@@ -0,0 +1,729 @@
|
|||||||
|
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=
|
||||||
|
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||||
|
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||||
|
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||||
|
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||||
|
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||||
|
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||||
|
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||||
|
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||||
|
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||||
|
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||||
|
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||||
|
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||||
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||||
|
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||||
|
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||||
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
|
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
|
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
|
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||||
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
|
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||||
|
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||||
|
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
|
||||||
|
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/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||||
|
github.com/andybalholm/go-bit v1.0.1 h1:GihKSzvvcJKJtMFvPov8ITgdDvHxHt5p5whGyptxzwc=
|
||||||
|
github.com/andybalholm/go-bit v1.0.1/go.mod h1:ezUwZUxOwUxgSjWJxb7p3Lo5dTdBBvImVcb6EsHgg8I=
|
||||||
|
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.34.0 h1:brux2dRrlwCF5JhTL7MUT3WUwo9zfDHZZp3+g3Mvlmo=
|
||||||
|
github.com/aws/aws-sdk-go v1.34.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||||
|
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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
|
github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw=
|
||||||
|
github.com/containerd/containerd v1.7.11/go.mod h1:5UluHxHTX2rdvYuZ5OJTC5m/KJNs0Zs9wVoJm9zf5ZE=
|
||||||
|
github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ=
|
||||||
|
github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw=
|
||||||
|
github.com/containernetworking/plugins v1.2.0 h1:SWgg3dQG1yzUo4d9iD8cwSVh1VqI+bP7mkPDoSfP9VU=
|
||||||
|
github.com/containernetworking/plugins v1.2.0/go.mod h1:/VjX4uHecW5vVimFa1wkG4s+r/s9qIfPdqlLF4TW8c4=
|
||||||
|
github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk=
|
||||||
|
github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
|
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||||
|
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/docker/distribution v2.8.2-beta.1+incompatible h1:gILO60VLD2v28ozemv4aAwDb8ds5U2O/vD/sBXbd7Rw=
|
||||||
|
github.com/docker/distribution v2.8.2-beta.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
|
github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
|
||||||
|
github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
|
github.com/docker/go-units v0.5.0/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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||||
|
github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ=
|
||||||
|
github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
|
||||||
|
github.com/evanphx/json-patch v4.12.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/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
|
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||||
|
github.com/fsouza/go-dockerclient v1.10.0 h1:ppSBsbR60I1DFbV4Ag7LlHlHakHFRNLk9XakATW1yVQ=
|
||||||
|
github.com/fsouza/go-dockerclient v1.10.0/go.mod h1:+iNzAW78AzClIBTZ6WFjkaMvOgz68GyCJ236b1opLTs=
|
||||||
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
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-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||||
|
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||||
|
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-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||||
|
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||||
|
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||||
|
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
|
github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
|
||||||
|
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
|
||||||
|
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
|
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
|
||||||
|
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||||
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
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/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
|
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
|
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.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||||
|
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.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
|
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||||
|
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
|
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/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
|
||||||
|
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
|
||||||
|
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.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
|
github.com/google/gofuzz v1.2.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/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
|
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
|
github.com/google/uuid v1.3.0/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/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
|
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/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
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.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
|
||||||
|
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||||
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
|
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||||
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||||
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
|
||||||
|
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/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/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
|
||||||
|
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
|
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.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
|
||||||
|
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||||
|
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.1.52 h1:Bmlc/qsNNULOe6bpXcUTsuOajd0DzRHwup6D9k1An0c=
|
||||||
|
github.com/miekg/dns v1.1.52/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
||||||
|
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||||
|
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||||
|
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||||
|
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||||
|
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
|
||||||
|
github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||||
|
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/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||||
|
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
|
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
|
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||||
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs=
|
||||||
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
|
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||||
|
github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
|
||||||
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||||
|
github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss=
|
||||||
|
github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8=
|
||||||
|
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/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
|
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||||
|
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||||
|
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
|
||||||
|
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
|
||||||
|
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.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
||||||
|
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
||||||
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||||
|
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||||
|
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
|
||||||
|
github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
|
||||||
|
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
|
||||||
|
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/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||||
|
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
|
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
|
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||||
|
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
|
github.com/rootless-containers/rootlesskit v1.1.0 h1:cRaRIYxY8oce4eE/zeAUZhgKu/4tU1p9YHN4+suwV7M=
|
||||||
|
github.com/rootless-containers/rootlesskit v1.1.0/go.mod h1:H+o9ndNe7tS91WqU0/+vpvc+VaCd7TCIWaJjnV0ujUo=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/safchain/ethtool v0.2.0 h1:dILxMBqDnQfX192cCAPjZr9v2IgVXeElHPy435Z/IdE=
|
||||||
|
github.com/safchain/ethtool v0.2.0/go.mod h1:WkKB1DnNtvsMlDmQ50sgwowDJV/hGbJSOvJoEXs1AJQ=
|
||||||
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
|
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||||
|
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||||
|
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/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||||
|
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/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=
|
||||||
|
github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
|
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/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||||
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||||
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
|
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
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/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||||
|
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
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/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||||
|
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
|
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/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||||
|
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||||
|
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||||
|
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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
|
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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
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-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||||
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||||
|
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
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/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
||||||
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/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-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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
|
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
|
||||||
|
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
|
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||||
|
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||||
|
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
|
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||||
|
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/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
|
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||||
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
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/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
|
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||||
|
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||||
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
|
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||||
|
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||||
|
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
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.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||||
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||||
|
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
|
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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
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/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/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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||||
|
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=
|
||||||
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
k8s.io/api v0.26.2 h1:dM3cinp3PGB6asOySalOZxEG4CZ0IAdJsrYZXE/ovGQ=
|
||||||
|
k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU=
|
||||||
|
k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ=
|
||||||
|
k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I=
|
||||||
|
k8s.io/client-go v0.26.2 h1:s1WkVujHX3kTp4Zn4yGNFK+dlDXy1bAAkIl+cFAiuYI=
|
||||||
|
k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU=
|
||||||
|
k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw=
|
||||||
|
k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||||
|
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E=
|
||||||
|
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
|
||||||
|
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk=
|
||||||
|
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
|
||||||
|
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
|
||||||
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
|
||||||
|
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||||
|
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||||
+2
-2
@@ -3,8 +3,8 @@ package ipam
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/api"
|
"github.com/rajch/weave/api"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
type allocateResult struct {
|
type allocateResult struct {
|
||||||
|
|||||||
+21
-25
@@ -9,13 +9,13 @@ import (
|
|||||||
|
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/db"
|
"github.com/rajch/weave/db"
|
||||||
"github.com/weaveworks/weave/ipam/paxos"
|
"github.com/rajch/weave/ipam/paxos"
|
||||||
"github.com/weaveworks/weave/ipam/ring"
|
"github.com/rajch/weave/ipam/ring"
|
||||||
"github.com/weaveworks/weave/ipam/space"
|
"github.com/rajch/weave/ipam/space"
|
||||||
"github.com/weaveworks/weave/ipam/tracker"
|
"github.com/rajch/weave/ipam/tracker"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Kinds of message we can unicast to other peers
|
// Kinds of message we can unicast to other peers
|
||||||
@@ -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 {
|
||||||
@@ -275,7 +260,7 @@ func (alloc *Allocator) spaceRequestDenied(sender mesh.PeerName, r address.Range
|
|||||||
for i := 0; i < len(alloc.pendingClaims); {
|
for i := 0; i < len(alloc.pendingClaims); {
|
||||||
claim := alloc.pendingClaims[i].(*claim)
|
claim := alloc.pendingClaims[i].(*claim)
|
||||||
if r.Contains(claim.cidr.Addr) {
|
if r.Contains(claim.cidr.Addr) {
|
||||||
claim.deniedBy(alloc, sender)
|
claim.deniedBy(alloc, sender, nil)
|
||||||
alloc.pendingClaims = append(alloc.pendingClaims[:i], alloc.pendingClaims[i+1:]...)
|
alloc.pendingClaims = append(alloc.pendingClaims[:i], alloc.pendingClaims[i+1:]...)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -556,7 +541,8 @@ func (alloc *Allocator) annotatePeernames(names []mesh.PeerName) []string {
|
|||||||
// in the ring. Async.
|
// in the ring. Async.
|
||||||
//
|
//
|
||||||
// NB: the function is invoked by the gossip library routines and should be
|
// NB: the function is invoked by the gossip library routines and should be
|
||||||
// registered manually.
|
//
|
||||||
|
// registered manually.
|
||||||
func (alloc *Allocator) PeerGone(peerName mesh.PeerName) {
|
func (alloc *Allocator) PeerGone(peerName mesh.PeerName) {
|
||||||
alloc.debugf("PeerGone: peer %s", peerName)
|
alloc.debugf("PeerGone: peer %s", peerName)
|
||||||
|
|
||||||
@@ -814,6 +800,16 @@ func (alloc *Allocator) sendRingUpdate(dest mesh.PeerName) {
|
|||||||
alloc.gossip.GossipUnicast(dest, msg)
|
alloc.gossip.GossipUnicast(dest, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (alloc *Allocator) hasAllocations(rs []address.Range) bool {
|
||||||
|
for _, r := range rs {
|
||||||
|
alloc.debugf("hasAllocations: %v %v vs %v", r, alloc.space.NumFreeAddressesInRange(r), r.Size())
|
||||||
|
if alloc.space.NumFreeAddressesInRange(r) != r.Size() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (alloc *Allocator) update(sender mesh.PeerName, msg []byte) error {
|
func (alloc *Allocator) update(sender mesh.PeerName, msg []byte) error {
|
||||||
reader := bytes.NewReader(msg)
|
reader := bytes.NewReader(msg)
|
||||||
decoder := gob.NewDecoder(reader)
|
decoder := gob.NewDecoder(reader)
|
||||||
@@ -832,7 +828,7 @@ func (alloc *Allocator) update(sender mesh.PeerName, msg []byte) error {
|
|||||||
// If someone sent us a ring, merge it into ours. Note this will move us
|
// If someone sent us a ring, merge it into ours. Note this will move us
|
||||||
// out of the awaiting-consensus state if we didn't have a ring already.
|
// out of the awaiting-consensus state if we didn't have a ring already.
|
||||||
case data.Ring != nil:
|
case data.Ring != nil:
|
||||||
updated, err := alloc.ring.Merge(*data.Ring)
|
updated, err := alloc.ring.Merge(*data.Ring, alloc.hasAllocations)
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
if updated {
|
if updated {
|
||||||
|
|||||||
@@ -9,16 +9,14 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/api"
|
"github.com/rajch/weave/api"
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
"github.com/weaveworks/weave/testing/gossip"
|
"github.com/rajch/weave/testing/gossip"
|
||||||
)
|
)
|
||||||
|
|
||||||
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 }
|
||||||
|
|||||||
+18
-7
@@ -5,13 +5,14 @@ import (
|
|||||||
|
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/api"
|
"github.com/rajch/weave/api"
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
type claim struct {
|
type claim struct {
|
||||||
resultChan chan<- error
|
resultChan chan<- error
|
||||||
|
tryCount int
|
||||||
ident string // a container ID, something like "weave:expose", or api.NoContainerID
|
ident string // a container ID, something like "weave:expose", or api.NoContainerID
|
||||||
cidr address.CIDR // single address being claimed
|
cidr address.CIDR // single address being claimed
|
||||||
isContainer bool // true if ident is a container ID
|
isContainer bool // true if ident is a container ID
|
||||||
@@ -19,6 +20,8 @@ type claim struct {
|
|||||||
hasBeenCancelled func() bool
|
hasBeenCancelled func() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const maxTryCount = 5
|
||||||
|
|
||||||
// Send an error (or nil for success) back to caller listening on resultChan
|
// Send an error (or nil for success) back to caller listening on resultChan
|
||||||
func (c *claim) sendResult(result error) {
|
func (c *claim) sendResult(result error) {
|
||||||
// Make sure we only send a result once, since listener stops listening after that
|
// Make sure we only send a result once, since listener stops listening after that
|
||||||
@@ -40,6 +43,8 @@ func (c *claim) Try(alloc *Allocator) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.tryCount++
|
||||||
|
|
||||||
addOwned := func() {
|
addOwned := func() {
|
||||||
if c.ident == api.NoContainerID {
|
if c.ident == api.NoContainerID {
|
||||||
alloc.addOwned(c.cidr.Addr.String(), c.cidr, c.isContainer)
|
alloc.addOwned(c.cidr.Addr.String(), c.cidr, c.isContainer)
|
||||||
@@ -90,8 +95,10 @@ func (c *claim) Try(alloc *Allocator) bool {
|
|||||||
if c.noErrorOnUnknown {
|
if c.noErrorOnUnknown {
|
||||||
alloc.infof("Claim %s for %s: %s; will try later.", c.cidr, c.ident, err)
|
alloc.infof("Claim %s for %s: %s; will try later.", c.cidr, c.ident, err)
|
||||||
c.sendResult(nil)
|
c.sendResult(nil)
|
||||||
} else { // just tell the user they can't do this.
|
} else if c.tryCount > maxTryCount {
|
||||||
c.deniedBy(alloc, owner)
|
// give up, tell the user they can't do this
|
||||||
|
c.deniedBy(alloc, owner, err)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -128,12 +135,16 @@ func (c *claim) Try(alloc *Allocator) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *claim) deniedBy(alloc *Allocator, owner mesh.PeerName) {
|
func (c *claim) deniedBy(alloc *Allocator, owner mesh.PeerName, err error) {
|
||||||
name, found := alloc.nicknames[owner]
|
name, found := alloc.nicknames[owner]
|
||||||
if found {
|
if found {
|
||||||
name = " (" + name + ")"
|
name = " (" + name + ")"
|
||||||
}
|
}
|
||||||
c.sendResult(fmt.Errorf("address %s is owned by other peer %s%s", c.cidr.String(), owner, name))
|
reason := ""
|
||||||
|
if err != nil {
|
||||||
|
reason = fmt.Sprintf(" - %s", err)
|
||||||
|
}
|
||||||
|
c.sendResult(fmt.Errorf("address %s is owned by other peer %s%s%s", c.cidr.String(), owner, name, reason))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *claim) Cancel() {
|
func (c *claim) Cancel() {
|
||||||
|
|||||||
+13
-12
@@ -1,15 +1,16 @@
|
|||||||
package ipam
|
package ipam
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/common/docker"
|
"github.com/rajch/weave/common/docker"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
func badRequest(w http.ResponseWriter, err error) {
|
func badRequest(w http.ResponseWriter, err error) {
|
||||||
@@ -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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
+6
-3
@@ -1,6 +1,7 @@
|
|||||||
package ipam
|
package ipam
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -11,9 +12,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/rajch/weave/common"
|
||||||
|
"github.com/rajch/weave/net/address"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/weaveworks/weave/common"
|
|
||||||
"github.com/weaveworks/weave/net/address"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func HTTPPost(t *testing.T, url string) string {
|
func HTTPPost(t *testing.T, url string) string {
|
||||||
@@ -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
|
||||||
|
|||||||
+7
-4
@@ -1,12 +1,13 @@
|
|||||||
package ring
|
package ring
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Entry represents entries around the ring
|
// Entry represents entries around the ring
|
||||||
@@ -25,6 +26,7 @@ func (e *entry) Equal(e2 *entry) bool {
|
|||||||
func (e *entry) update(peername mesh.PeerName, free address.Count) {
|
func (e *entry) update(peername mesh.PeerName, free address.Count) {
|
||||||
e.Peer = peername
|
e.Peer = peername
|
||||||
e.Version++
|
e.Version++
|
||||||
|
common.Log.Debugln(fmt.Sprintf("Updating ring token=%s current peer=%s updated peer=%s new version=%s", e.Token, e.Peer, peername, fmt.Sprint(e.Version)))
|
||||||
e.Free = free
|
e.Free = free
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,8 +74,9 @@ func (es entries) get(token address.Address) (*entry, bool) {
|
|||||||
// Is token between entries at i and j?
|
// Is token between entries at i and j?
|
||||||
// NB i and j can overflow and will wrap
|
// NB i and j can overflow and will wrap
|
||||||
// NBB this function does not work very well if there is only one
|
// NBB this function does not work very well if there is only one
|
||||||
// token on the ring; luckily an accurate answer is not needed
|
//
|
||||||
// by the call sites in this case.
|
// token on the ring; luckily an accurate answer is not needed
|
||||||
|
// by the call sites in this case.
|
||||||
func (es entries) between(token address.Address, i, j int) bool {
|
func (es entries) between(token address.Address, i, j int) bool {
|
||||||
common.Assert(i < j)
|
common.Assert(i < j)
|
||||||
|
|
||||||
|
|||||||
+65
-20
@@ -14,8 +14,8 @@ import (
|
|||||||
|
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OnUpdate func(prev, curr []address.Range, local bool)
|
type OnUpdate func(prev, curr []address.Range, local bool)
|
||||||
@@ -213,7 +213,7 @@ func (r *Ring) GrantRangeToHost(start, end address.Address, peer mesh.PeerName)
|
|||||||
|
|
||||||
// Merge the given ring into this ring and indicate whether this ring
|
// Merge the given ring into this ring and indicate whether this ring
|
||||||
// got updated as a result.
|
// got updated as a result.
|
||||||
func (r *Ring) Merge(gossip Ring) (bool, error) {
|
func (r *Ring) Merge(gossip Ring, hasAllocations func(r []address.Range) bool) (bool, error) {
|
||||||
r.assertInvariants()
|
r.assertInvariants()
|
||||||
defer r.trackUpdates()()
|
defer r.trackUpdates()()
|
||||||
|
|
||||||
@@ -238,12 +238,22 @@ func (r *Ring) Merge(gossip Ring) (bool, error) {
|
|||||||
return false, ErrDifferentRange
|
return false, ErrDifferentRange
|
||||||
}
|
}
|
||||||
|
|
||||||
result, updated, err := r.Entries.merge(gossip.Entries, r.Peer)
|
result, updated, err := r.Entries.merge(gossip.Entries, r.Peer, r, hasAllocations)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset the free space for entries if there is invalid free space
|
||||||
|
// due to accepting an unexpected update from the peers
|
||||||
|
for i := 0; i < len(result); i++ {
|
||||||
|
distance := r.distance(result.entry(i).Token, result.entry(i+1).Token)
|
||||||
|
if result.entry(i).Peer == r.Peer && result.entry(i).Free > distance {
|
||||||
|
// case that can arise when a range that we own that got split and had no allocations
|
||||||
|
result.entry(i).Free = distance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := r.checkEntries(result); err != nil {
|
if err := r.checkEntries(result); err != nil {
|
||||||
return false, fmt.Errorf("Merge of incoming data causes: %s", err)
|
return false, fmt.Errorf("Merge of incoming data causes: %s", err)
|
||||||
}
|
}
|
||||||
@@ -260,7 +270,7 @@ func (r *Ring) Merge(gossip Ring) (bool, error) {
|
|||||||
// entries belonging to ourPeer. Returns the merged entries and an
|
// entries belonging to ourPeer. Returns the merged entries and an
|
||||||
// indication whether the merge resulted in any changes, i.e. the
|
// indication whether the merge resulted in any changes, i.e. the
|
||||||
// result differs from the original.
|
// result differs from the original.
|
||||||
func (es entries) merge(other entries, ourPeer mesh.PeerName) (result entries, updated bool, err error) {
|
func (es entries) merge(other entries, ourPeer mesh.PeerName, r *Ring, hasAllocations func(r []address.Range) bool) (result entries, updated bool, err error) {
|
||||||
var mine, theirs *entry
|
var mine, theirs *entry
|
||||||
var previousOwner *mesh.PeerName
|
var previousOwner *mesh.PeerName
|
||||||
addToResult := func(e entry) { result = append(result, &e) }
|
addToResult := func(e entry) { result = append(result, &e) }
|
||||||
@@ -274,6 +284,7 @@ func (es entries) merge(other entries, ourPeer mesh.PeerName) (result entries, u
|
|||||||
var i, j int
|
var i, j int
|
||||||
for i < len(es) && j < len(other) {
|
for i < len(es) && j < len(other) {
|
||||||
mine, theirs = es[i], other[j]
|
mine, theirs = es[i], other[j]
|
||||||
|
common.Log.Debugf("[ring %s]: Merge mine.Token=%s theirs.Token=%s mine.Peer=%s theirs.Peer=%s mine.Version=%v theirs.Version=%v", ourPeer, mine.Token, theirs.Token, mine.Peer, theirs.Peer, mine.Version, theirs.Version)
|
||||||
switch {
|
switch {
|
||||||
case mine.Token < theirs.Token:
|
case mine.Token < theirs.Token:
|
||||||
addToResult(*mine)
|
addToResult(*mine)
|
||||||
@@ -282,8 +293,11 @@ func (es entries) merge(other entries, ourPeer mesh.PeerName) (result entries, u
|
|||||||
case mine.Token > theirs.Token:
|
case mine.Token > theirs.Token:
|
||||||
// insert, checking that a range owned by us hasn't been split
|
// insert, checking that a range owned by us hasn't been split
|
||||||
if previousOwner != nil && *previousOwner == ourPeer && theirs.Peer != ourPeer {
|
if previousOwner != nil && *previousOwner == ourPeer && theirs.Peer != ourPeer {
|
||||||
err = errEntryInMyRange(theirs)
|
// check we have no allocations in the range that got split
|
||||||
return
|
if hasAllocations(r.makeRanges(theirs.Token, mine.Token)) {
|
||||||
|
err = errEntryInMyRange(theirs)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
addTheirs(*theirs)
|
addTheirs(*theirs)
|
||||||
j++
|
j++
|
||||||
@@ -292,17 +306,44 @@ func (es entries) merge(other entries, ourPeer mesh.PeerName) (result entries, u
|
|||||||
switch {
|
switch {
|
||||||
case mine.Version >= theirs.Version:
|
case mine.Version >= theirs.Version:
|
||||||
if mine.Version == theirs.Version && !mine.Equal(theirs) {
|
if mine.Version == theirs.Version && !mine.Equal(theirs) {
|
||||||
err = errInconsistentEntry(mine, theirs)
|
if mine.Peer == ourPeer {
|
||||||
return
|
// if we own the entry and has allocations
|
||||||
|
if hasAllocations(r.makeRanges(theirs.Token, es.entry(i+1).Token)) {
|
||||||
|
err = errInconsistentEntry(mine, theirs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// tie-break here, pick the entry with the highest free count
|
||||||
|
if mine.Free >= theirs.Free {
|
||||||
|
addToResult(*mine)
|
||||||
|
previousOwner = &mine.Peer
|
||||||
|
} else {
|
||||||
|
addTheirs(*theirs)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addToResult(*mine)
|
||||||
|
previousOwner = &mine.Peer
|
||||||
}
|
}
|
||||||
addToResult(*mine)
|
|
||||||
previousOwner = &mine.Peer
|
|
||||||
case mine.Version < theirs.Version:
|
case mine.Version < theirs.Version:
|
||||||
if mine.Peer == ourPeer { // We shouldn't receive updates to our own tokens
|
if mine.Peer == ourPeer {
|
||||||
err = errNewerVersion(mine, theirs)
|
// We received update to our own tokens accept the received entry
|
||||||
return
|
// if either it belongs to a different peer and we do not have allocations
|
||||||
|
// in the range effectively given away, or it belongs to our own peer, in
|
||||||
|
// which case we should set our version to the one received plus one,
|
||||||
|
// effectively imposing our existing entry.
|
||||||
|
if theirs.Peer != ourPeer && !hasAllocations(r.makeRanges(mine.Token, es.entry(i+1).Token)) {
|
||||||
|
common.Log.Infof("ring: repair inconsistent data by accepting token %v from %v - no allocations up to %v", theirs.Token, theirs.Peer, es.entry(i+1).Token)
|
||||||
|
addTheirs(*theirs)
|
||||||
|
} else if theirs.Peer == ourPeer {
|
||||||
|
mine.Version = theirs.Version + 1
|
||||||
|
addToResult(*mine)
|
||||||
|
} else {
|
||||||
|
err = errNewerVersion(mine, theirs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addTheirs(*theirs)
|
||||||
}
|
}
|
||||||
addTheirs(*theirs)
|
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
j++
|
j++
|
||||||
@@ -334,6 +375,11 @@ func (r *Ring) Empty() bool {
|
|||||||
return len(r.Entries) == 0
|
return len(r.Entries) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convenience function to normalise a single range that may span zero
|
||||||
|
func (r *Ring) makeRanges(start, end address.Address) []address.Range {
|
||||||
|
return r.splitRangesOverZero([]address.Range{{Start: start, End: end}})
|
||||||
|
}
|
||||||
|
|
||||||
// Given a slice of ranges which are all in the right order except
|
// Given a slice of ranges which are all in the right order except
|
||||||
// possibly the last one spans zero, fix that up and return the slice
|
// possibly the last one spans zero, fix that up and return the slice
|
||||||
func (r *Ring) splitRangesOverZero(ranges []address.Range) []address.Range {
|
func (r *Ring) splitRangesOverZero(ranges []address.Range) []address.Range {
|
||||||
@@ -384,10 +430,7 @@ type RangeInfo struct {
|
|||||||
|
|
||||||
func (r *Ring) AllRangeInfo() (result []RangeInfo) {
|
func (r *Ring) AllRangeInfo() (result []RangeInfo) {
|
||||||
for i, entry := range r.Entries {
|
for i, entry := range r.Entries {
|
||||||
nextEntry := r.Entries.entry(i + 1)
|
for _, r := range r.makeRanges(entry.Token, r.Entries.entry(i+1).Token) {
|
||||||
ranges := []address.Range{{Start: entry.Token, End: nextEntry.Token}}
|
|
||||||
ranges = r.splitRangesOverZero(ranges)
|
|
||||||
for _, r := range ranges {
|
|
||||||
result = append(result, RangeInfo{entry.Peer, r, entry.Version})
|
result = append(result, RangeInfo{entry.Peer, r, entry.Version})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -485,6 +528,7 @@ func (r *Ring) ReportFree(freespace map[address.Address]address.Count) (updated
|
|||||||
|
|
||||||
entries[i].Free = free
|
entries[i].Free = free
|
||||||
entries[i].Version++
|
entries[i].Version++
|
||||||
|
common.Log.Debugf("[ring %s]: ReportFree token=%s peer=%s version=%v", r.Peer, entries[i].Token, entries[i].Peer, entries[i].Version)
|
||||||
updated = true
|
updated = true
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -516,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,6 +612,7 @@ func (r *Ring) Transfer(from, to mesh.PeerName) []address.Range {
|
|||||||
// bump version by large value so that transfer of range takes precedence (if there is any conflict in merging entry)
|
// bump version by large value so that transfer of range takes precedence (if there is any conflict in merging entry)
|
||||||
// over other opertaions on the entry that increments the version
|
// over other opertaions on the entry that increments the version
|
||||||
entry.Version = entry.Version + 100
|
entry.Version = entry.Version + 100
|
||||||
|
common.Log.Debugf("[ring %s]: Transfer token=%s from=%s to=%s version=%v", r.Peer, entry.Token, from, to, entry.Version)
|
||||||
newRanges = append(newRanges, address.Range{Start: entry.Token, End: r.Entries.entry(i + 1).Token})
|
newRanges = append(newRanges, address.Range{Start: entry.Token, End: r.Entries.entry(i + 1).Token})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+78
-10
@@ -10,8 +10,8 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -32,7 +32,27 @@ func ParseIP(s string) address.Address {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func merge(r1, r2 *Ring) error {
|
func merge(r1, r2 *Ring) error {
|
||||||
_, err := r1.Merge(*r2)
|
distance := func(start, end address.Address) address.Count {
|
||||||
|
if end > start {
|
||||||
|
return address.Count(end - start)
|
||||||
|
}
|
||||||
|
return address.Count((r1.End - start) + (end - r1.Start))
|
||||||
|
}
|
||||||
|
check := func(rs []address.Range) bool {
|
||||||
|
for _, r := range rs {
|
||||||
|
size := distance(r.Start, r.End)
|
||||||
|
entry, found := r1.Entries.get(r.Start)
|
||||||
|
if !found {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if entry.Free < size {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := r1.Merge(*r2, check)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,6 +239,61 @@ func TestMergeSimple(t *testing.T) {
|
|||||||
require.Equal(t, ring2.Entries, ring1.Entries)
|
require.Equal(t, ring2.Entries, ring1.Entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMergeWithConflicts(t *testing.T) {
|
||||||
|
|
||||||
|
// received update to entry with a token and version identical to an entry we have
|
||||||
|
// but but holding different content, if there are no allocations, resolve the
|
||||||
|
// conflict by picking entry one with high free count
|
||||||
|
ring1 := NewRing(start, end, peer1name)
|
||||||
|
ring2 := NewRing(start, end, peer2name)
|
||||||
|
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 256, Version: 1}}
|
||||||
|
ring2.Entries = []*entry{{Token: start, Peer: peer2name, Free: 256, Version: 1}}
|
||||||
|
require.NoError(t, merge(ring1, ring2))
|
||||||
|
|
||||||
|
// received update to entry with a token and version identical to an entry we have
|
||||||
|
// but but holding different content, if there are allocations, then reject the received
|
||||||
|
// entry
|
||||||
|
ring1 = NewRing(start, end, peer1name)
|
||||||
|
ring2 = NewRing(start, end, peer2name)
|
||||||
|
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 128, Version: 1}}
|
||||||
|
ring2.Entries = []*entry{{Token: start, Peer: peer2name, Free: 256, Version: 1}}
|
||||||
|
require.Error(t, merge(ring1, ring2), "Expected error")
|
||||||
|
|
||||||
|
// received an entry with update to one of our own tokens and with new version,
|
||||||
|
// accept the received entry if its still going to belong to us
|
||||||
|
ring1 = NewRing(start, end, peer1name)
|
||||||
|
ring2 = NewRing(start, end, peer2name)
|
||||||
|
ring1.Entries = []*entry{{Token: start, Peer: peer1name}}
|
||||||
|
ring2.Entries = []*entry{{Token: start, Peer: peer1name, Version: 1}}
|
||||||
|
require.NoError(t, merge(ring1, ring2))
|
||||||
|
|
||||||
|
// received an entry with update to one of our own tokens and with new version,
|
||||||
|
// but belongs to a different peer, accept the received entry if we do not
|
||||||
|
// have allocations in the range
|
||||||
|
ring1 = NewRing(start, end, peer1name)
|
||||||
|
ring2 = NewRing(start, end, peer2name)
|
||||||
|
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 256}}
|
||||||
|
ring2.Entries = []*entry{{Token: start, Peer: peer2name, Free: 256, Version: 1}}
|
||||||
|
require.NoError(t, merge(ring1, ring2))
|
||||||
|
|
||||||
|
// received an entry with update to one of our own tokens and with new version,
|
||||||
|
// reject received entry if we have allocations in the range
|
||||||
|
ring1 = NewRing(start, end, peer1name)
|
||||||
|
ring2 = NewRing(start, end, peer2name)
|
||||||
|
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 128}}
|
||||||
|
ring2.Entries = []*entry{{Token: start, Peer: peer2name, Version: 1}}
|
||||||
|
require.Error(t, merge(ring1, ring2), "Expected error")
|
||||||
|
|
||||||
|
// we receive an entry that splits one of our ranges, giving some of it
|
||||||
|
// away to another peer. accept the entry provided that we have no allocations
|
||||||
|
// in the range that got given away.
|
||||||
|
ring1 = NewRing(start, end, peer1name)
|
||||||
|
ring2 = NewRing(start, end, peer2name)
|
||||||
|
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 256, Version: 1}}
|
||||||
|
ring2.Entries = []*entry{{Token: start, Peer: peer1name, Free: 128, Version: 2}, {Token: middle, Peer: peer2name, Free: 128}}
|
||||||
|
require.NoError(t, merge(ring1, ring2))
|
||||||
|
}
|
||||||
|
|
||||||
func TestMergeErrors(t *testing.T) {
|
func TestMergeErrors(t *testing.T) {
|
||||||
// Cannot Merge in an invalid ring
|
// Cannot Merge in an invalid ring
|
||||||
ring1 := NewRing(start, end, peer1name)
|
ring1 := NewRing(start, end, peer1name)
|
||||||
@@ -231,13 +306,6 @@ func TestMergeErrors(t *testing.T) {
|
|||||||
ring2.Entries = []*entry{}
|
ring2.Entries = []*entry{}
|
||||||
require.True(t, merge(ring1, ring2) == ErrDifferentRange, "Expected ErrDifferentRange")
|
require.True(t, merge(ring1, ring2) == ErrDifferentRange, "Expected ErrDifferentRange")
|
||||||
|
|
||||||
// Cannot Merge newer version of entry I own
|
|
||||||
ring2 = NewRing(start, end, peer2name)
|
|
||||||
ring1.Entries = []*entry{{Token: start, Peer: peer1name}}
|
|
||||||
ring2.Entries = []*entry{{Token: start, Peer: peer1name, Version: 1}}
|
|
||||||
fmt.Println(merge(ring1, ring2))
|
|
||||||
require.Error(t, merge(ring1, ring2), "Expected error")
|
|
||||||
|
|
||||||
// Cannot Merge two entries with same version but different hosts
|
// Cannot Merge two entries with same version but different hosts
|
||||||
ring1.Entries = []*entry{{Token: start, Peer: peer1name}}
|
ring1.Entries = []*entry{{Token: start, Peer: peer1name}}
|
||||||
ring2.Entries = []*entry{{Token: start, Peer: peer2name}}
|
ring2.Entries = []*entry{{Token: start, Peer: peer2name}}
|
||||||
|
|||||||
+2
-2
@@ -5,8 +5,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Space struct {
|
type Space struct {
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package space
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rajch/weave/net/address"
|
||||||
|
wt "github.com/rajch/weave/testing"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/weaveworks/weave/net/address"
|
|
||||||
wt "github.com/weaveworks/weave/testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeSpace(start address.Address, size address.Offset) *Space {
|
func makeSpace(start address.Address, size address.Offset) *Space {
|
||||||
@@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -2,8 +2,9 @@ package ipam
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/weaveworks/weave/ipam/paxos"
|
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/ipam/paxos"
|
||||||
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Status struct {
|
type Status struct {
|
||||||
|
|||||||
+5
-27
@@ -9,9 +9,9 @@ import (
|
|||||||
|
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
|
|
||||||
|
"github.com/rajch/weave/net/address"
|
||||||
|
"github.com/rajch/weave/testing/gossip"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/weaveworks/weave/net/address"
|
|
||||||
"github.com/weaveworks/weave/testing/gossip"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockMessage struct {
|
type mockMessage struct {
|
||||||
@@ -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
|
||||||
@@ -65,6 +57,9 @@ func (m *mockGossipComms) GossipBroadcast(update mesh.GossipData) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *mockGossipComms) GossipNeighbourSubset(update mesh.GossipData) {
|
||||||
|
m.GossipBroadcast(update)
|
||||||
|
}
|
||||||
func equalByteBuffer(a, b []byte) bool {
|
func equalByteBuffer(a, b []byte) bool {
|
||||||
if len(a) != len(b) {
|
if len(a) != len(b) {
|
||||||
return false
|
return false
|
||||||
@@ -97,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()
|
||||||
@@ -205,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)
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ import (
|
|||||||
"github.com/aws/aws-sdk-go/service/ec2"
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AWSVPCTracker struct {
|
type AWSVPCTracker struct {
|
||||||
@@ -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,46 +0,0 @@
|
|||||||
package tracker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/weaveworks/weave/net/address"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Merge merges adjacent range entries.
|
|
||||||
// The given slice has to be sorted in increasing order.
|
|
||||||
func Merge(r []address.Range) []address.Range {
|
|
||||||
var merged []address.Range
|
|
||||||
|
|
||||||
for i := range r {
|
|
||||||
if prev := len(merged) - 1; prev >= 0 && merged[prev].End == r[i].Start {
|
|
||||||
merged[prev].End = r[i].End
|
|
||||||
} else {
|
|
||||||
merged = append(merged, r[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return merged
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveCommon filters out CIDR ranges which are contained in both a and b slices.
|
|
||||||
// Both slices have to be sorted in increasing order.
|
|
||||||
func RemoveCommon(a, b []address.CIDR) (newA, newB []address.CIDR) {
|
|
||||||
i, j := 0, 0
|
|
||||||
|
|
||||||
for i < len(a) && j < len(b) {
|
|
||||||
switch {
|
|
||||||
case a[i].Start() < b[j].Start() || a[i].End() < b[j].End():
|
|
||||||
newA = append(newA, a[i])
|
|
||||||
i++
|
|
||||||
case a[i].Start() > b[j].Start() || a[i].End() > b[j].End():
|
|
||||||
newB = append(newB, b[j])
|
|
||||||
j++
|
|
||||||
default:
|
|
||||||
i++
|
|
||||||
j++
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
newA = append(newA, a[i:]...)
|
|
||||||
newB = append(newB, b[j:]...)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -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]
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package tracker
|
package tracker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LocalRangeTracker is an interface for tracking changes in the IPAM ring.
|
// LocalRangeTracker is an interface for tracking changes in the IPAM ring.
|
||||||
|
|||||||
+7
-3
@@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -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),
|
||||||
@@ -269,7 +273,7 @@ func (h *handler) handleRecursive(w dns.ResponseWriter, req *dns.Msg) {
|
|||||||
reqCopy := req.Copy()
|
reqCopy := req.Copy()
|
||||||
reqCopy.Id = dns.Id()
|
reqCopy.Id = dns.Id()
|
||||||
response, _, err := h.client.Exchange(reqCopy, fmt.Sprintf("%s:%s", server, upstreamConfig.Port))
|
response, _, err := h.client.Exchange(reqCopy, fmt.Sprintf("%s:%s", server, upstreamConfig.Port))
|
||||||
if (err != nil && err != dns.ErrTruncated) || response == nil {
|
if (err != nil) || response == nil {
|
||||||
h.ns.debugf("error trying %s: %v", server, err)
|
h.ns.debugf("error trying %s: %v", server, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/rajch/weave/net/address"
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
"github.com/weaveworks/weave/net/address"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockUpstream struct {
|
type mockUpstream struct {
|
||||||
@@ -41,23 +41,20 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
doRequest := func(client *dns.Client, request *dns.Msg, port int, expectedErr error) *dns.Msg {
|
doRequest := func(client *dns.Client, request *dns.Msg, port int) *dns.Msg {
|
||||||
request.SetQuestion("foo.weave.local.", dns.TypeA)
|
request.SetQuestion("foo.weave.local.", dns.TypeA)
|
||||||
response, _, err := client.Exchange(request, fmt.Sprintf("127.0.0.1:%d", port))
|
response, _, _ := client.Exchange(request, fmt.Sprintf("127.0.0.1:%d", port))
|
||||||
require.Equal(t, expectedErr, err)
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
// do a udp query, ensure we get a truncated response
|
// do a udp query, ensure we get a truncated response
|
||||||
{
|
{
|
||||||
udpClient := dns.Client{Net: "udp", UDPSize: minUDPSize}
|
udpClient := dns.Client{Net: "udp", UDPSize: minUDPSize}
|
||||||
response := doRequest(&udpClient, &dns.Msg{}, udpPort, dns.ErrTruncated)
|
response := doRequest(&udpClient, &dns.Msg{}, udpPort)
|
||||||
require.True(t, response.MsgHdr.Truncated)
|
require.True(t, response.MsgHdr.Truncated)
|
||||||
require.True(t, len(response.Answer) < 100)
|
require.True(t, len(response.Answer) < 100)
|
||||||
}
|
}
|
||||||
@@ -67,7 +64,7 @@ func TestTruncation(t *testing.T) {
|
|||||||
udpClient := dns.Client{Net: "udp", UDPSize: 65535}
|
udpClient := dns.Client{Net: "udp", UDPSize: 65535}
|
||||||
request := &dns.Msg{}
|
request := &dns.Msg{}
|
||||||
request.SetEdns0(65535, false)
|
request.SetEdns0(65535, false)
|
||||||
response := doRequest(&udpClient, request, udpPort, nil)
|
response := doRequest(&udpClient, request, udpPort)
|
||||||
require.False(t, response.MsgHdr.Truncated)
|
require.False(t, response.MsgHdr.Truncated)
|
||||||
require.Equal(t, len(response.Answer), 100)
|
require.Equal(t, len(response.Answer), 100)
|
||||||
}
|
}
|
||||||
@@ -75,7 +72,7 @@ func TestTruncation(t *testing.T) {
|
|||||||
// do a tcp query, ensure we don't get a truncated response
|
// do a tcp query, ensure we don't get a truncated response
|
||||||
{
|
{
|
||||||
tcpClient := dns.Client{Net: "tcp"}
|
tcpClient := dns.Client{Net: "tcp"}
|
||||||
response := doRequest(&tcpClient, &dns.Msg{}, tcpPort, nil)
|
response := doRequest(&tcpClient, &dns.Msg{}, tcpPort)
|
||||||
require.False(t, response.MsgHdr.Truncated)
|
require.False(t, response.MsgHdr.Truncated)
|
||||||
require.Equal(t, len(response.Answer), 100)
|
require.Equal(t, len(response.Answer), 100)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
var now = func() int64 { return time.Now().Unix() }
|
var now = func() int64 { return time.Now().Unix() }
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
func l(es Entries) Entries {
|
func l(es Entries) Entries {
|
||||||
|
|||||||
+13
-2
@@ -3,13 +3,14 @@ package nameserver
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common/docker"
|
"github.com/rajch/weave/common/docker"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (n *Nameserver) badRequest(w http.ResponseWriter, err error) {
|
func (n *Nameserver) badRequest(w http.ResponseWriter, err error) {
|
||||||
@@ -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)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
"github.com/weaveworks/weave/testing/gossip"
|
"github.com/rajch/weave/testing/gossip"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeNameserver(name mesh.PeerName) *Nameserver {
|
func makeNameserver(name mesh.PeerName) *Nameserver {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Using 32-bit integer to represent IPv4 address
|
// Using 32-bit integer to represent IPv4 address
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package address
|
||||||
|
|
||||||
|
// Merge merges adjacent range entries.
|
||||||
|
// The given slice has to be sorted in increasing order.
|
||||||
|
func Merge(r []Range) []Range {
|
||||||
|
var merged []Range
|
||||||
|
|
||||||
|
for i := range r {
|
||||||
|
if prev := len(merged) - 1; prev >= 0 && merged[prev].End == r[i].Start {
|
||||||
|
merged[prev].End = r[i].End
|
||||||
|
} else {
|
||||||
|
merged = append(merged, r[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return merged
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveCommon filters out CIDR ranges which are contained in both a and b slices.
|
||||||
|
// Both slices have to be sorted in increasing order.
|
||||||
|
func RemoveCommon(a, b []CIDR) (newA, newB []CIDR) {
|
||||||
|
i, j := 0, 0
|
||||||
|
|
||||||
|
for i < len(a) && j < len(b) {
|
||||||
|
switch {
|
||||||
|
case a[i].Start() < b[j].Start() || a[i].End() < b[j].End():
|
||||||
|
newA = append(newA, a[i])
|
||||||
|
i++
|
||||||
|
case a[i].Start() > b[j].Start() || a[i].End() > b[j].End():
|
||||||
|
newB = append(newB, b[j])
|
||||||
|
j++
|
||||||
|
default:
|
||||||
|
i++
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
newA = append(newA, a[i:]...)
|
||||||
|
newB = append(newB, b[j:]...)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
+89
-50
@@ -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/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/common/odp"
|
"github.com/rajch/weave/common/chains"
|
||||||
"github.com/weaveworks/weave/ipam/tracker"
|
"github.com/rajch/weave/common/odp"
|
||||||
"github.com/weaveworks/weave/net/address"
|
"github.com/rajch/weave/net/address"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/rajch/weave/net/ipset"
|
||||||
"github.com/weaveworks/weave/npc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/* This code implements three possible configurations to connect
|
/* This code implements three possible configurations to connect
|
||||||
@@ -50,7 +48,7 @@ the "datapath" device, via "router/fastdp.go:fastDatapathBridge"
|
|||||||
|
|
||||||
"weave" is an Open vSwitch datapath, and capture/injection are as in
|
"weave" is an Open vSwitch datapath, and capture/injection are as in
|
||||||
BridgedFastdp. Not used by default due to missing conntrack support in
|
BridgedFastdp. Not used by default due to missing conntrack support in
|
||||||
datapath of old kernel versions (https://github.com/weaveworks/weave/issues/1577).
|
datapath of old kernel versions (https://github.com/rajch/weave/issues/1577).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -63,10 +61,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Bridge interface {
|
type Bridge interface {
|
||||||
init(config *BridgeConfig) error // create and initialise bridge device(s)
|
init(procPath string, config *BridgeConfig) error // create and initialise bridge device(s)
|
||||||
attach(veth *netlink.Veth) error // attach veth to bridge
|
attach(veth *netlink.Veth) error // attach veth to bridge
|
||||||
IsFastdp() bool // does this bridge use fastdp?
|
IsFastdp() bool // does this bridge use fastdp?
|
||||||
String() string // human-readable type string
|
String() string // human-readable type string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to indicate a fallback to the Bridge type
|
// Used to indicate a fallback to the Bridge type
|
||||||
@@ -221,6 +219,7 @@ type BridgeConfig struct {
|
|||||||
MTU int
|
MTU int
|
||||||
Mac string
|
Mac string
|
||||||
Port int
|
Port int
|
||||||
|
ControlPort string
|
||||||
NoMasqLocal bool
|
NoMasqLocal bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +249,7 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if err := bridgeType.init(config); err != nil {
|
if err := bridgeType.init(procPath, config); err != nil {
|
||||||
if errors.Cause(err) == errBridgeNotSupported {
|
if errors.Cause(err) == errBridgeNotSupported {
|
||||||
log.Warnf("Skipping bridge creation of %q due to: %s", bridgeType, err)
|
log.Warnf("Skipping bridge creation of %q due to: %s", bridgeType, err)
|
||||||
bridgeType = bridgeImpl{}
|
bridgeType = bridgeImpl{}
|
||||||
@@ -261,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")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,6 +278,10 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
|
|||||||
return bridgeType, errors.Wrap(err, "setting proxy_arp")
|
return bridgeType, errors.Wrap(err, "setting proxy_arp")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// No ipv6 router advertisments please
|
||||||
|
if err := sysctlIfExists(procPath, "net/ipv6/conf/"+config.WeaveBridgeName+"/accept_ra", "0"); err != nil {
|
||||||
|
return bridgeType, errors.Wrap(err, "setting accept_ra to 0")
|
||||||
|
}
|
||||||
|
|
||||||
if err := linkSetUpByName(config.WeaveBridgeName); err != nil {
|
if err := linkSetUpByName(config.WeaveBridgeName); err != nil {
|
||||||
return bridgeType, err
|
return bridgeType, err
|
||||||
@@ -292,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,11 +346,11 @@ func (b bridgeImpl) initPrep(config *BridgeConfig) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b bridgeImpl) init(config *BridgeConfig) error {
|
func (b bridgeImpl) init(procPath string, config *BridgeConfig) error {
|
||||||
if err := b.initPrep(config); err != nil {
|
if err := b.initPrep(config); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := CreateAndAttachVeth(BridgeIfName, PcapIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
|
if _, err := CreateAndAttachVeth(procPath, BridgeIfName, PcapIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
|
||||||
return netlink.LinkSetUp(veth)
|
return netlink.LinkSetUp(veth)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Wrap(err, "creating pcap veth pair")
|
return errors.Wrap(err, "creating pcap veth pair")
|
||||||
@@ -361,7 +362,7 @@ func (b bridgeImpl) init(config *BridgeConfig) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f fastdpImpl) init(config *BridgeConfig) error {
|
func (f fastdpImpl) init(procPath string, config *BridgeConfig) error {
|
||||||
odpSupported, err := odp.CreateDatapath(f.datapathName)
|
odpSupported, err := odp.CreateDatapath(f.datapathName)
|
||||||
if !odpSupported {
|
if !odpSupported {
|
||||||
msg := ""
|
msg := ""
|
||||||
@@ -392,14 +393,14 @@ func (f fastdpImpl) init(config *BridgeConfig) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bf bridgedFastdpImpl) init(config *BridgeConfig) error {
|
func (bf bridgedFastdpImpl) init(procPath string, config *BridgeConfig) error {
|
||||||
if err := bf.fastdpImpl.init(config); err != nil {
|
if err := bf.fastdpImpl.init(procPath, config); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := bf.bridgeImpl.initPrep(config); err != nil {
|
if err := bf.bridgeImpl.initPrep(config); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := CreateAndAttachVeth(BridgeIfName, DatapathIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
|
if _, err := CreateAndAttachVeth(procPath, BridgeIfName, DatapathIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
|
||||||
if err := netlink.LinkSetUp(veth); err != nil {
|
if err := netlink.LinkSetUp(veth); err != nil {
|
||||||
return errors.Wrapf(err, "setting link up on %q", veth.Attrs().Name)
|
return errors.Wrapf(err, "setting link up on %q", veth.Attrs().Name)
|
||||||
}
|
}
|
||||||
@@ -426,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!
|
||||||
@@ -465,15 +496,27 @@ func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.ControlPort != "" {
|
||||||
|
if err = ipt.AppendUnique("filter", "INPUT", "-p", "tcp", "--dst", "127.0.0.1", "--dport", config.ControlPort,
|
||||||
|
"-m", "addrtype", "!", "--src-type", "LOCAL",
|
||||||
|
"-m", "conntrack", "!", "--ctstate", "RELATED,ESTABLISHED",
|
||||||
|
"-m", "comment", "--comment", "Block non-local access to Weave Net control port",
|
||||||
|
"-j", "DROP"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove the rule from Weave Net 2.6.3 which dropped too much.
|
||||||
|
_ = ipt.Delete("filter", "INPUT", "-p", "tcp", "--dst", "127.0.0.1", "-m", "addrtype", "!", "--src-type", "LOCAL", "-m", "conntrack", "!", "--ctstate", "RELATED,ESTABLISHED", "-j", "DROP")
|
||||||
|
|
||||||
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,
|
||||||
@@ -482,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"},
|
||||||
}...)
|
}...)
|
||||||
@@ -498,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"})
|
||||||
@@ -515,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 {
|
||||||
@@ -547,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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,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 {
|
||||||
@@ -592,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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func ensureInterface(ifaceName string) (*net.Interface, error) {
|
|||||||
ch := make(chan netlink.LinkUpdate)
|
ch := make(chan netlink.LinkUpdate)
|
||||||
// NB: We do not supply (and eventually close) a 'done' channel
|
// NB: We do not supply (and eventually close) a 'done' channel
|
||||||
// here since that can cause incorrect file descriptor
|
// here since that can cause incorrect file descriptor
|
||||||
// re-usage. See https://github.com/weaveworks/weave/issues/2120
|
// re-usage. See https://github.com/rajch/weave/issues/2120
|
||||||
if err := netlink.LinkSubscribe(ch, nil); err != nil {
|
if err := netlink.LinkSubscribe(ch, nil); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-24
@@ -85,7 +85,7 @@ func New(log *logrus.Logger) (*IPSec, error) {
|
|||||||
|
|
||||||
// InitSALocal initializes inbound ipsec from remotePeer and triggers
|
// InitSALocal initializes inbound ipsec from remotePeer and triggers
|
||||||
// the initialization on remotePeer.
|
// the initialization on remotePeer.
|
||||||
func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uint64, localIP, remoteIP net.IP, udpPort int, sessionKey *[32]byte, initRemote func([]byte) error) error {
|
func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uint64, localIP, remoteIP net.IP, udpPort int, sessionKey *[32]byte) ([]byte, error) {
|
||||||
// ID of inbound SPI
|
// ID of inbound SPI
|
||||||
spiID := getSPIId(remotePeer, localPeer, connUID)
|
spiID := getSPIId(remotePeer, localPeer, connUID)
|
||||||
|
|
||||||
@@ -95,17 +95,17 @@ func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uin
|
|||||||
// Derive SA key
|
// Derive SA key
|
||||||
nonce, err := genNonce()
|
nonce, err := genNonce()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "generate nonce")
|
return nil, errors.Wrap(err, "generate nonce")
|
||||||
}
|
}
|
||||||
key, err := deriveKey(sessionKey[:], nonce, localPeer)
|
key, err := deriveKey(sessionKey[:], nonce, localPeer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "derive key")
|
return nil, errors.Wrap(err, "derive key")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate SA
|
// Allocate SA
|
||||||
sa, err := netlink.XfrmStateAllocSpi(xfrmAllocSpiState(remoteIP, localIP))
|
sa, err := netlink.XfrmStateAllocSpi(xfrmAllocSpiState(remoteIP, localIP))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("ip xfrm state allocspi (in, %s, %s)", remoteIP, localIP))
|
return nil, errors.Wrap(err, fmt.Sprintf("ip xfrm state allocspi (in, %s, %s)", remoteIP, localIP))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use SPI generated by the kernel. The kernel ensures {dstIP, spi} to
|
// Use SPI generated by the kernel. The kernel ensures {dstIP, spi} to
|
||||||
@@ -117,28 +117,24 @@ func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uin
|
|||||||
// Create SA
|
// Create SA
|
||||||
if sa, err := xfrmState(remoteIP, localIP, spi, false, key); err == nil {
|
if sa, err := xfrmState(remoteIP, localIP, spi, false, key); err == nil {
|
||||||
if err := netlink.XfrmStateUpdate(sa); err != nil {
|
if err := netlink.XfrmStateUpdate(sa); err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("xfrm state update (in, %s, %s, 0x%x)", sa.Src, sa.Dst, sa.Spi))
|
return nil, errors.Wrap(err, fmt.Sprintf("xfrm state update (in, %s, %s, 0x%x)", sa.Src, sa.Dst, sa.Spi))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return errors.Wrap(err, "new xfrm state (in)")
|
return nil, errors.Wrap(err, "new xfrm state (in)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install iptables rules
|
// Install iptables rules
|
||||||
if err := ipsec.installDropNonEncrypted(localIP, remoteIP, udpPort, spi); err != nil {
|
if err := ipsec.installDropNonEncrypted(localIP, remoteIP, udpPort, spi); err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("install protecting rules (%s, %s, %d, 0x%x)", localIP, remoteIP, udpPort, spi))
|
return nil, errors.Wrap(err, fmt.Sprintf("install protecting rules (%s, %s, %d, 0x%x)", localIP, remoteIP, udpPort, spi))
|
||||||
}
|
}
|
||||||
|
|
||||||
si := spiInfo{spi: spi, isDirOut: false}
|
si := spiInfo{spi: spi, isDirOut: false}
|
||||||
ipsec.spiInfo[spiID] = si
|
ipsec.spiInfo[spiID] = si
|
||||||
ipsec.spis[spi] = &si
|
ipsec.spis[spi] = &si
|
||||||
|
|
||||||
// Trigger the initialization on the remote peer
|
// Generate the message to trigger initialization on the remote peer
|
||||||
msg := &msgInitSARemote{nonce, spi}
|
msg := &msgInitSARemote{nonce, spi}
|
||||||
if err := initRemote(msg.serialize()); err != nil {
|
return msg.serialize(), nil
|
||||||
return errors.Wrap(err, "send InitSARemote")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitSARemote initializes outbound ipsec to remotePeer.
|
// InitSARemote initializes outbound ipsec to remotePeer.
|
||||||
@@ -223,9 +219,19 @@ func (ipsec *IPSec) Destroy(localPeer, remotePeer mesh.PeerName, connUID uint64,
|
|||||||
|
|
||||||
if outSPIInfo, ok := ipsec.spiInfo[outSPIID]; ok {
|
if outSPIInfo, ok := ipsec.spiInfo[outSPIID]; ok {
|
||||||
ipsec.log.Infof("ipsec: destroy: out %s -> %s 0x%x", localIP, remoteIP, outSPIInfo.spi)
|
ipsec.log.Infof("ipsec: destroy: out %s -> %s 0x%x", localIP, remoteIP, outSPIInfo.spi)
|
||||||
|
policy, err := netlink.XfrmPolicyGet(xfrmPolicy(localIP, remoteIP, outSPIInfo.spi))
|
||||||
if err := netlink.XfrmPolicyDel(xfrmPolicy(localIP, remoteIP, outSPIInfo.spi)); err != nil {
|
if err != nil {
|
||||||
ipsec.log.Warnf("ipsec: xfrm policy del (%s, %s, 0x%x) failed: %s", localIP, remoteIP, outSPIInfo.spi, err)
|
ipsec.log.Warnf("ipsec: xfrm policy get (%s, %s, 0x%x) failed: %s", localIP, remoteIP, outSPIInfo.spi, err)
|
||||||
|
} else {
|
||||||
|
if len(policy.Tmpls) == 1 {
|
||||||
|
if policy.Tmpls[0].Spi == int(outSPIInfo.spi) {
|
||||||
|
if err := netlink.XfrmPolicyDel(xfrmPolicy(localIP, remoteIP, outSPIInfo.spi)); err != nil {
|
||||||
|
ipsec.log.Warnf("ipsec: xfrm policy del (%s, %s, 0x%x) failed: %s", localIP, remoteIP, outSPIInfo.spi, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ipsec.log.Debugf("ipsec: xfrm not my policy (%s, %s, 0x%x) got 0x%x ", localIP, remoteIP, outSPIInfo.spi, policy.Tmpls[0].Spi)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outSA := &netlink.XfrmState{
|
outSA := &netlink.XfrmState{
|
||||||
@@ -424,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 {
|
||||||
|
|||||||
+47
-18
@@ -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
|
||||||
|
|
||||||
@@ -48,8 +53,8 @@ type ipset struct {
|
|||||||
// List of users per ipset entry. User is either a namespace or a pod.
|
// List of users per ipset entry. User is either a namespace or a pod.
|
||||||
// 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/rajch/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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -55,9 +55,9 @@ func WithNetNSByPath(path string, work func() error) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NSPathByPid(pid int) string {
|
func NSPathByPid(pid int) string {
|
||||||
return NSPathByPidWithRoot("/", pid)
|
return NSPathByPidWithProc("/proc", pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NSPathByPidWithRoot(root string, pid int) string {
|
func NSPathByPidWithProc(procPath string, pid int) string {
|
||||||
return filepath.Join(root, fmt.Sprintf("/proc/%d/ns/net", pid))
|
return filepath.Join(procPath, fmt.Sprint(pid), "/ns/net")
|
||||||
}
|
}
|
||||||
+1
-1
@@ -6,8 +6,8 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/rajch/weave/db"
|
||||||
"github.com/weaveworks/mesh"
|
"github.com/weaveworks/mesh"
|
||||||
"github.com/weaveworks/weave/db"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func getOldStyleSystemUUID() ([]byte, error) {
|
func getOldStyleSystemUUID() ([]byte, error) {
|
||||||
|
|||||||
+17
-8
@@ -13,7 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// create and attach a veth to the Weave bridge
|
// create and attach a veth to the Weave bridge
|
||||||
func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, keepTXOn bool, errIfLinkExist bool, init func(peer netlink.Link) error) (*netlink.Veth, error) {
|
func CreateAndAttachVeth(procPath, name, peerName, bridgeName string, mtu int, keepTXOn bool, errIfLinkExist bool, init func(peer netlink.Link) error) (*netlink.Veth, error) {
|
||||||
bridge, err := netlink.LinkByName(bridgeName)
|
bridge, err := netlink.LinkByName(bridgeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf(`bridge "%s" not present; did you launch weave?`, bridgeName)
|
return nil, fmt.Errorf(`bridge "%s" not present; did you launch weave?`, bridgeName)
|
||||||
@@ -49,6 +49,13 @@ func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, keepTXOn bo
|
|||||||
if err := bridgeType.attach(veth); err != nil {
|
if err := bridgeType.attach(veth); err != nil {
|
||||||
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
|
||||||
|
if err := sysctlIfExists(procPath, "net/ipv6/conf/"+name+"/accept_ra", "0"); err != nil {
|
||||||
|
return cleanup("setting accept_ra to 0: %s", err)
|
||||||
|
}
|
||||||
|
if err := sysctlIfExists(procPath, "net/ipv6/conf/"+peerName+"/accept_ra", "0"); err != nil {
|
||||||
|
return cleanup("setting accept_ra to 0: %s", err)
|
||||||
|
}
|
||||||
if !bridgeType.IsFastdp() && !keepTXOn {
|
if !bridgeType.IsFastdp() && !keepTXOn {
|
||||||
if err := EthtoolTXOff(veth.PeerName); err != nil {
|
if err := EthtoolTXOff(veth.PeerName); err != nil {
|
||||||
return cleanup(`unable to set tx off on %q: %s`, peerName, err)
|
return cleanup(`unable to set tx off on %q: %s`, peerName, err)
|
||||||
@@ -112,6 +119,9 @@ func interfaceExistsInNamespace(netNSPath string, ifName string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool, hairpinMode bool) error {
|
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool, hairpinMode bool) error {
|
||||||
|
// AttachContainer expects to be called in host pid namespace
|
||||||
|
const procPath = "/proc"
|
||||||
|
|
||||||
ns, err := netns.GetFromPath(netNSPath)
|
ns, err := netns.GetFromPath(netNSPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -124,12 +134,12 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
|
|||||||
id = id[:maxIDLen] // trim passed ID if too long
|
id = id[:maxIDLen] // trim passed ID if too long
|
||||||
}
|
}
|
||||||
name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id
|
name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id
|
||||||
veth, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, true, func(veth netlink.Link) error {
|
veth, err := CreateAndAttachVeth(procPath, name, peerName, bridgeName, mtu, keepTXOn, true, func(veth netlink.Link) error {
|
||||||
if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil {
|
if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil {
|
||||||
return fmt.Errorf("failed to move veth to container netns: %s", err)
|
return fmt.Errorf("failed to move veth to container netns: %s", err)
|
||||||
}
|
}
|
||||||
if err := WithNetNS(ns, func() error {
|
if err := WithNetNS(ns, func() error {
|
||||||
return setupIface(peerName, ifName)
|
return setupIface(procPath, peerName, ifName)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("error setting up interface: %s", err)
|
return fmt.Errorf("error setting up interface: %s", err)
|
||||||
}
|
}
|
||||||
@@ -206,7 +216,7 @@ func setupIfaceAddrs(veth netlink.Link, withMulticastRoute bool, cidrs []*net.IP
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setupIface expects to be called in the container's netns
|
// setupIface expects to be called in the container's netns
|
||||||
func setupIface(ifaceName, newIfName string) error {
|
func setupIface(procPath, ifaceName, newIfName string) error {
|
||||||
ipt, err := iptables.New()
|
ipt, err := iptables.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -219,15 +229,14 @@ func setupIface(ifaceName, newIfName string) error {
|
|||||||
if err := netlink.LinkSetName(link, newIfName); err != nil {
|
if err := netlink.LinkSetName(link, newIfName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// This is only called by AttachContainer which is only called in host pid namespace
|
if err := configureARPCache(procPath, newIfName); err != nil {
|
||||||
if err := configureARPCache("/proc", newIfName); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return ipt.Append("filter", "INPUT", "-i", newIfName, "-d", "224.0.0.0/4", "-j", "DROP")
|
return ipt.Append("filter", "INPUT", "-i", newIfName, "-d", "224.0.0.0/4", "-j", "DROP")
|
||||||
}
|
}
|
||||||
|
|
||||||
// configureARP is a helper for the Docker plugin which doesn't set the addresses itself
|
// configureARP is a helper for the Docker plugin which doesn't set the addresses itself
|
||||||
func ConfigureARP(prefix, rootPath string) error {
|
func ConfigureARP(prefix, procPath string) error {
|
||||||
links, err := netlink.LinkList()
|
links, err := netlink.LinkList()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -235,7 +244,7 @@ func ConfigureARP(prefix, rootPath string) error {
|
|||||||
for _, link := range links {
|
for _, link := range links {
|
||||||
ifName := link.Attrs().Name
|
ifName := link.Attrs().Name
|
||||||
if strings.HasPrefix(ifName, prefix) {
|
if strings.HasPrefix(ifName, prefix) {
|
||||||
configureARPCache(rootPath+"/proc", ifName)
|
configureARPCache(procPath, ifName)
|
||||||
if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil {
|
if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil {
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName)
|
arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName)
|
||||||
|
|||||||
+34
-20
@@ -7,17 +7,19 @@ import (
|
|||||||
networkingv1 "k8s.io/api/networking/v1"
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/rajch/weave/net/ipset"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
||||||
rules map[string]*ruleSpec,
|
rules map[string]*ruleSpec,
|
||||||
nsSelectors, podSelectors map[string]*selectorSpec,
|
nsSelectors, podSelectors, namespacedPodSelectors map[string]*selectorSpec,
|
||||||
ipBlocks map[string]*ipBlockSpec,
|
ipBlocks map[string]*ipBlockSpec,
|
||||||
err error) {
|
err error) {
|
||||||
|
|
||||||
nsSelectors = make(map[string]*selectorSpec)
|
nsSelectors = make(map[string]*selectorSpec)
|
||||||
podSelectors = make(map[string]*selectorSpec)
|
podSelectors = make(map[string]*selectorSpec)
|
||||||
|
namespacedPodSelectors = make(map[string]*selectorSpec)
|
||||||
|
|
||||||
ipBlocks = make(map[string]*ipBlockSpec)
|
ipBlocks = make(map[string]*ipBlockSpec)
|
||||||
rules = make(map[string]*ruleSpec)
|
rules = make(map[string]*ruleSpec)
|
||||||
policyTypes := make([]policyType, 0)
|
policyTypes := make([]policyType, 0)
|
||||||
@@ -31,9 +33,9 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If empty, matches all pods in a namespace
|
// If empty, matches all pods in a namespace
|
||||||
targetSelector, err := newSelectorSpec(&policy.Spec.PodSelector, policyTypes, ns.name, ipset.HashIP)
|
targetSelector, err := newSelectorSpec(&policy.Spec.PodSelector, nil, policyTypes, ns.name, ipset.HashIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// To prevent targetSelector being overwritten by a subsequent selector with
|
// To prevent targetSelector being overwritten by a subsequent selector with
|
||||||
@@ -52,7 +54,7 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
|||||||
|
|
||||||
if !allPorts {
|
if !allPorts {
|
||||||
if err = checkForNamedPorts(ingressRule.Ports); err != nil {
|
if err = checkForNamedPorts(ingressRule.Ports); err != nil {
|
||||||
return nil, nil, nil, nil, fmt.Errorf("named ports in network policies is not supported yet. "+
|
return nil, nil, nil, nil, nil, fmt.Errorf("named ports in network policies is not supported yet. "+
|
||||||
"Rejecting network policy: %s from further processing. "+err.Error(), policy.Name)
|
"Rejecting network policy: %s from further processing. "+err.Error(), policy.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,18 +74,24 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
|||||||
var srcRuleHost ruleHost
|
var srcRuleHost ruleHost
|
||||||
|
|
||||||
// NetworkPolicyPeer describes a peer to allow traffic from.
|
// NetworkPolicyPeer describes a peer to allow traffic from.
|
||||||
// Exactly one of its fields must be specified.
|
if peer.PodSelector != nil && peer.NamespaceSelector != nil {
|
||||||
if peer.PodSelector != nil {
|
srcSelector, err = newSelectorSpec(peer.PodSelector, peer.NamespaceSelector, nil, "", ipset.HashIP)
|
||||||
srcSelector, err = newSelectorSpec(peer.PodSelector, nil, ns.name, ipset.HashIP)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, err
|
||||||
|
}
|
||||||
|
addIfNotExist(srcSelector, namespacedPodSelectors)
|
||||||
|
srcRuleHost = srcSelector
|
||||||
|
} else if peer.PodSelector != nil {
|
||||||
|
srcSelector, err = newSelectorSpec(peer.PodSelector, nil, nil, ns.name, ipset.HashIP)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
addIfNotExist(srcSelector, podSelectors)
|
addIfNotExist(srcSelector, podSelectors)
|
||||||
srcRuleHost = srcSelector
|
srcRuleHost = srcSelector
|
||||||
} else if peer.NamespaceSelector != nil {
|
} else if peer.NamespaceSelector != nil {
|
||||||
srcSelector, err = newSelectorSpec(peer.NamespaceSelector, nil, "", ipset.ListSet)
|
srcSelector, err = newSelectorSpec(nil, peer.NamespaceSelector, nil, "", ipset.ListSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
nsSelectors[srcSelector.key] = srcSelector
|
nsSelectors[srcSelector.key] = srcSelector
|
||||||
srcRuleHost = srcSelector
|
srcRuleHost = srcSelector
|
||||||
@@ -98,7 +106,7 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
|||||||
rules[rule.key] = rule
|
rules[rule.key] = rule
|
||||||
} else {
|
} else {
|
||||||
withNormalisedProtoAndPort(ingressRule.Ports, func(proto, port string) {
|
withNormalisedProtoAndPort(ingressRule.Ports, func(proto, port string) {
|
||||||
rule := newRuleSpec(policyTypeIngress, &proto, srcSelector, targetSelector, &port)
|
rule := newRuleSpec(policyTypeIngress, &proto, srcRuleHost, targetSelector, &port)
|
||||||
rules[rule.key] = rule
|
rules[rule.key] = rule
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -117,7 +125,7 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
|||||||
|
|
||||||
if !allPorts {
|
if !allPorts {
|
||||||
if err = checkForNamedPorts(egressRule.Ports); err != nil {
|
if err = checkForNamedPorts(egressRule.Ports); err != nil {
|
||||||
return nil, nil, nil, nil, fmt.Errorf("named ports in network policies is not supported yet. "+
|
return nil, nil, nil, nil, nil, fmt.Errorf("named ports in network policies is not supported yet. "+
|
||||||
"Rejecting network policy: %s from further processing. "+err.Error(), policy.Name)
|
"Rejecting network policy: %s from further processing. "+err.Error(), policy.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,19 +145,25 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
|||||||
var dstRuleHost ruleHost
|
var dstRuleHost ruleHost
|
||||||
|
|
||||||
// NetworkPolicyPeer describes a peer to allow traffic to.
|
// NetworkPolicyPeer describes a peer to allow traffic to.
|
||||||
// Exactly one of its fields must be specified.
|
if peer.PodSelector != nil && peer.NamespaceSelector != nil {
|
||||||
if peer.PodSelector != nil {
|
dstSelector, err = newSelectorSpec(peer.PodSelector, peer.NamespaceSelector, nil, "", ipset.HashIP)
|
||||||
dstSelector, err = newSelectorSpec(peer.PodSelector, nil, ns.name, ipset.HashIP)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, err
|
||||||
|
}
|
||||||
|
addIfNotExist(dstSelector, namespacedPodSelectors)
|
||||||
|
dstRuleHost = dstSelector
|
||||||
|
} else if peer.PodSelector != nil {
|
||||||
|
dstSelector, err = newSelectorSpec(peer.PodSelector, nil, nil, ns.name, ipset.HashIP)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
addIfNotExist(dstSelector, podSelectors)
|
addIfNotExist(dstSelector, podSelectors)
|
||||||
dstRuleHost = dstSelector
|
dstRuleHost = dstSelector
|
||||||
|
|
||||||
} else if peer.NamespaceSelector != nil {
|
} else if peer.NamespaceSelector != nil {
|
||||||
dstSelector, err = newSelectorSpec(peer.NamespaceSelector, nil, "", ipset.ListSet)
|
dstSelector, err = newSelectorSpec(nil, peer.NamespaceSelector, nil, "", ipset.ListSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
nsSelectors[dstSelector.key] = dstSelector
|
nsSelectors[dstSelector.key] = dstSelector
|
||||||
dstRuleHost = dstSelector
|
dstRuleHost = dstSelector
|
||||||
@@ -173,7 +187,7 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rules, nsSelectors, podSelectors, ipBlocks, nil
|
return rules, nsSelectors, podSelectors, namespacedPodSelectors, ipBlocks, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addIfNotExist(s *selectorSpec, ss map[string]*selectorSpec) {
|
func addIfNotExist(s *selectorSpec, ss map[string]*selectorSpec) {
|
||||||
|
|||||||
+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-"
|
||||||
|
|
||||||
|
|||||||
+120
-47
@@ -1,30 +1,35 @@
|
|||||||
package npc
|
package npc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
coreapi "k8s.io/api/core/v1"
|
coreapi "k8s.io/api/core/v1"
|
||||||
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"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/rajch/weave/common/chains"
|
||||||
"github.com/weaveworks/weave/npc/iptables"
|
"github.com/rajch/weave/net/ipset"
|
||||||
|
"github.com/rajch/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 {
|
||||||
@@ -32,31 +37,34 @@ type controller struct {
|
|||||||
|
|
||||||
nodeName string // my node name
|
nodeName string // my node name
|
||||||
|
|
||||||
ipt iptables.Interface
|
ipt iptables.Interface
|
||||||
ips ipset.Interface
|
ips ipset.Interface
|
||||||
|
clientset kubernetes.Interface
|
||||||
nss map[string]*ns // ns name -> ns struct
|
nss map[string]*ns // ns name -> ns struct
|
||||||
nsSelectors *selectorSet // selector string -> nsSelector
|
nsSelectors *selectorSet // selector string -> nsSelector
|
||||||
|
namespacedPodSelectors *selectorSet
|
||||||
|
defaultEgressDrop bool // flag to track if base iptable rule to drop egress traffic is added or not
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(nodeName string, ipt iptables.Interface, ips ipset.Interface) NetworkPolicyController {
|
func New(nodeName string, ipt iptables.Interface, ips ipset.Interface, clientset kubernetes.Interface) NetworkPolicyController {
|
||||||
c := &controller{
|
c := &controller{
|
||||||
nodeName: nodeName,
|
nodeName: nodeName,
|
||||||
ipt: ipt,
|
ipt: ipt,
|
||||||
ips: ips,
|
ips: ips,
|
||||||
nss: make(map[string]*ns)}
|
clientset: clientset,
|
||||||
|
nss: make(map[string]*ns)}
|
||||||
|
|
||||||
doNothing := func(*selector, policyType) error { return nil }
|
doNothing := func(*selector, policyType) error { return nil }
|
||||||
c.nsSelectors = newSelectorSet(ips, c.onNewNsSelector, doNothing, doNothing)
|
c.nsSelectors = newSelectorSet(ips, c.onNewNsSelector, doNothing, doNothing)
|
||||||
|
c.namespacedPodSelectors = newSelectorSet(ips, c.onNewNamespacePodsSelector, doNothing, doNothing)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
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.matches(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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,10 +73,32 @@ func (npc *controller) onNewNsSelector(selector *selector) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (npc *controller) withNS(name string, f func(ns *ns) error) error {
|
func (npc *controller) onNewNamespacePodsSelector(selector *selector) error {
|
||||||
|
for _, ns := range npc.nss {
|
||||||
|
if ns.namespaceUID != "" && len(ns.pods) > 0 {
|
||||||
|
for _, pod := range ns.pods {
|
||||||
|
if hasIP(pod) {
|
||||||
|
if selector.matchesNamespacedPodSelector(pod.ObjectMeta.Labels, ns.namespaceLabels) {
|
||||||
|
if err := selector.addEntry(uid(pod), pod.Status.PodIP, podComment(pod)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
newNs, err := newNS(name, npc.nodeName, npc.ipt, npc.ips, npc.nsSelectors)
|
namespace, err := npc.clientset.CoreV1().Namespaces().Get(ctx, name, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
newNs, err := newNS(name, npc.nodeName, npc.ipt, npc.ips, npc.nsSelectors, npc.namespacedPodSelectors, namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -87,52 +117,70 @@ 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()
|
||||||
|
|
||||||
|
// lazily add default rule to drop egress traffic only when network policies are applied
|
||||||
|
if !npc.defaultEgressDrop {
|
||||||
|
egressNetworkPolicy, err := isEgressNetworkPolicy(obj)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if egressNetworkPolicy {
|
||||||
|
if err := npc.ipt.Append(TableFilter, chains.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 {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsName, err := nsName(obj)
|
nsName, err := nsName(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
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()
|
||||||
|
|
||||||
@@ -142,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()
|
||||||
|
|
||||||
@@ -157,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")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -202,3 +250,28 @@ func nsName(obj interface{}) (string, error) {
|
|||||||
|
|
||||||
return "", errInvalidNetworkPolicyObjType
|
return "", errInvalidNetworkPolicyObjType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isEgressNetworkPolicy(obj interface{}) (bool, error) {
|
||||||
|
if policy, ok := obj.(*networkingv1.NetworkPolicy); ok {
|
||||||
|
if len(policy.Spec.PolicyTypes) > 0 {
|
||||||
|
for _, policyType := range policy.Spec.PolicyTypes {
|
||||||
|
if policyType == networkingv1.PolicyTypeEgress {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if policy.Spec.Egress != nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
+206
-88
@@ -1,25 +1,27 @@
|
|||||||
package npc
|
package npc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/rajch/weave/common/chains"
|
||||||
|
"github.com/rajch/weave/net/ipset"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
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 {
|
||||||
@@ -34,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)
|
||||||
@@ -54,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)
|
||||||
@@ -71,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,11 +156,12 @@ func (ipt *mockIPTables) Insert(table, chain string, pos int, rulespec ...string
|
|||||||
|
|
||||||
func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
|
func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
|
||||||
// Test for race condition between namespace and networkpolicy events
|
// Test for race condition between namespace and networkpolicy events
|
||||||
// https://github.com/weaveworks/weave/issues/3059
|
// https://github.com/rajch/weave/issues/3059
|
||||||
|
|
||||||
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",
|
||||||
},
|
},
|
||||||
@@ -163,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",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,28 +207,32 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
|
|||||||
|
|
||||||
// Namespaces first
|
// Namespaces first
|
||||||
m := newMockIPSet()
|
m := newMockIPSet()
|
||||||
controller := New("foo", newMockIPTables(), &m)
|
client := fake.NewSimpleClientset()
|
||||||
|
ctx := context.Background()
|
||||||
|
controller := New("foo", newMockIPTables(), &m, client)
|
||||||
|
client.CoreV1().Namespaces().Create(ctx, sourceNamespace, metav1.CreateOptions{})
|
||||||
|
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)
|
||||||
|
|
||||||
// NetworkPolicy first
|
// NetworkPolicy first
|
||||||
m = newMockIPSet()
|
m = newMockIPSet()
|
||||||
controller = New("foo", newMockIPTables(), &m)
|
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)
|
||||||
}
|
}
|
||||||
@@ -235,14 +248,16 @@ func TestDefaultAllow(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
m := newMockIPSet()
|
m := newMockIPSet()
|
||||||
controller := New("bar", newMockIPTables(), &m)
|
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)
|
||||||
@@ -255,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{
|
||||||
@@ -269,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{
|
||||||
@@ -303,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)
|
||||||
@@ -363,14 +378,18 @@ func TestOutOfOrderPodEvents(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
m := newMockIPSet()
|
m := newMockIPSet()
|
||||||
controller := New("qux", newMockIPTables(), &m)
|
client := fake.NewSimpleClientset()
|
||||||
|
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",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
controller.AddNamespace(defaultNamespace)
|
client.CoreV1().Namespaces().Create(ctx, defaultNamespace, metav1.CreateOptions{})
|
||||||
|
controller.AddNamespace(ctx, defaultNamespace)
|
||||||
|
|
||||||
podFoo := &coreapi.Pod{
|
podFoo := &coreapi.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -379,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{
|
||||||
@@ -401,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{
|
||||||
@@ -413,31 +432,31 @@ 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/rajch/weave/issues/3222
|
||||||
func TestNewTargetSelector(t *testing.T) {
|
func TestNewTargetSelector(t *testing.T) {
|
||||||
const (
|
const (
|
||||||
ingressDefaultAllowIPSetName = "weave-;rGqyMIl1HN^cfDki~Z$3]6!N"
|
ingressDefaultAllowIPSetName = "weave-;rGqyMIl1HN^cfDki~Z$3]6!N"
|
||||||
@@ -445,14 +464,18 @@ func TestNewTargetSelector(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
m := newMockIPSet()
|
m := newMockIPSet()
|
||||||
controller := New("baz", newMockIPTables(), &m)
|
client := fake.NewSimpleClientset()
|
||||||
|
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",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
controller.AddNamespace(defaultNamespace)
|
client.CoreV1().Namespaces().Create(ctx, defaultNamespace, metav1.CreateOptions{})
|
||||||
|
controller.AddNamespace(ctx, defaultNamespace)
|
||||||
|
|
||||||
podFoo := &coreapi.Pod{
|
podFoo := &coreapi.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -461,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{
|
||||||
@@ -481,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{
|
||||||
@@ -502,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) {
|
||||||
@@ -521,7 +544,24 @@ func TestEgressPolicyWithIPBlock(t *testing.T) {
|
|||||||
|
|
||||||
m := newMockIPSet()
|
m := newMockIPSet()
|
||||||
ipt := newMockIPTables()
|
ipt := newMockIPTables()
|
||||||
controller := New("foo", ipt, &m)
|
client := fake.NewSimpleClientset()
|
||||||
|
controller := New("foo", ipt, &m, client)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
defaultNamespace := &coreapi.Namespace{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "default",
|
||||||
|
UID: "default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
nonDefaultNamespace := &coreapi.Namespace{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "non-default",
|
||||||
|
UID: "non-default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
client.CoreV1().Namespaces().Create(ctx, defaultNamespace, metav1.CreateOptions{})
|
||||||
|
client.CoreV1().Namespaces().Create(ctx, nonDefaultNamespace, metav1.CreateOptions{})
|
||||||
|
|
||||||
netpolFoo := &networkingv1.NetworkPolicy{
|
netpolFoo := &networkingv1.NetworkPolicy{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@@ -547,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")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -588,7 +628,85 @@ 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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test case for https://github.com/rajch/weave/issues/3653
|
||||||
|
func TestIngressPolicyWithIPBlockAndPortSpecified(t *testing.T) {
|
||||||
|
const (
|
||||||
|
barPodIP = "10.32.0.11"
|
||||||
|
runBarIPSetName = "weave-bZ~x=yBgzH)Ht()K*Uv3z{M]Y"
|
||||||
|
)
|
||||||
|
|
||||||
|
m := newMockIPSet()
|
||||||
|
ipt := newMockIPTables()
|
||||||
|
client := fake.NewSimpleClientset()
|
||||||
|
controller := New("any", ipt, &m, client)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
defaultNamespace := &coreapi.Namespace{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "default",
|
||||||
|
UID: "default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
client.CoreV1().Namespaces().Create(ctx, defaultNamespace, metav1.CreateOptions{})
|
||||||
|
|
||||||
|
podBar := &coreapi.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
UID: "bar",
|
||||||
|
Namespace: "default",
|
||||||
|
Name: "bar",
|
||||||
|
Labels: map[string]string{"run": "bar"}},
|
||||||
|
Status: coreapi.PodStatus{PodIP: barPodIP}}
|
||||||
|
controller.AddPod(ctx, podBar)
|
||||||
|
defer controller.DeletePod(ctx, podBar)
|
||||||
|
|
||||||
|
portProtocol := coreapi.ProtocolTCP
|
||||||
|
port := intstr.FromInt(80)
|
||||||
|
netpolicty := &networkingv1.NetworkPolicy{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
UID: "ipblock-bar",
|
||||||
|
Name: "allow-ipblock-to-bar",
|
||||||
|
Namespace: "default",
|
||||||
|
},
|
||||||
|
Spec: networkingv1.NetworkPolicySpec{
|
||||||
|
PolicyTypes: []networkingv1.PolicyType{
|
||||||
|
networkingv1.PolicyTypeIngress,
|
||||||
|
},
|
||||||
|
PodSelector: metav1.LabelSelector{MatchLabels: podBar.Labels},
|
||||||
|
Ingress: []networkingv1.NetworkPolicyIngressRule{
|
||||||
|
{
|
||||||
|
Ports: []networkingv1.NetworkPolicyPort{
|
||||||
|
{
|
||||||
|
Protocol: &portProtocol,
|
||||||
|
Port: &port,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
From: []networkingv1.NetworkPolicyPeer{
|
||||||
|
{
|
||||||
|
IPBlock: &networkingv1.IPBlock{
|
||||||
|
CIDR: "192.168.48.4/32",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := controller.AddNetworkPolicy(ctx, netpolicty)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer controller.DeleteNetworkPolicy(ctx, netpolicty)
|
||||||
|
|
||||||
|
require.Equal(t, 1, len(m.sets[runBarIPSetName].subSets))
|
||||||
|
require.True(t, m.entriesExist(runBarIPSetName, barPodIP))
|
||||||
|
|
||||||
|
require.Equal(t, 1, len(ipt.rules[chains.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")
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-8
@@ -6,10 +6,9 @@ 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/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/rajch/weave/net/ipset"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ipBlockSpec struct {
|
type ipBlockSpec struct {
|
||||||
@@ -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{}{}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-1
@@ -11,7 +11,7 @@ import (
|
|||||||
"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"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -22,6 +22,12 @@ var (
|
|||||||
},
|
},
|
||||||
[]string{"protocol", "dport"},
|
[]string{"protocol", "dport"},
|
||||||
)
|
)
|
||||||
|
PolicyEnforcementErrors = prometheus.NewCounter(
|
||||||
|
prometheus.CounterOpts{
|
||||||
|
Name: "weavenpc_policy_enforcement_errors",
|
||||||
|
Help: "Errors occured in enforcing the network policies.",
|
||||||
|
},
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
func gatherMetrics() {
|
func gatherMetrics() {
|
||||||
@@ -95,6 +101,9 @@ func Start(addr string) error {
|
|||||||
if err := prometheus.Register(blockedConnections); err != nil {
|
if err := prometheus.Register(blockedConnections); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := prometheus.Register(PolicyEnforcementErrors); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
http.Handle("/metrics", promhttp.Handler())
|
http.Handle("/metrics", promhttp.Handler())
|
||||||
|
|
||||||
|
|||||||
+134
-89
@@ -8,12 +8,12 @@ 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/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/rajch/weave/common/chains"
|
||||||
"github.com/weaveworks/weave/npc/iptables"
|
"github.com/rajch/weave/net/ipset"
|
||||||
|
"github.com/rajch/weave/npc/iptables"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errInvalidNetworkPolicyObjType = errors.New("invalid NetworkPolicy object type")
|
var errInvalidNetworkPolicyObjType = errors.New("invalid NetworkPolicy object type")
|
||||||
@@ -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
|
||||||
@@ -37,30 +38,34 @@ type ns struct {
|
|||||||
ingressDefaultAllowIPSet ipset.Name
|
ingressDefaultAllowIPSet ipset.Name
|
||||||
egressDefaultAllowIPSet ipset.Name
|
egressDefaultAllowIPSet ipset.Name
|
||||||
|
|
||||||
nsSelectors *selectorSet
|
nsSelectors *selectorSet // reference to global selectorSet that is shared across the `ns`. Used to represent all pods in the matching namespaces
|
||||||
podSelectors *selectorSet
|
podSelectors *selectorSet // used to represent the matching pods in namespace respresented by this `ns`
|
||||||
ipBlocks *ipBlockSet
|
namespacedPodsSelectors *selectorSet // reference to global selectorSet that is shared across the `ns`. Used to represent matching pods in matching namespace
|
||||||
rules *ruleSet
|
ipBlocks *ipBlockSet
|
||||||
|
rules *ruleSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNS(name, nodeName string, ipt iptables.Interface, ips ipset.Interface, nsSelectors *selectorSet) (*ns, error) {
|
func newNS(name, nodeName string, ipt iptables.Interface, ips ipset.Interface, nsSelectors *selectorSet, namespacedPodsSelectors *selectorSet, namespaceObj *coreapi.Namespace) (*ns, error) {
|
||||||
allPods, err := newSelectorSpec(&metav1.LabelSelector{}, nil, name, ipset.HashIP)
|
allPods, err := newSelectorSpec(&metav1.LabelSelector{}, nil, nil, name, ipset.HashIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ns := &ns{
|
ns := &ns{
|
||||||
ipt: ipt,
|
ipt: ipt,
|
||||||
ips: ips,
|
ips: ips,
|
||||||
name: name,
|
name: name,
|
||||||
nodeName: nodeName,
|
namespaceUID: nsuid(namespaceObj),
|
||||||
pods: make(map[types.UID]*coreapi.Pod),
|
namespaceLabels: namespaceObj.ObjectMeta.Labels,
|
||||||
policies: make(map[types.UID]interface{}),
|
nodeName: nodeName,
|
||||||
uid: uuid.NewUUID(),
|
pods: make(map[ipset.UID]*coreapi.Pod),
|
||||||
allPods: allPods,
|
policies: make(map[ipset.UID]interface{}),
|
||||||
nsSelectors: nsSelectors,
|
uid: ipset.UID(uuid.NewUUID()),
|
||||||
ipBlocks: newIPBlockSet(ips),
|
allPods: allPods,
|
||||||
rules: newRuleSet(ipt),
|
nsSelectors: nsSelectors,
|
||||||
|
namespacedPodsSelectors: namespacedPodsSelectors,
|
||||||
|
ipBlocks: newIPBlockSet(ips),
|
||||||
|
rules: newRuleSet(ipt),
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.podSelectors = newSelectorSet(ips, ns.onNewPodSelector, ns.onNewTargetPodSelector, ns.onDestroyTargetPodSelector)
|
ns.podSelectors = newSelectorSet(ips, ns.onNewPodSelector, ns.onNewTargetPodSelector, ns.onDestroyTargetPodSelector)
|
||||||
@@ -85,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 {
|
||||||
@@ -95,8 +100,8 @@ func (ns *ns) destroy() error {
|
|||||||
func (ns *ns) onNewPodSelector(selector *selector) error {
|
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.matches(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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,8 +116,8 @@ func (ns *ns) onNewTargetPodSelector(selector *selector, policyType policyType)
|
|||||||
if hasIP(pod) {
|
if hasIP(pod) {
|
||||||
// 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.matches(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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,7 +130,7 @@ func (ns *ns) onNewTargetPodSelector(selector *selector, policyType policyType)
|
|||||||
func (ns *ns) onDestroyTargetPodSelector(selector *selector, policyType policyType) error {
|
func (ns *ns) onDestroyTargetPodSelector(selector *selector, policyType policyType) error {
|
||||||
for _, pod := range ns.pods {
|
for _, pod := range ns.pods {
|
||||||
if hasIP(pod) {
|
if hasIP(pod) {
|
||||||
if selector.matches(pod.ObjectMeta.Labels) {
|
if selector.matchesPodSelector(pod.ObjectMeta.Labels) {
|
||||||
if err := ns.addToDefaultAllowIfNoMatching(pod, policyType); err != nil {
|
if err := ns.addToDefaultAllowIfNoMatching(pod, policyType); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -141,88 +146,93 @@ func (ns *ns) addToDefaultAllowIfNoMatching(pod *coreapi.Pod, policyType policyT
|
|||||||
found := false
|
found := false
|
||||||
// TODO(mp) optimize (avoid iterating over selectors) by ref counting IP addrs.
|
// TODO(mp) optimize (avoid iterating over selectors) by ref counting IP addrs.
|
||||||
for _, s := range ns.podSelectors.entries {
|
for _, s := range ns.podSelectors.entries {
|
||||||
if ns.podSelectors.targetSelectorExist(s, policyType) && s.matches(pod.ObjectMeta.Labels) {
|
if ns.podSelectors.targetSelectorExist(s, policyType) && s.matchesPodSelector(pod.ObjectMeta.Labels) {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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.addToMatching(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(uid(obj), obj.ObjectMeta.Labels, ns.namespaceLabels, obj.Status.PodIP, podComment(obj))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
}
|
||||||
|
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(uid(oldObj), oldObj.ObjectMeta.Labels, ns.namespaceLabels, oldObj.Status.PodIP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ns.podSelectors.delFromMatching(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.addToMatching(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(uid(newObj), newObj.ObjectMeta.Labels, ns.namespaceLabels, newObj.Status.PodIP, podComment(newObj))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -240,18 +250,18 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
|
|||||||
oldObj.Status.PodIP != newObj.Status.PodIP {
|
oldObj.Status.PodIP != newObj.Status.PodIP {
|
||||||
|
|
||||||
for _, ps := range ns.podSelectors.entries {
|
for _, ps := range ns.podSelectors.entries {
|
||||||
oldMatch := ps.matches(oldObj.ObjectMeta.Labels)
|
oldMatch := ps.matchesPodSelector(oldObj.ObjectMeta.Labels)
|
||||||
newMatch := ps.matches(newObj.ObjectMeta.Labels)
|
newMatch := ps.matchesPodSelector(newObj.ObjectMeta.Labels)
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,6 +273,23 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, ps := range ns.namespacedPodsSelectors.entries {
|
||||||
|
oldMatch := ps.matchesNamespacedPodSelector(oldObj.ObjectMeta.Labels, ns.namespaceLabels)
|
||||||
|
newMatch := ps.matchesNamespacedPodSelector(newObj.ObjectMeta.Labels, ns.namespaceLabels)
|
||||||
|
if oldMatch == newMatch && oldObj.Status.PodIP == newObj.Status.PodIP {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if oldMatch {
|
||||||
|
if err := ps.delEntry(uid(oldObj), oldObj.Status.PodIP); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if newMatch {
|
||||||
|
if err := ps.addEntry(uid(newObj), newObj.Status.PodIP, podComment(newObj)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -273,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:
|
||||||
@@ -286,26 +313,31 @@ 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(uid(obj), obj.ObjectMeta.Labels, obj.Status.PodIP); err != nil {
|
||||||
return ns.podSelectors.delFromMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP)
|
return err
|
||||||
|
}
|
||||||
|
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(uid(obj), obj.ObjectMeta.Labels, ns.namespaceLabels, obj.Status.PodIP); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ns *ns) addNetworkPolicy(obj interface{}) error {
|
func (ns *ns) addNetworkPolicy(obj interface{}) error {
|
||||||
// Analyse policy, determine which rules and ipsets are required
|
// Analyse policy, determine which rules and ipsets are required
|
||||||
|
|
||||||
uid, rules, nsSelectors, podSelectors, ipBlocks, err := ns.analyse(obj)
|
uid, rules, nsSelectors, podSelectors, namespacedPodsSelectors, ipBlocks, err := ns.analyse(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -317,6 +349,9 @@ func (ns *ns) addNetworkPolicy(obj interface{}) error {
|
|||||||
if err := ns.podSelectors.provision(uid, nil, podSelectors); err != nil {
|
if err := ns.podSelectors.provision(uid, nil, podSelectors); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := ns.namespacedPodsSelectors.provision(uid, nil, namespacedPodsSelectors); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := ns.ipBlocks.provision(uid, nil, ipBlocks); err != nil {
|
if err := ns.ipBlocks.provision(uid, nil, ipBlocks); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -325,11 +360,11 @@ func (ns *ns) addNetworkPolicy(obj interface{}) error {
|
|||||||
|
|
||||||
func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
|
func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
|
||||||
// Analyse the old and the new policy so we can determine differences
|
// Analyse the old and the new policy so we can determine differences
|
||||||
oldUID, oldRules, oldNsSelectors, oldPodSelectors, oldIPBlocks, err := ns.analyse(oldObj)
|
oldUID, oldRules, oldNsSelectors, oldPodSelectors, oldNamespacedPodsSelectors, oldIPBlocks, err := ns.analyse(oldObj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
newUID, newRules, newNsSelectors, newPodSelectors, newIPBlocks, err := ns.analyse(newObj)
|
newUID, newRules, newNsSelectors, newPodSelectors, newNamespacedPodsSelectors, newIPBlocks, err := ns.analyse(newObj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -347,6 +382,9 @@ func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
|
|||||||
if err := ns.podSelectors.deprovision(oldUID, oldPodSelectors, newPodSelectors); err != nil {
|
if err := ns.podSelectors.deprovision(oldUID, oldPodSelectors, newPodSelectors); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := ns.namespacedPodsSelectors.deprovision(oldUID, oldNamespacedPodsSelectors, newNamespacedPodsSelectors); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := ns.ipBlocks.deprovision(oldUID, oldIPBlocks, newIPBlocks); err != nil {
|
if err := ns.ipBlocks.deprovision(oldUID, oldIPBlocks, newIPBlocks); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -356,6 +394,9 @@ func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
|
|||||||
if err := ns.podSelectors.provision(oldUID, oldPodSelectors, newPodSelectors); err != nil {
|
if err := ns.podSelectors.provision(oldUID, oldPodSelectors, newPodSelectors); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := ns.namespacedPodsSelectors.provision(oldUID, oldNamespacedPodsSelectors, newNamespacedPodsSelectors); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := ns.ipBlocks.provision(oldUID, oldIPBlocks, newIPBlocks); err != nil {
|
if err := ns.ipBlocks.provision(oldUID, oldIPBlocks, newIPBlocks); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -364,7 +405,7 @@ func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
|
|||||||
|
|
||||||
func (ns *ns) deleteNetworkPolicy(obj interface{}) error {
|
func (ns *ns) deleteNetworkPolicy(obj interface{}) error {
|
||||||
// Analyse network policy to free resources
|
// Analyse network policy to free resources
|
||||||
uid, rules, nsSelectors, podSelectors, ipBlocks, err := ns.analyse(obj)
|
uid, rules, nsSelectors, podSelectors, namespacedPodsSelectors, ipBlocks, err := ns.analyse(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -381,6 +422,9 @@ func (ns *ns) deleteNetworkPolicy(obj interface{}) error {
|
|||||||
if err := ns.podSelectors.deprovision(uid, podSelectors, nil); err != nil {
|
if err := ns.podSelectors.deprovision(uid, podSelectors, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := ns.namespacedPodsSelectors.deprovision(uid, namespacedPodsSelectors, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := ns.ipBlocks.deprovision(uid, ipBlocks, nil); err != nil {
|
if err := ns.ipBlocks.deprovision(uid, ipBlocks, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -392,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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -406,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},
|
||||||
@@ -446,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 {
|
||||||
@@ -454,28 +499,28 @@ 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.addToMatching(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.matches(oldObj.ObjectMeta.Labels)
|
oldMatch := selector.matchesNamespaceSelector(oldObj.ObjectMeta.Labels)
|
||||||
newMatch := selector.matches(newObj.ObjectMeta.Labels)
|
newMatch := selector.matchesNamespaceSelector(newObj.ObjectMeta.Labels)
|
||||||
if oldMatch == newMatch {
|
if oldMatch == newMatch {
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -486,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 {
|
||||||
@@ -494,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.delFromMatching(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
|
||||||
}
|
}
|
||||||
@@ -544,17 +589,17 @@ 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 map[string]*selectorSpec,
|
nsSelectors, podSelectors, namespacedPodsSelectors map[string]*selectorSpec,
|
||||||
ipBlocks map[string]*ipBlockSpec,
|
ipBlocks map[string]*ipBlockSpec,
|
||||||
err error) {
|
err error) {
|
||||||
|
|
||||||
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
|
||||||
@@ -562,7 +607,7 @@ func (ns *ns) analyse(obj interface{}) (
|
|||||||
ns.policies[uid] = obj
|
ns.policies[uid] = obj
|
||||||
|
|
||||||
// Analyse policy, determine which rules and ipsets are required
|
// Analyse policy, determine which rules and ipsets are required
|
||||||
rules, nsSelectors, podSelectors, ipBlocks, err = ns.analysePolicy(obj.(*networkingv1.NetworkPolicy))
|
rules, nsSelectors, podSelectors, namespacedPodsSelectors, ipBlocks, err = ns.analysePolicy(obj.(*networkingv1.NetworkPolicy))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-12
@@ -5,10 +5,10 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"github.com/rajch/weave/common"
|
||||||
|
"github.com/rajch/weave/common/chains"
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/net/ipset"
|
||||||
"github.com/weaveworks/weave/npc/iptables"
|
"github.com/rajch/weave/npc/iptables"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ruleHost interface {
|
type ruleHost interface {
|
||||||
@@ -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{}{}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -1,13 +1,14 @@
|
|||||||
package npc
|
package npc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRegressionHandleNil3095(t *testing.T) {
|
func TestRegressionHandleNil3095(t *testing.T) {
|
||||||
// Test for handling nil values
|
// Test for handling nil values
|
||||||
// https://github.com/weaveworks/weave/issues/3095
|
// https://github.com/rajch/weave/issues/3095
|
||||||
|
|
||||||
rs := newRuleSpec(policyTypeIngress, nil, nil, nil, nil)
|
rs := newRuleSpec(policyTypeIngress, nil, nil, nil, nil)
|
||||||
|
|
||||||
|
|||||||
+95
-30
@@ -5,32 +5,45 @@ 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/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/rajch/weave/net/ipset"
|
||||||
)
|
)
|
||||||
|
|
||||||
type selectorSpec struct {
|
type selectorSpec struct {
|
||||||
key string // string representation (for hash keying/equality comparison)
|
key string // string representation (for hash keying/equality comparison)
|
||||||
selector labels.Selector // k8s Selector object (for matching)
|
podSelector labels.Selector // k8s Selector object (for matching pods)
|
||||||
policyTypes []policyType // If non-empty, then selectorSpec is a target selector for given policyTypes.
|
namespaceSelector labels.Selector // k8s Selector object (for matching namespaces)
|
||||||
|
policyTypes []policyType // If non-empty, then selectorSpec is a target selector for given policyTypes.
|
||||||
|
|
||||||
ipsetType ipset.Type // type of ipset to provision
|
ipsetType ipset.Type // type of ipset to provision
|
||||||
ipsetName ipset.Name // generated ipset name
|
ipsetName ipset.Name // generated ipset name
|
||||||
nsName string // Namespace name
|
nsName string // Namespace name
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSelectorSpec(json *metav1.LabelSelector, policyType []policyType, nsName string, ipsetType ipset.Type) (*selectorSpec, error) {
|
func newSelectorSpec(podJSON *metav1.LabelSelector, namespaceJSON *metav1.LabelSelector, policyType []policyType, nsName string, ipsetType ipset.Type) (*selectorSpec, error) {
|
||||||
selector, err := metav1.LabelSelectorAsSelector(json)
|
var podSelector, namespaceSelector labels.Selector
|
||||||
if err != nil {
|
var err error
|
||||||
return nil, err
|
var key string
|
||||||
|
if namespaceJSON != nil {
|
||||||
|
namespaceSelector, err = metav1.LabelSelectorAsSelector(namespaceJSON)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
key = namespaceSelector.String()
|
||||||
|
}
|
||||||
|
if podJSON != nil {
|
||||||
|
podSelector, err = metav1.LabelSelectorAsSelector(podJSON)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
key = key + podSelector.String()
|
||||||
}
|
}
|
||||||
key := selector.String()
|
|
||||||
return &selectorSpec{
|
return &selectorSpec{
|
||||||
key: key,
|
key: key,
|
||||||
selector: selector,
|
podSelector: podSelector,
|
||||||
policyTypes: policyType,
|
namespaceSelector: namespaceSelector,
|
||||||
|
policyTypes: policyType,
|
||||||
// We prefix the selector string with the namespace name when generating
|
// We prefix the selector string with the namespace name when generating
|
||||||
// the shortname because you can specify the same selector in multiple
|
// the shortname because you can specify the same selector in multiple
|
||||||
// namespaces - we need those to map to distinct ipsets
|
// namespaces - we need those to map to distinct ipsets
|
||||||
@@ -46,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 {
|
||||||
@@ -61,15 +74,23 @@ type selector struct {
|
|||||||
spec *selectorSpec
|
spec *selectorSpec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *selector) matches(labelMap map[string]string) bool {
|
func (s *selector) matchesPodSelector(podsLabelMap map[string]string) bool {
|
||||||
return s.spec.selector.Matches(labels.Set(labelMap))
|
return s.spec.podSelector.Matches(labels.Set(podsLabelMap))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *selector) addEntry(user types.UID, entry string, comment string) error {
|
func (s *selector) matchesNamespaceSelector(namespaceLabelMap map[string]string) bool {
|
||||||
|
return s.spec.namespaceSelector.Matches(labels.Set(namespaceLabelMap))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *selector) matchesNamespacedPodSelector(podsLabelMap, namespaceLabelMap map[string]string) bool {
|
||||||
|
return s.spec.podSelector.Matches(labels.Set(podsLabelMap)) && s.spec.namespaceSelector.Matches(labels.Set(namespaceLabelMap))
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,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
|
||||||
@@ -100,16 +121,16 @@ 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) addToMatching(user types.UID, labelMap 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 {
|
||||||
if s.matches(labelMap) {
|
if s.matchesPodSelector(podLabelsMap) {
|
||||||
if ss.targetSelectorExist(s, policyTypeIngress) {
|
if ss.targetSelectorExist(s, policyTypeIngress) {
|
||||||
foundIngress = true
|
foundIngress = true
|
||||||
}
|
}
|
||||||
@@ -124,9 +145,53 @@ func (ss *selectorSet) addToMatching(user types.UID, labelMap map[string]string,
|
|||||||
return foundIngress, foundEgress, nil
|
return foundIngress, foundEgress, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *selectorSet) delFromMatching(user types.UID, labelMap map[string]string, entry 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.matches(labelMap) {
|
if s.matchesNamespaceSelector(namespaceLabelsMap) {
|
||||||
|
if err := s.addEntry(user, entry, comment); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
if s.matchesNamespacedPodSelector(podLabelsMap, namespaceLabelsMap) {
|
||||||
|
if err := s.addEntry(user, entry, comment); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss *selectorSet) delFromMatchingPodSelector(user ipset.UID, podLabelsMap map[string]string, entry string) error {
|
||||||
|
for _, s := range ss.entries {
|
||||||
|
if s.matchesPodSelector(podLabelsMap) {
|
||||||
|
if err := s.delEntry(user, entry); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss *selectorSet) delFromMatchingNamespaceSelector(user ipset.UID, namespaceLabelsMap map[string]string, entry string) error {
|
||||||
|
for _, s := range ss.entries {
|
||||||
|
if s.matchesNamespaceSelector(namespaceLabelsMap) {
|
||||||
|
if err := s.delEntry(user, entry); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss *selectorSet) delFromMatchingNamespacedPodSelector(user ipset.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string) error {
|
||||||
|
for _, s := range ss.entries {
|
||||||
|
if s.matchesNamespacedPodSelector(podLabelsMap, namespaceLabelsMap) {
|
||||||
if err := s.delEntry(user, entry); err != nil {
|
if err := s.delEntry(user, entry); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -139,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)
|
||||||
@@ -167,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}
|
||||||
@@ -180,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{}{}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func waitForExit(cmd *exec.Cmd) {
|
func waitForExit(cmd *exec.Cmd) {
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# Weave Net - Weaving Containers into Applications
|
||||||
|
|
||||||
|
[](https://circleci.com/gh/weaveworks/weave)
|
||||||
|
[](https://coveralls.io/r/weaveworks/weave)
|
||||||
|
[](https://goreportcard.com/report/github.com/weaveworks/weave)
|
||||||
|
[](https://hub.docker.com/r/weaveworks/weave/)
|
||||||
|
|
||||||
|
# About Weaveworks
|
||||||
|
|
||||||
|
[Weaveworks](https://www.weave.works) is the company that delivers the most productive way for developers to connect, observe and control Docker containers.
|
||||||
|
|
||||||
|
This repository contains [Weave Net](https://www.weave.works/products/weave-net/), the first product developed by Weaveworks, with over 8 million downloads to date. Weave Net enables you to get started with Docker clusters and portable apps in a fraction of the time required by other solutions.
|
||||||
|
|
||||||
|
# Weave Net
|
||||||
|
|
||||||
|
Weave Net creates a virtual network that connects Docker containers across multiple hosts and enables their automatic discovery. With Weave Net, portable microservices-based applications consisting of multiple containers can run anywhere: on one host, multiple hosts or even across cloud providers and data centers. Applications use the network just as if the containers were all plugged into the same network switch, without having to configure port mappings, ambassadors or links.
|
||||||
|
|
||||||
|
Services provided by application containers on the Weave network can be exposed to the outside world, regardless of where they are running. Similarly, existing internal systems can be opened to accept connections from application containers irrespective of their location.
|
||||||
|
|
||||||
|
## <a name="help"></a>Getting help
|
||||||
|
|
||||||
|
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).
|
||||||
|
- Invite yourself to the <a href="https://slack.weave.works/" target="_blank">Weave Users Slack</a>.
|
||||||
|
- 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.
|
||||||
|
- [File an issue](https://github.com/weaveworks/weave/issues/new).
|
||||||
|
|
||||||
|
We follow the [CNCF Code of Conduct](code-of-conduct.md).
|
||||||
|
|
||||||
|
Your feedback is always welcome!
|
||||||
|
|
||||||
|
## Further Information
|
||||||
|
|
||||||
|
* [Installing Weave Net](https://www.weave.works/docs/net/latest/install/installing-weave)
|
||||||
|
* [Weave Net Product Overview](https://www.weave.works/products/weave-net)
|
||||||
+10
-2
@@ -2,12 +2,13 @@ package ipamplugin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
"github.com/containernetworking/cni/pkg/skel"
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
current "github.com/containernetworking/cni/pkg/types/100"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (i *Ipam) CmdAdd(args *skel.CmdArgs) error {
|
func (i *Ipam) CmdAdd(args *skel.CmdArgs) error {
|
||||||
@@ -22,6 +23,13 @@ func (i *Ipam) CmdAdd(args *skel.CmdArgs) error {
|
|||||||
return types.PrintResult(result, conf.CNIVersion)
|
return types.PrintResult(result, conf.CNIVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Ipam) CmdCheck(args *skel.CmdArgs) error {
|
||||||
|
// TODO: Figure out how to do a proper CNI check here
|
||||||
|
// For now, return not implemented error
|
||||||
|
|
||||||
|
return errors.New("CNI plugin check not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
func (i *Ipam) Allocate(args *skel.CmdArgs) (types.Result, error) {
|
func (i *Ipam) Allocate(args *skel.CmdArgs) (types.Result, error) {
|
||||||
// extract the things we care about
|
// extract the things we care about
|
||||||
conf, err := loadIPAMConf(args.StdinData)
|
conf, err := loadIPAMConf(args.StdinData)
|
||||||
@@ -52,8 +60,8 @@ func (i *Ipam) Allocate(args *skel.CmdArgs) (types.Result, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
result := ¤t.Result{
|
result := ¤t.Result{
|
||||||
|
CNIVersion: current.ImplementedSpecVersion,
|
||||||
IPs: []*current.IPConfig{{
|
IPs: []*current.IPConfig{{
|
||||||
Version: "4",
|
|
||||||
Address: *ipnet,
|
Address: *ipnet,
|
||||||
Gateway: conf.Gateway,
|
Gateway: conf.Gateway,
|
||||||
}},
|
}},
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
|
|
||||||
"github.com/docker/libnetwork/discoverapi"
|
"github.com/docker/libnetwork/discoverapi"
|
||||||
"github.com/docker/libnetwork/netlabel"
|
"github.com/docker/libnetwork/netlabel"
|
||||||
"github.com/weaveworks/weave/api"
|
"github.com/rajch/weave/api"
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Ipam struct {
|
type Ipam struct {
|
||||||
|
|||||||
+16
-6
@@ -3,20 +3,21 @@ package plugin
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/ipam"
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
"github.com/containernetworking/cni/pkg/skel"
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
"github.com/containernetworking/cni/pkg/types/current"
|
current "github.com/containernetworking/cni/pkg/types/100"
|
||||||
|
"github.com/containernetworking/plugins/pkg/ipam"
|
||||||
|
weaveapi "github.com/rajch/weave/api"
|
||||||
|
weavenet "github.com/rajch/weave/net"
|
||||||
|
ipamplugin "github.com/rajch/weave/plugin/ipam"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
"github.com/vishvananda/netns"
|
"github.com/vishvananda/netns"
|
||||||
weaveapi "github.com/weaveworks/weave/api"
|
|
||||||
weavenet "github.com/weaveworks/weave/net"
|
|
||||||
ipamplugin "github.com/weaveworks/weave/plugin/ipam"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -176,8 +177,17 @@ func setupRoutes(link netlink.Link, name string, ipnet net.IPNet, gw net.IP, rou
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CNIPlugin) CmdCheck(args *skel.CmdArgs) error {
|
||||||
|
// TODO: Figure out how to do a proper CNI check here
|
||||||
|
// For now, return not implemented error
|
||||||
|
|
||||||
|
return errors.New("CNI plugin check not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
// As of CNI 0.5 spec:
|
// As of CNI 0.5 spec:
|
||||||
// "Plugins should generally complete a DEL action without error even if some resources are missing"
|
//
|
||||||
|
// "Plugins should generally complete a DEL action without error even if some resources are missing"
|
||||||
|
//
|
||||||
// this method should therefore return nil in most, if not all, cases.
|
// this method should therefore return nil in most, if not all, cases.
|
||||||
func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
|
func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
|
||||||
conf, err := loadNetConf(args.StdinData)
|
conf, err := loadNetConf(args.StdinData)
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ import (
|
|||||||
"github.com/docker/libnetwork/types"
|
"github.com/docker/libnetwork/types"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
weaveapi "github.com/rajch/weave/api"
|
||||||
|
"github.com/rajch/weave/common"
|
||||||
|
"github.com/rajch/weave/common/docker"
|
||||||
|
weavenet "github.com/rajch/weave/net"
|
||||||
|
"github.com/rajch/weave/plugin/skel"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
weaveapi "github.com/weaveworks/weave/api"
|
|
||||||
"github.com/weaveworks/weave/common"
|
|
||||||
"github.com/weaveworks/weave/common/docker"
|
|
||||||
weavenet "github.com/weaveworks/weave/net"
|
|
||||||
"github.com/weaveworks/weave/plugin/skel"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -39,9 +39,10 @@ type driver struct {
|
|||||||
// used only by plugin-v2
|
// used only by plugin-v2
|
||||||
forceMulticast bool
|
forceMulticast bool
|
||||||
networks map[string]network
|
networks map[string]network
|
||||||
|
procPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns, isPluginV2, forceMulticast bool) (skel.Driver, error) {
|
func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns, isPluginV2, forceMulticast bool, procPath string) (skel.Driver, error) {
|
||||||
driver := &driver{
|
driver := &driver{
|
||||||
name: name,
|
name: name,
|
||||||
scope: scope,
|
scope: scope,
|
||||||
@@ -51,6 +52,7 @@ func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns,
|
|||||||
// make sure that it's used only by plugin-v2
|
// make sure that it's used only by plugin-v2
|
||||||
forceMulticast: isPluginV2 && forceMulticast,
|
forceMulticast: isPluginV2 && forceMulticast,
|
||||||
networks: make(map[string]network),
|
networks: make(map[string]network),
|
||||||
|
procPath: procPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not start watcher in the case of plugin v2, which prevents us from
|
// Do not start watcher in the case of plugin v2, which prevents us from
|
||||||
@@ -134,7 +136,7 @@ func (driver *driver) CreateEndpoint(create *api.CreateEndpointRequest) (*api.Cr
|
|||||||
|
|
||||||
// create veths. note we assume endpoint IDs are unique in the first 9 chars
|
// create veths. note we assume endpoint IDs are unique in the first 9 chars
|
||||||
name, peerName := vethPair(create.EndpointID)
|
name, peerName := vethPair(create.EndpointID)
|
||||||
if _, err := weavenet.CreateAndAttachVeth(name, peerName, weavenet.WeaveBridgeName, 0, false, true, nil); err != nil {
|
if _, err := weavenet.CreateAndAttachVeth(driver.procPath, name, peerName, weavenet.WeaveBridgeName, 0, false, true, nil); err != nil {
|
||||||
return nil, driver.error("JoinEndpoint", "%s", err)
|
return nil, driver.error("JoinEndpoint", "%s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-12
@@ -3,9 +3,9 @@ package plugin
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
weaveapi "github.com/weaveworks/weave/api"
|
weaveapi "github.com/rajch/weave/api"
|
||||||
"github.com/weaveworks/weave/common/docker"
|
"github.com/rajch/weave/common/docker"
|
||||||
weavenet "github.com/weaveworks/weave/net"
|
weavenet "github.com/rajch/weave/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type watcher struct {
|
type watcher struct {
|
||||||
@@ -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,18 +45,27 @@ 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rootDir := "/"
|
netNSPath := weavenet.NSPathByPidWithProc(w.driver.procPath, info.State.Pid)
|
||||||
if w.driver.isPluginV2 {
|
|
||||||
// We bind mount host's /proc to /host/proc for plugin-v2
|
|
||||||
rootDir = "/host"
|
|
||||||
}
|
|
||||||
netNSPath := weavenet.NSPathByPidWithRoot(rootDir, info.State.Pid)
|
|
||||||
if err := weavenet.WithNetNSByPath(netNSPath, func() error {
|
if err := weavenet.WithNetNSByPath(netNSPath, func() error {
|
||||||
return weavenet.ConfigureARP(weavenet.VethName, rootDir)
|
return weavenet.ConfigureARP(weavenet.VethName, w.driver.procPath)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
w.driver.warn("ContainerStarted", "unable to configure interfaces: %s", err)
|
w.driver.warn("ContainerStarted", "unable to configure interfaces: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-11
@@ -7,13 +7,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/libnetwork/ipamapi"
|
"github.com/docker/libnetwork/ipamapi"
|
||||||
weaveapi "github.com/weaveworks/weave/api"
|
weaveapi "github.com/rajch/weave/api"
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/common/docker"
|
"github.com/rajch/weave/common/docker"
|
||||||
weavenet "github.com/weaveworks/weave/net"
|
weavenet "github.com/rajch/weave/net"
|
||||||
ipamplugin "github.com/weaveworks/weave/plugin/ipam"
|
ipamplugin "github.com/rajch/weave/plugin/ipam"
|
||||||
netplugin "github.com/weaveworks/weave/plugin/net"
|
netplugin "github.com/rajch/weave/plugin/net"
|
||||||
"github.com/weaveworks/weave/plugin/skel"
|
"github.com/rajch/weave/plugin/skel"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -32,6 +32,7 @@ type Config struct {
|
|||||||
EnableV2Multicast bool
|
EnableV2Multicast bool
|
||||||
DNS bool
|
DNS bool
|
||||||
DefaultSubnet string
|
DefaultSubnet string
|
||||||
|
ProcPath string // path to reach host /proc filesystem
|
||||||
}
|
}
|
||||||
|
|
||||||
type Plugin struct {
|
type Plugin struct {
|
||||||
@@ -62,7 +63,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
|
|||||||
endChan := make(chan error, 1)
|
endChan := make(chan error, 1)
|
||||||
|
|
||||||
if plugin.Socket != "" {
|
if plugin.Socket != "" {
|
||||||
globalListener, err := listenAndServe(dockerClient, weave, plugin.Socket, endChan, "global", false, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast)
|
globalListener, err := listenAndServe(dockerClient, weave, plugin.Socket, endChan, "global", false, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast, plugin.ProcPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -70,7 +71,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
|
|||||||
defer globalListener.Close()
|
defer globalListener.Close()
|
||||||
}
|
}
|
||||||
if plugin.MeshSocket != "" {
|
if plugin.MeshSocket != "" {
|
||||||
meshListener, err := listenAndServe(dockerClient, weave, plugin.MeshSocket, endChan, "local", true, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast)
|
meshListener, err := listenAndServe(dockerClient, weave, plugin.MeshSocket, endChan, "local", true, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast, plugin.ProcPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -87,7 +88,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
|
|||||||
return <-endChan
|
return <-endChan
|
||||||
}
|
}
|
||||||
|
|
||||||
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, dns bool, isPluginV2, forceMulticast bool) (net.Listener, error) {
|
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, dns bool, isPluginV2, forceMulticast bool, procPath string) (net.Listener, error) {
|
||||||
var name string
|
var name string
|
||||||
if isPluginV2 {
|
if isPluginV2 {
|
||||||
name = pluginV2Name
|
name = pluginV2Name
|
||||||
@@ -95,7 +96,7 @@ func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address
|
|||||||
name = pluginNameFromAddress(address)
|
name = pluginNameFromAddress(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2, forceMulticast)
|
d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2, forceMulticast, procPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
"k8s.io/client-go/testing"
|
"k8s.io/client-go/testing"
|
||||||
|
|
||||||
weavetracker "github.com/weaveworks/weave/testing/kubernetes/testing"
|
weavetracker "github.com/rajch/weave/testing/kubernetes/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var scheme = runtime.NewScheme()
|
var scheme = runtime.NewScheme()
|
||||||
|
|||||||
+99
-28
@@ -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"
|
||||||
@@ -15,14 +16,16 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/vishvananda/netlink"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
api "k8s.io/apimachinery/pkg/apis/meta/v1"
|
api "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
|
||||||
weaveapi "github.com/weaveworks/weave/api"
|
weaveapi "github.com/rajch/weave/api"
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
type nodeInfo struct {
|
type nodeInfo struct {
|
||||||
@@ -32,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
|
||||||
}
|
}
|
||||||
@@ -54,6 +58,10 @@ func getKubePeers(c kubernetes.Interface, includeWithNoIPAddr bool) ([]nodeInfo,
|
|||||||
|
|
||||||
// Fallback for cases where a Node has an ExternalIP but no InternalIP
|
// Fallback for cases where a Node has an ExternalIP but no InternalIP
|
||||||
if internalIP != "" {
|
if internalIP != "" {
|
||||||
|
// exclude self from the list of peers this node will peer with
|
||||||
|
if isLocalNodeIP(internalIP) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
addresses = append(addresses, nodeInfo{name: peer.Name, addr: internalIP})
|
addresses = append(addresses, nodeInfo{name: peer.Name, addr: internalIP})
|
||||||
} else if externalIP != "" {
|
} else if externalIP != "" {
|
||||||
addresses = append(addresses, nodeInfo{name: peer.Name, addr: externalIP})
|
addresses = append(addresses, nodeInfo{name: peer.Name, addr: externalIP})
|
||||||
@@ -64,6 +72,20 @@ func getKubePeers(c kubernetes.Interface, includeWithNoIPAddr bool) ([]nodeInfo,
|
|||||||
return addresses, nil
|
return addresses, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns true if given IP matches with one of the local IP's
|
||||||
|
func isLocalNodeIP(ip string) bool {
|
||||||
|
addrs, err := netlink.AddrList(nil, unix.AF_INET)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if addr.Peer != nil && addr.Peer.IP.String() == ip {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// (minimal, incomplete) interface so weaver can be mocked for testing.
|
// (minimal, incomplete) interface so weaver can be mocked for testing.
|
||||||
type weaveClient interface {
|
type weaveClient interface {
|
||||||
RmPeer(peerName string) (string, error)
|
RmPeer(peerName string) (string, error)
|
||||||
@@ -74,11 +96,8 @@ type weaveClient interface {
|
|||||||
func reclaimRemovedPeers(kube kubernetes.Interface, cml *configMapAnnotations, myPeerName, myNodeName string) error {
|
func reclaimRemovedPeers(kube kubernetes.Interface, cml *configMapAnnotations, myPeerName, myNodeName string) error {
|
||||||
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), common.Log)
|
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), common.Log)
|
||||||
for loopsWhenNothingChanged := 0; loopsWhenNothingChanged < 3; loopsWhenNothingChanged++ {
|
for loopsWhenNothingChanged := 0; loopsWhenNothingChanged < 3; loopsWhenNothingChanged++ {
|
||||||
if err := cml.Init(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// 1. Compare peers stored in the peerList against all peers reported by k8s now.
|
// 1. Compare peers stored in the peerList against all peers reported by k8s now.
|
||||||
storedPeerList, err := cml.GetPeerList()
|
storedPeerList, err := getRefreshedPeerList(cml)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -92,7 +111,9 @@ func reclaimRemovedPeers(kube kubernetes.Interface, cml *configMapAnnotations, m
|
|||||||
}
|
}
|
||||||
peerMap := make(map[string]peerInfo, len(storedPeerList.Peers))
|
peerMap := make(map[string]peerInfo, len(storedPeerList.Peers))
|
||||||
for _, peer := range storedPeerList.Peers {
|
for _, peer := range storedPeerList.Peers {
|
||||||
peerMap[peer.PeerName] = peer
|
if peer.PeerName != myPeerName {
|
||||||
|
peerMap[peer.PeerName] = peer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// remove entries from the peer map that are current nodes
|
// remove entries from the peer map that are current nodes
|
||||||
for key, peer := range peerMap {
|
for key, peer := range peerMap {
|
||||||
@@ -136,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
|
||||||
@@ -168,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)
|
||||||
@@ -178,14 +200,19 @@ func reclaimPeer(weave weaveClient, cml *configMapAnnotations, peerName string,
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
// 6. If step 4 or 5 succeeded, rmpeer X
|
// 6. If step 4 or 5 succeeded, rmpeer X
|
||||||
result, err := weave.RmPeer(peerName)
|
// we will try once more to see if the peerName has been removed from the annotation
|
||||||
common.Log.Infof("[kube-peers] rmpeer of %s: %s", peerName, result)
|
// by another weave pod
|
||||||
if err != nil {
|
storedPeerList, err := getRefreshedPeerList(cml)
|
||||||
return false, err
|
if storedPeerList.contains(peerName) {
|
||||||
|
result, err := weave.RmPeer(peerName)
|
||||||
|
common.Log.Infof("[kube-peers] rmpeer of %s: %s", peerName, result)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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
|
||||||
@@ -193,12 +220,16 @@ func reclaimPeer(weave weaveClient, cml *configMapAnnotations, peerName string,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
storedPeerList.remove(peerName)
|
if storedPeerList.contains(peerName) {
|
||||||
if err := cml.UpdatePeerList(*storedPeerList); err != nil {
|
storedPeerList.remove(peerName)
|
||||||
return err
|
if err := cml.UpdatePeerList(ctx, *storedPeerList); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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
|
||||||
|
|
||||||
@@ -239,6 +270,13 @@ func registerForNodeUpdates(client *kubernetes.Clientset, stopCh <-chan struct{}
|
|||||||
common.Log.Debugln("registering for updates for node delete events")
|
common.Log.Debugln("registering for updates for node delete events")
|
||||||
nodeInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
nodeInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||||
DeleteFunc: func(obj interface{}) {
|
DeleteFunc: func(obj interface{}) {
|
||||||
|
var name string
|
||||||
|
if apiObj, ok := obj.(api.Object); ok {
|
||||||
|
name = apiObj.GetName()
|
||||||
|
} else {
|
||||||
|
name = fmt.Sprintf("%#v", obj)
|
||||||
|
}
|
||||||
|
common.Log.Debugln("Delete event for", name)
|
||||||
// add random delay to avoid all nodes acting on node delete event at the same
|
// add random delay to avoid all nodes acting on node delete event at the same
|
||||||
// time leading to contention to use `weave-net` configmap
|
// time leading to contention to use `weave-net` configmap
|
||||||
r := rand.Intn(5000)
|
r := rand.Intn(5000)
|
||||||
@@ -259,11 +297,25 @@ func registerForNodeUpdates(client *kubernetes.Clientset, stopCh <-chan struct{}
|
|||||||
informerFactory.Start(stopCh)
|
informerFactory.Start(stopCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getRefreshedPeerList will fetch the latest peer list from the config map annotation
|
||||||
|
func getRefreshedPeerList(cml *configMapAnnotations) (*peerList, error) {
|
||||||
|
if err := cml.Init(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
storedPeerList, err := cml.GetPeerList()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return storedPeerList, nil
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var (
|
var (
|
||||||
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
|
||||||
@@ -273,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)")
|
||||||
@@ -321,6 +375,33 @@ 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 {
|
||||||
|
// Handle SIGINT and SIGTERM
|
||||||
|
ch := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
stopCh := make(chan struct{})
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
registerForNodeUpdates(c, stopCh, nodeName, peerName)
|
||||||
|
<-ch
|
||||||
|
close(stopCh)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
peers, err := getKubePeers(c, false)
|
peers, err := getKubePeers(c, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.Log.Fatalf("[kube-peers] Could not get peers: %v", err)
|
common.Log.Fatalf("[kube-peers] Could not get peers: %v", err)
|
||||||
@@ -328,14 +409,4 @@ func main() {
|
|||||||
for _, node := range peers {
|
for _, node := range peers {
|
||||||
fmt.Println(node.addr)
|
fmt.Println(node.addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if runReclaimDaemon {
|
|
||||||
// Handle SIGINT and SIGTERM
|
|
||||||
ch := make(chan os.Signal)
|
|
||||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
|
||||||
stopCh := make(chan struct{})
|
|
||||||
registerForNodeUpdates(c, stopCh, nodeName, peerName)
|
|
||||||
<-ch
|
|
||||||
close(stopCh)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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,12 +4,13 @@ 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"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -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,10 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -15,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) {
|
||||||
@@ -45,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)
|
||||||
@@ -71,6 +71,7 @@ func doConcurrentIterations(iterations, concurrency int, f func(int)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPeerListFuzz(t *testing.T) {
|
func TestPeerListFuzz(t *testing.T) {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
const (
|
const (
|
||||||
testIters = 1000
|
testIters = 1000
|
||||||
maxNodes = 100
|
maxNodes = 100
|
||||||
|
|||||||
@@ -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
|
||||||
+39
-54
@@ -1,35 +1,47 @@
|
|||||||
#!/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"
|
||||||
}
|
|
||||||
|
|
||||||
# Check whether xt_set actually exists
|
# Setup iptables backend to be legacy or nftable
|
||||||
xt_set_exists() {
|
setup_iptables_backend() {
|
||||||
# Clean everything up in advance, in case there's leftovers
|
if [ -n "${IPTABLES_BACKEND}" ]; then
|
||||||
iptables -F WEAVE-KUBE-TEST 2>/dev/null || true
|
mode=$IPTABLES_BACKEND
|
||||||
iptables -X WEAVE-KUBE-TEST 2>/dev/null || true
|
else
|
||||||
ipset destroy weave-kube-test 2>/dev/null || true
|
# auto-detect if iptables backend mode to use if not specified explicitly
|
||||||
|
num_legacy_lines=$( (iptables-legacy-save || true) 2>/dev/null | grep '^-' | wc -l)
|
||||||
ipset create weave-kube-test hash:ip
|
num_nft_lines=$( (iptables-nft-save || true) 2>/dev/null | grep '^-' | wc -l)
|
||||||
iptables -t filter -N WEAVE-KUBE-TEST
|
if [ "${num_legacy_lines}" -ge 10 ]; then
|
||||||
if ! iptables -A WEAVE-KUBE-TEST -m set --match-set weave-kube-test src -j DROP; then
|
mode="legacy"
|
||||||
NOT_EXIST=1
|
else
|
||||||
|
if [ "${num_legacy_lines}" -ge "${num_nft_lines}" ]; then
|
||||||
|
mode="legacy"
|
||||||
|
else
|
||||||
|
mode="nft"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ $mode = "nft" ]; then
|
||||||
|
rm /sbin/iptables
|
||||||
|
rm /sbin/iptables-save
|
||||||
|
rm /sbin/iptables-restore
|
||||||
|
ln -s /sbin/iptables-nft /sbin/iptables
|
||||||
|
ln -s /sbin/iptables-nft-save /sbin/iptables-save
|
||||||
|
ln -s /sbin/iptables-nft-restore /sbin/iptables-restore
|
||||||
fi
|
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
|
||||||
|
|
||||||
# Default if not supplied - same as weave net default
|
# Default if not supplied - same as weave net default
|
||||||
IPALLOC_RANGE=${IPALLOC_RANGE:-10.32.0.0/12}
|
IPALLOC_RANGE=${IPALLOC_RANGE:-10.32.0.0/12}
|
||||||
HTTP_ADDR=${WEAVE_HTTP_ADDR:-127.0.0.1:6784}
|
HTTP_ADDR=${WEAVE_HTTP_ADDR:-127.0.0.1:6784}
|
||||||
METRICS_ADDR=${WEAVE_METRICS_ADDR:-0.0.0.0:6782}
|
METRICS_ADDR=${WEAVE_METRICS_ADDR:-0.0.0.0:6782}
|
||||||
HOST_ROOT=${HOST_ROOT:-/host}
|
HOST_ROOT=${HOST_ROOT:-/host}
|
||||||
CONN_LIMIT=${CONN_LIMIT:-100}
|
CONN_LIMIT=${CONN_LIMIT:-200}
|
||||||
DB_PREFIX=${DB_PREFIX:-/weavedb/weave-net}
|
DB_PREFIX=${DB_PREFIX:-/weavedb/weave-net}
|
||||||
|
|
||||||
# Check if the IP range overlaps anything existing on the host
|
# Check if the IP range overlaps anything existing on the host
|
||||||
@@ -38,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
|
||||||
@@ -66,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
|
||||||
@@ -85,7 +81,7 @@ router_bridge_opts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if [ -z "$KUBE_PEERS" ]; then
|
if [ -z "$KUBE_PEERS" ]; then
|
||||||
if ! KUBE_PEERS=$(/home/weave/kube-utils) || [ -z "$KUBE_PEERS" ]; then
|
if ! KUBE_PEERS=$(/home/weave/kube-utils); then
|
||||||
echo Failed to get peers >&2
|
echo Failed to get peers >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -122,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
|
||||||
@@ -129,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
|
||||||
|
|
||||||
@@ -159,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 \
|
||||||
|
|||||||
@@ -0,0 +1,239 @@
|
|||||||
|
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/v1
|
||||||
|
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
|
||||||
|
- apiGroups:
|
||||||
|
- 'networking.k8s.io'
|
||||||
|
resources:
|
||||||
|
- networkpolicies
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ''
|
||||||
|
resources:
|
||||||
|
- nodes/status
|
||||||
|
verbs:
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
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/v1
|
||||||
|
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/v1
|
||||||
|
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: apps/v1
|
||||||
|
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
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
name: weave-net
|
||||||
|
minReadySeconds: 5
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: weave-net
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: weave-init
|
||||||
|
image: 'rajchaudhuri/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:
|
||||||
|
- name: weave
|
||||||
|
command:
|
||||||
|
- /home/weave/launch.sh
|
||||||
|
env:
|
||||||
|
- name: INIT_CONTAINER
|
||||||
|
value: "true"
|
||||||
|
- name: HOSTNAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
- name: CHECKPOINT_DISABLE
|
||||||
|
value: "1"
|
||||||
|
image: 'rajchaudhuri/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: dbus
|
||||||
|
mountPath: /host/var/lib/dbus
|
||||||
|
readOnly: true
|
||||||
|
- mountPath: /host/etc/machine-id
|
||||||
|
name: cni-machine-id
|
||||||
|
readOnly: true
|
||||||
|
- name: xtables-lock
|
||||||
|
mountPath: /run/xtables.lock
|
||||||
|
readOnly: false
|
||||||
|
- name: weave-npc
|
||||||
|
env:
|
||||||
|
- name: HOSTNAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
image: 'rajchaudhuri/weave-npc:latest'
|
||||||
|
imagePullPolicy: Always
|
||||||
|
#npc-args
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
volumeMounts:
|
||||||
|
- name: xtables-lock
|
||||||
|
mountPath: /run/xtables.lock
|
||||||
|
readOnly: false
|
||||||
|
hostNetwork: true
|
||||||
|
dnsPolicy: ClusterFirstWithHostNet
|
||||||
|
hostPID: false
|
||||||
|
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: cni-machine-id
|
||||||
|
hostPath:
|
||||||
|
path: /etc/machine-id
|
||||||
|
- name: dbus
|
||||||
|
hostPath:
|
||||||
|
path: /var/lib/dbus
|
||||||
|
- name: lib-modules
|
||||||
|
hostPath:
|
||||||
|
path: /lib/modules
|
||||||
|
- name: xtables-lock
|
||||||
|
hostPath:
|
||||||
|
path: /run/xtables.lock
|
||||||
|
type: FileOrCreate
|
||||||
|
priorityClassName: system-node-critical
|
||||||
|
updateStrategy:
|
||||||
|
type: RollingUpdate
|
||||||
@@ -1,179 +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: 10m
|
|
||||||
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: 10m
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
hostNetwork: true
|
|
||||||
hostPID: true
|
|
||||||
restartPolicy: Always
|
|
||||||
securityContext:
|
|
||||||
seLinuxOptions: {}
|
|
||||||
serviceAccountName: weave-net
|
|
||||||
tolerations:
|
|
||||||
- effect: NoSchedule
|
|
||||||
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,198 +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: 10m
|
|
||||||
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: 10m
|
|
||||||
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
|
|
||||||
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
|
|
||||||
@@ -8,7 +8,7 @@ items:
|
|||||||
labels:
|
labels:
|
||||||
name: weave-net
|
name: weave-net
|
||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
- apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
metadata:
|
metadata:
|
||||||
name: weave-net
|
name: weave-net
|
||||||
@@ -48,7 +48,7 @@ items:
|
|||||||
verbs:
|
verbs:
|
||||||
- patch
|
- patch
|
||||||
- update
|
- update
|
||||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
- apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
name: weave-net
|
name: weave-net
|
||||||
@@ -62,7 +62,7 @@ items:
|
|||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: weave-net
|
name: weave-net
|
||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
- apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: Role
|
kind: Role
|
||||||
metadata:
|
metadata:
|
||||||
name: weave-net
|
name: weave-net
|
||||||
@@ -85,7 +85,7 @@ items:
|
|||||||
- configmaps
|
- configmaps
|
||||||
verbs:
|
verbs:
|
||||||
- create
|
- create
|
||||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
- apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
name: weave-net
|
name: weave-net
|
||||||
@@ -115,17 +115,42 @@ items:
|
|||||||
labels:
|
labels:
|
||||||
name: weave-net
|
name: weave-net
|
||||||
spec:
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: weave-init
|
||||||
|
image: 'rajchaudhuri/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:
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
fieldPath: spec.nodeName
|
fieldPath: spec.nodeName
|
||||||
image: 'weaveworks/weave-kube:latest'
|
- name: CHECKPOINT_DISABLE
|
||||||
|
value: "1"
|
||||||
|
image: 'rajchaudhuri/weave-kube:latest'
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
@@ -134,22 +159,18 @@ items:
|
|||||||
port: 6784
|
port: 6784
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 10m
|
cpu: 50m
|
||||||
securityContext:
|
securityContext:
|
||||||
privileged: true
|
privileged: true
|
||||||
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
|
||||||
@@ -160,12 +181,12 @@ items:
|
|||||||
fieldRef:
|
fieldRef:
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
fieldPath: spec.nodeName
|
fieldPath: spec.nodeName
|
||||||
image: 'weaveworks/weave-npc:latest'
|
image: 'rajchaudhuri/weave-npc:latest'
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
#npc-args
|
#npc-args
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 10m
|
cpu: 50m
|
||||||
securityContext:
|
securityContext:
|
||||||
privileged: true
|
privileged: true
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
@@ -173,7 +194,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: {}
|
||||||
@@ -181,6 +202,8 @@ items:
|
|||||||
tolerations:
|
tolerations:
|
||||||
- effect: NoSchedule
|
- effect: NoSchedule
|
||||||
operator: Exists
|
operator: Exists
|
||||||
|
- effect: NoExecute
|
||||||
|
operator: Exists
|
||||||
volumes:
|
volumes:
|
||||||
- name: weavedb
|
- name: weavedb
|
||||||
hostPath:
|
hostPath:
|
||||||
@@ -194,6 +217,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
|
||||||
|
|||||||
@@ -0,0 +1,238 @@
|
|||||||
|
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/v1
|
||||||
|
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
|
||||||
|
- apiGroups:
|
||||||
|
- 'networking.k8s.io'
|
||||||
|
resources:
|
||||||
|
- networkpolicies
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ''
|
||||||
|
resources:
|
||||||
|
- nodes/status
|
||||||
|
verbs:
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
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/v1
|
||||||
|
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/v1
|
||||||
|
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: apps/v1
|
||||||
|
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
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
name: weave-net
|
||||||
|
minReadySeconds: 5
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
name: weave-net
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: weave-init
|
||||||
|
image: 'rajchaudhuri/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:
|
||||||
|
- name: weave
|
||||||
|
command:
|
||||||
|
- /home/weave/launch.sh
|
||||||
|
env:
|
||||||
|
- name: INIT_CONTAINER
|
||||||
|
value: "true"
|
||||||
|
- name: HOSTNAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
- name: CHECKPOINT_DISABLE
|
||||||
|
value: "1"
|
||||||
|
image: 'rajchaudhuri/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: dbus
|
||||||
|
mountPath: /host/var/lib/dbus
|
||||||
|
readOnly: true
|
||||||
|
- mountPath: /host/etc/machine-id
|
||||||
|
name: cni-machine-id
|
||||||
|
readOnly: true
|
||||||
|
- name: xtables-lock
|
||||||
|
mountPath: /run/xtables.lock
|
||||||
|
readOnly: false
|
||||||
|
- name: weave-npc
|
||||||
|
env:
|
||||||
|
- name: HOSTNAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
apiVersion: v1
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
image: 'rajchaudhuri/weave-npc:latest'
|
||||||
|
imagePullPolicy: Always
|
||||||
|
#npc-args
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
volumeMounts:
|
||||||
|
- name: xtables-lock
|
||||||
|
mountPath: /run/xtables.lock
|
||||||
|
readOnly: false
|
||||||
|
hostNetwork: true
|
||||||
|
dnsPolicy: ClusterFirstWithHostNet
|
||||||
|
hostPID: false
|
||||||
|
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: cni-machine-id
|
||||||
|
hostPath:
|
||||||
|
path: /etc/machine-id
|
||||||
|
- name: dbus
|
||||||
|
hostPath:
|
||||||
|
path: /var/lib/dbus
|
||||||
|
- name: lib-modules
|
||||||
|
hostPath:
|
||||||
|
path: /lib/modules
|
||||||
|
- name: xtables-lock
|
||||||
|
hostPath:
|
||||||
|
path: /run/xtables.lock
|
||||||
|
type: FileOrCreate
|
||||||
|
updateStrategy:
|
||||||
|
type: RollingUpdate
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: List
|
|
||||||
items:
|
|
||||||
- apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: weave-net
|
|
||||||
labels:
|
|
||||||
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:
|
|
||||||
annotations:
|
|
||||||
scheduler.alpha.kubernetes.io/tolerations: >-
|
|
||||||
[{"key":"dedicated","operator":"Equal","value":"master","effect":"NoSchedule"}]
|
|
||||||
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: 10m
|
|
||||||
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: 10m
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
hostNetwork: true
|
|
||||||
hostPID: true
|
|
||||||
restartPolicy: Always
|
|
||||||
securityContext:
|
|
||||||
seLinuxOptions: {}
|
|
||||||
serviceAccountName: weave-net
|
|
||||||
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
|
|
||||||
@@ -27,7 +27,8 @@ RUN apk add --update \
|
|||||||
&& mknod /var/log/ulogd.pcap p
|
&& mknod /var/log/ulogd.pcap p
|
||||||
COPY ./weave-npc /usr/bin/weave-npc
|
COPY ./weave-npc /usr/bin/weave-npc
|
||||||
COPY ./ulogd.conf /etc/ulogd.conf
|
COPY ./ulogd.conf /etc/ulogd.conf
|
||||||
ENTRYPOINT ["/usr/bin/weave-npc"]
|
COPY ./launch.sh /usr/bin/
|
||||||
|
ENTRYPOINT ["/usr/bin/launch.sh"]
|
||||||
|
|
||||||
# These labels will change for every build, and should therefore be the last layer of the image:
|
# These labels will change for every build, and should therefore be the last layer of the image:
|
||||||
ARG revision
|
ARG revision
|
||||||
|
|||||||
Executable
+36
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Setup iptables backend to be legacy or nftable
|
||||||
|
setup_iptables_backend() {
|
||||||
|
if [ -n "${IPTABLES_BACKEND}" ]; then
|
||||||
|
mode=$IPTABLES_BACKEND
|
||||||
|
else
|
||||||
|
# auto-detect if iptables backend mode to use if not specified explicitly
|
||||||
|
num_legacy_lines=$( (iptables-legacy-save || true) 2>/dev/null | grep '^-' | wc -l)
|
||||||
|
num_nft_lines=$( (iptables-nft-save || true) 2>/dev/null | grep '^-' | wc -l)
|
||||||
|
if [ "${num_legacy_lines}" -ge 10 ]; then
|
||||||
|
mode="legacy"
|
||||||
|
else
|
||||||
|
if [ "${num_legacy_lines}" -ge "${num_nft_lines}" ]; then
|
||||||
|
mode="legacy"
|
||||||
|
else
|
||||||
|
mode="nft"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ $mode = "nft" ]; then
|
||||||
|
rm /sbin/iptables
|
||||||
|
rm /sbin/iptables-save
|
||||||
|
rm /sbin/iptables-restore
|
||||||
|
ln -s /sbin/iptables-nft /sbin/iptables
|
||||||
|
ln -s /sbin/iptables-nft-save /sbin/iptables-save
|
||||||
|
ln -s /sbin/iptables-nft-restore /sbin/iptables-restore
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_iptables_backend
|
||||||
|
|
||||||
|
# Start weave-npc with any flags specified in $EXTRA_ARGS as well as any flags passed to this container (for backwards compatibility)
|
||||||
|
exec /usr/bin/weave-npc $EXTRA_ARGS $@
|
||||||
+77
-62
@@ -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"
|
||||||
@@ -16,12 +19,13 @@ import (
|
|||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
|
||||||
"github.com/weaveworks/weave/common"
|
"github.com/rajch/weave/common"
|
||||||
"github.com/weaveworks/weave/net"
|
"github.com/rajch/weave/common/chains"
|
||||||
"github.com/weaveworks/weave/net/ipset"
|
"github.com/rajch/weave/net"
|
||||||
"github.com/weaveworks/weave/npc"
|
"github.com/rajch/weave/net/ipset"
|
||||||
"github.com/weaveworks/weave/npc/metrics"
|
"github.com/rajch/weave/npc"
|
||||||
"github.com/weaveworks/weave/npc/ulogd"
|
"github.com/rajch/weave/npc/metrics"
|
||||||
|
"github.com/rajch/weave/npc/ulogd"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -34,7 +38,14 @@ var (
|
|||||||
bridgePortName string
|
bridgePortName string
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleError(err error) { common.CheckFatal(err) }
|
func handleError(err error) {
|
||||||
|
if err != nil {
|
||||||
|
metrics.PolicyEnforcementErrors.Inc()
|
||||||
|
common.Log.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleFatal(err error) { common.CheckFatal(err) }
|
||||||
|
|
||||||
func makeController(getter cache.Getter, resource string,
|
func makeController(getter cache.Getter, resource string,
|
||||||
objType runtime.Object, handlers cache.ResourceEventHandlerFuncs) cache.Controller {
|
objType runtime.Object, handlers cache.ResourceEventHandlerFuncs) cache.Controller {
|
||||||
@@ -45,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,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
|
||||||
}
|
}
|
||||||
@@ -180,17 +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"},
|
|
||||||
{"-m", "mark", "!", "--mark", npc.EgressMark, "-j", "DROP"},
|
|
||||||
}...)
|
}...)
|
||||||
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 {
|
||||||
@@ -203,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) {
|
||||||
@@ -241,79 +247,88 @@ func root(cmd *cobra.Command, args []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config, err := rest.InClusterConfig()
|
config, err := rest.InClusterConfig()
|
||||||
handleError(err)
|
handleFatal(err)
|
||||||
|
|
||||||
client, err := kubernetes.NewForConfig(config)
|
client, err := kubernetes.NewForConfig(config)
|
||||||
handleError(err)
|
handleFatal(err)
|
||||||
|
|
||||||
ipt, err := iptables.New()
|
ipt, err := iptables.New()
|
||||||
handleError(err)
|
handleFatal(err)
|
||||||
|
|
||||||
ips := ipset.New(common.LogLogger(), maxList)
|
ips := ipset.New(common.LogLogger(), maxList)
|
||||||
|
|
||||||
handleError(resetIPTables(ipt))
|
handleFatal(resetIPTables(ipt))
|
||||||
handleError(resetIPSets(ips))
|
handleFatal(resetIPSets(ips))
|
||||||
handleError(createBaseRules(ipt, ips))
|
handleFatal(createBaseRules(ipt, ips))
|
||||||
|
|
||||||
npc := npc.New(nodeName, ipt, ips)
|
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)
|
||||||
@@ -340,5 +355,5 @@ func main() {
|
|||||||
rootCmd.PersistentFlags().IntVar(&maxList, "max-list-size", 1024, "maximum size of ipset list (for namespaces)")
|
rootCmd.PersistentFlags().IntVar(&maxList, "max-list-size", 1024, "maximum size of ipset list (for namespaces)")
|
||||||
rootCmd.PersistentFlags().StringVar(&bridgePortName, "bridge-port-name", "vethwe-bridge", "name of the brige port on which packets are received and sent")
|
rootCmd.PersistentFlags().StringVar(&bridgePortName, "bridge-port-name", "vethwe-bridge", "name of the brige port on which packets are received and sent")
|
||||||
|
|
||||||
handleError(rootCmd.Execute())
|
handleFatal(rootCmd.Execute())
|
||||||
}
|
}
|
||||||
@@ -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 \
|
||||||
|
|||||||
Loaded 100 of 5508 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user