Compare commits

...
178 Commits
Author SHA1 Message Date
Bryan Boreham ba64f8e8eb Add release v2.8.1 2021-01-25 10:55:30 +00:00
Bryan Boreham 263aecf4ef Merge pull request #3886 from avestuk/add-etc-machine-id-mount
Update daemonset manifest to mount /etc/machine-id
2021-01-22 14:21:16 +00:00
Bryan Boreham f9239c9a44 Merge pull request #3885 from weaveworks/move-k8s-checkpoint
Move Kubernetes API calls into kube-utils program
2021-01-22 12:50:08 +00:00
Alex Vest 9a2682671c Update daemonset manifest to mount /etc/machine-id
Mounted as ReadOnly in order to minimize attack surface as in #3880
2021-01-21 18:00:26 +00:00
Bryan Boreham ad621c807e Move Kubernetes API calls into kube-utils program
This reduces the size of the 'weaver' binary.
2021-01-19 17:22:47 +00:00
Bryan Boreham 164175160a Add release v2.8.0 2021-01-18 14:51:21 +00:00
Bryan Boreham edd28ab4cb Fix ambiguous cast in dummy value
Go 1.15 picks this up as an error
2021-01-18 14:41:42 +00:00
Bryan Boreham 4368dd5841 Run CI builds using Go 1.15.6 2021-01-18 14:40:57 +00:00
Bryan Boreham 1dfe1f3b98 Merge pull request #3883 from weaveworks/golang-15-6
Update Go to 1.15.6
2021-01-18 14:09:43 +00:00
Bryan Boreham b1651c322a Merge pull request #3882 from weaveworks/3847-sleep-before-ipset-destroy
Workaround to fix ipset conflict with iptables
2021-01-18 14:09:19 +00:00
Bryan Boreham ba6741166d Update Go to 1.15.6 2021-01-18 13:52:39 +00:00
Bryan Boreham 108f0a5c14 Merge pull request #3851 from NeonSludge/fix-ipset-destroy
Pause and retry ipset deletion if it fails the first time
2021-01-18 13:31:58 +00:00
Bryan Boreham b04217d8e6 Merge pull request #3840 from mastappl/patch-1
website: add info about network aliases
2021-01-18 12:36:26 +00:00
KevDG 3ef97f0c7c Workaround to fix ipset conflict with iptables
Sleep before ipset destroy in startup, otherwise the operation can
sometimes fail - see https://github.com/weaveworks/weave/issues/3847
2021-01-18 12:33:54 +00:00
Bryan Boreham e91900cc9e Merge pull request #3880 from weaveworks/init-container
Kubernetes: move kernel and CNI setup to init container

This allows the main container to run without write access to the host filesystem,
except for two specific areas, thus trimming the attack surface.

Also remove manifests for Kubernetes 1.6 and 1.7 to reduce maintenance load -
they are ancient history.
2021-01-14 12:10:25 +00:00
Bryan Boreham fe61992c06 Make launch.sh compatible with older k8s manifests 2021-01-12 15:53:12 +00:00
Bryan Boreham 8eeb3ca4f2 Kubernetes: move part of launch to init container
This allows the main container to run without write access to the host
filesystem, except for two specific areas, thus trimming the attack
surface.

We lose the behaviour that the CNI plugin is only installed if Weave Net
gets up and running at least once, so the error reports from kubelet
will be slightly different in the case that it never manages to run.
2021-01-11 17:54:43 +00:00
Bryan Boreham b7a9947c2f Remove manifests for Kubernetes 1.6 and 1.7
They are ancient history; reduce maintenance load by removing
2021-01-11 14:34:09 +00:00
Bryan Boreham d81e908d1a Merge pull request #3876 from weaveworks/k8s-disable-hostpid
For K8s, stop running in host PID namespace
2020-12-17 16:53:42 +00:00
Bryan Boreham a0ac81b3b4 Stop running in host PID namespace
We shouldn't need this
2020-12-17 12:49:27 +00:00
Bryan Boreham c6d0d140a4 Use newest manifest in k8s tests 2020-12-17 12:49:27 +00:00
Bryan Boreham 9bb14662e5 Add security policy 2020-12-17 11:52:07 +00:00
Bryan Boreham 240d1b2f2a Merge pull request #3854 from weaveworks/simplify-test-840
Simplify Kubernetes externalTrafficPolicy:local test
2020-12-17 11:21:46 +00:00
Bryan Boreham 414cbfb838 Simplify Kubernetes externalTrafficPolicy:local test
There's no point stopping and starting the daemons now "no-masq-local"
is the default.
2020-08-27 15:20:04 +00:00
Bryan Boreham fb7fc7ddae Merge pull request #3852 from weaveworks/spurious-egress-drop-logs
Move egress logging rule beside drop rule
2020-08-27 16:12:16 +01:00
Bryan Boreham 8c52698222 Move egress logging rule beside drop rule
Otherwise we might log a blocked connection even though the packet
was not dropped.
2020-08-26 10:02:32 +00:00
Kirill Buev cb2e56fc44 Pause and retry ipset deletion if it fails the first time 2020-08-24 16:23:52 +03:00
Bryan Boreham 30ce219794 Add release v2.7.0 2020-08-05 10:38:13 +00:00
Bryan Boreham 911f506b63 Merge pull request #3841 from weaveworks/fail-controller-if-goroutines-fail
Terminate NPC application if any of the watches panic
2020-08-05 11:35:49 +01:00
Bryan Boreham 4795ba5807 Show stack-trace from panic in weave-npc
Rather than exiting silently, fetch the stack trace and print that
for the user to understand what happened.

Exit via existing fatal-error code.
2020-08-05 09:45:20 +00:00
Bryan Boreham 23a827088b Remove unused stopChan 2020-08-05 09:44:19 +00:00
naemono 269786abf5 Simply run os.Exit on panic of goroutine 2020-08-05 09:40:02 +00:00
Bryan Boreham 9cf4104de7 Merge pull request #3838 from weaveworks/go1_14_4
Update to Go 1.14.4 and modules; update other dependencies
2020-08-04 18:25:40 +01:00
Bryan Boreham 5f27dbf17c Merge pull request #3756 from weaveworks/issue-3389
Change NO_MASQ_LOCAL option to default ON
2020-08-04 17:42:16 +01:00
Bryan Boreham 0ab2d08f0c Update docs now NO_MASQ_LOCAL is the default 2020-08-04 16:21:30 +00:00
Bryan Boreham 4d7e9931f9 Remove NO_MASQ_LOCAL setting from test 840
now it's the default
2020-08-04 16:21:30 +00:00
Murali Reddy fca23f805a modify launch.sh to launch weaver with --no-masq-local by default 2020-08-04 16:21:30 +00:00
Denis Zaripov 905ec927a3 add info about network aliases
Update documentation for #3090
2020-08-04 20:43:10 +05:00
Bryan Boreham 2864d1ebc5 Use Go 1.14.4 in CI build 2020-08-04 10:11:30 +00:00
Bryan Boreham b3d387fb86 Update Kubernetes client packages to 0.18.6
Lots of functions need Context parameters added
2020-08-04 10:11:30 +00:00
Bryan Boreham d14502e071 Update Prometheus client to latest version
Also let Prometheus export process and Go metrics
2020-08-04 10:11:28 +00:00
Bryan Boreham 9439606c57 Update vendor files 2020-08-04 10:11:27 +00:00
Bryan Boreham feb05c0904 Move to Go modules: initial go.mod 2020-08-04 10:11:27 +00:00
Bryan Boreham 514695e127 Update Go version to 1.14.6 2020-08-04 10:11:27 +00:00
Bryan Boreham f9e27f76d6 Merge remote-tracking branch 'gobomb/fix-nil-ns-pointer'
Needed a few modifications to resolve conflicts due to changed
datatype of UID.
2020-08-03 12:32:31 +00:00
Bryan Boreham c3504788a0 Merge pull request #3780 from alok87/patch-1
Documentation Update for Weave Net Monitoring.
2020-08-03 11:42:13 +01:00
Bryan Boreham 4592758e48 Merge pull request #3789 from hairyhenderson/add-connection-type-label-to-weave-connection-metric-3788
Add new 'type' and 'encryption' labels to weave_connections metric
2020-08-03 11:40:16 +01:00
gobomb 2ec3e1ef1a add fake namespace uid for npc test 2020-08-02 23:42:12 +08:00
gobomb 0789670344 add namespaceLabels and namespaceUID, remove namespace in ns struct 2020-08-02 21:06:17 +08:00
Bryan Boreham 80a80816aa Merge pull request #3687 from weaveworks/docker-19-3
Bump Docker to 19.03.1, Kubernetes to 1.14.0 for smoke tests
2020-07-31 18:04:13 +01:00
Bryan Boreham c50b3380ea Fix tests where newer Docker returns hex ID of container as network ID 2020-07-31 16:29:41 +00:00
Bryan Boreham aa9caab1b0 Fix incompatibility in Docker Python test
Using code from https://github.com/bboreham/docker-py/tree/v1.9.0-prime

Also change to using Python 3 since 2.x is EOL.
2020-07-31 16:29:41 +00:00
Murali Reddy ce9d05e0bd Allow kubeadm to install on nodes with 1 CPU, for smoke tests 2020-07-31 16:29:41 +00:00
Murali Reddy 0c4aeb3a0b Run smoke-tests with Kubernetes 1.14.0 and CNI 0.7.5 2020-07-31 16:29:02 +00:00
Murali Reddy f24cf798bc build tool updates
including changes to accommodate current get.docker.com script
2020-07-31 16:28:52 +00:00
Murali Reddy 3d66dcd94e run terraform init for gcp plugin initialization 2020-07-31 14:52:46 +00:00
Bryan Boreham fab09693b9 Bump Docker to 19.03.1 for smoke tests 2020-07-31 14:52:46 +00:00
Bryan Boreham cdbc25d462 Merge pull request #3231 from weaveworks/issues/1770-fetch-dns-address
Fetch DNS listen address from daemon
2020-07-31 13:47:41 +01:00
Bryan Boreham 6946731fdd Merge pull request #3090 from berlic/dns-aliases
Register container name and its network aliases with weaveDNS
2020-07-31 13:30:27 +01:00
Bryan Boreham 0078fc535a Merge pull request #3714 from weaveworks/lint-cleanup
Lint cleanup
2020-07-31 13:02:21 +01:00
Bryan Boreham 9ffd0e3450 Fix up tests for DNS changes
Now that `weave dns-args` doesn't parse any flags we need to
call it or not call it, which `start_container` will do for us.

Also add back the part of the test where we run weaver with and
without DNS, which had become lost in 8b061fd555

Also change a couple of tests to use proxy to start containers,
again to avoid needing `dns-args` to parse flags.
2020-07-31 11:59:20 +00:00
Bryan Boreham 5b2311bb45 Remove obsolete args parsing from dns-args
It was used as part of 'weave run'; does not make sense to support
--name, -h, etc., on 'weave dns-args'.
2020-07-31 11:59:20 +00:00
Bryan Boreham b0274e11be Fetch DNS listen address from daemon
instead of assuming it's on the Docker bridge

Also move DNS address validation into NewDNSServer(),
so we only do it once.
2020-07-31 11:58:56 +00:00
Bryan Boreham 34dc4dabce Clean up some lint warnings
I ran golangci-lint and it pointed out a few things to clean up.
2020-07-31 10:28:55 +00:00
Bryan Boreham 28e482af14 Avoid some deprecated APIs 2020-07-31 10:28:55 +00:00
Bryan Boreham c197624689 Fix up incorrect output formatting 2020-07-31 09:03:27 +00:00
Bryan Boreham 00bc020498 Use Context instead of deprecated http.CloseNotifier interface 2020-07-31 09:03:27 +00:00
Bryan Boreham df52117bfa Remove unused code 2020-07-31 09:03:27 +00:00
Bryan Boreham 00623be8a7 Merge pull request #3624 from weaveworks/trim-tools
Remove some unused tools from the Weave docker containers
2020-07-30 14:14:49 +01:00
Bryan Boreham 4d3e8d4a82 Merge pull request #3726 from weaveworks/slim-dependencies
Slim utility binaries by reducing dependencies
2020-07-30 14:13:47 +01:00
Bryan Boreham 2cc5c635c9 Add 'encrypted' label to connections metric
Extend tests to check it shows up.
Tests assume that metrics are published with metrics in alphabetical
order, which appears to be the case for now.
2020-07-30 11:07:33 +00:00
Bryan Boreham 865e2b726f Ensure maps for connection counts are created before use
We know all the expected states, so can pre-create maps
2020-07-30 10:25:14 +00:00
Bryan Boreham f6a3af4a10 Add a check for correct metrics in smoke-test 2020-07-30 10:25:14 +00:00
Dave Henderson 2deb7e2e48 Add new 'type' label to weave_connections metric
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
2020-07-30 10:24:38 +00:00
Bryan Boreham ce38141e5b Merge pull request #3835 from nesc58/iptables-w
wait added to iptables commands
2020-07-29 17:25:36 +01:00
Bryan Boreham 6bc656d66c Move address range helpers into address package
This means that users don't drag in a dependency on aws-sdk.
2020-07-29 13:08:35 +00:00
Bryan Boreham ca4f93d0d7 Remove the dependency of 'ipset' package on Kubernetes
We don't want everyone that uses the `net` package to get a transitive
dependency on the Kubernetes APIs, so have it define the `UID` type.

Conceptually this is a simple change because `UID` is a `string`, but
unfortunately it is used in a lot of places.
2020-07-29 13:08:35 +00:00
Bryan Boreham a3c76e141b Move name constants to separate 'chains' package, to reduce dependencies
We don't want everyone that uses the `net` package to get a transitive
dependency on the Kubernetes APIs required by `npc`.
2020-07-29 12:55:46 +00:00
Nesc58 f4009c39d8 wait added to iptables commands 2020-07-28 10:46:49 +02:00
Bryan Boreham 9928ddb401 Merge branch '2.6' 2020-07-27 17:44:11 +00:00
Bryan Boreham 7b927a7bac Merge pull request #3802 from weaveworks/reload-ip-tables
Reload router iptables rules if they get cleared
2020-07-24 14:33:47 +01:00
Simon Howe 341bac9968 Rename Monitor -> MonitorForIptablesFlush
- Makes it all a bit more explicit
2020-07-24 15:04:28 +02:00
Simon Howe 1d7ca17c3e Improve Monitor function description 2020-07-24 15:01:45 +02:00
Konstantin Suvorov add109a63d Merge pull request #4 from a-kataev/dns-aliases
Fixed mismatched types
2020-07-17 08:50:45 +03:00
Alex Kataev 0f276a4d63 Fixed mismatched types in the condition 2020-07-17 10:45:53 +05:00
Konstantin Suvorov 0ac333b91c Merge pull request #3 from a-kataev/dns-aliases
Additional DNS names registration
2020-07-16 22:11:11 +03:00
Alex Kataev acbd744372 Refactor: additional DNS names registration 2020-07-15 16:34:28 +05:00
Simon Howe c0e5008202 Update tests after removing canary refresh flag 2020-07-15 11:37:53 +02:00
Simon Howe 899490c3f9 Removes disabling iptable canary
- Should always be on. Simpler.
2020-07-15 11:37:53 +02:00
Simon Howe 709b434f55 Clean up the Monitor go routine 2020-07-15 11:37:53 +02:00
Simon Howe ca7103d007 Review feedback: don't recreate NoMasqLocalIpset onCanaryDeleted 2020-07-15 11:37:53 +02:00
Simon Howe 66eb80d841 Adds a CANARY chain and Monitor loop instead of reapplying iptables 2020-07-15 11:37:16 +02:00
Simon Howe 94e75e45af Make ConfigureIPTables idempotent and poll it
- Instead of EnsureBridge
- Adds ipset.ExistEntry method
- Refactor ipset method names Exist <-> EntryExists
- Turn on iptable-refresh by default (10s)
- Adds a test that checks iptables are refreshed, check EXPOSE recovers
2020-07-15 11:35:41 +02:00
Konstantin Suvorov fa5e032e49 Register container name and its network aliases with weaveDNS 2020-07-14 18:15:37 +03:00
Bryan Boreham a90c0075c8 Typo 2020-06-17 17:03:13 +00:00
Bryan Boreham 1ff09fd4d1 Merge branch '2.6' 2020-06-10 17:15:14 +00:00
Bryan Boreham e0348233af Add release v2.6.5 2020-06-10 13:41:13 +00:00
Bryan Boreham 495bea8890 Merge pull request #3808 from weaveworks/stop-switch-fwd
router: tell goroutine to exit when forwarder is stopped
2020-06-10 14:07:41 +01:00
Bryan Boreham 88799b36b2 Merge branch '2.6' 2020-06-04 17:53:53 +00:00
Bryan Boreham 3d79b07dba Merge pull request #3815 from weaveworks/ignore-ipv6-not-found
Don't exit if machine has no ipv6 installed
2020-06-04 18:47:28 +01:00
Bryan Boreham 27f8f9092f router: tell goroutine to exit when forwarder is stopped
Otherwise a goroutine is leaked each time a connection is closed.
2020-06-04 17:46:18 +00:00
Bryan Boreham 7174738d9d Don't exit if machine has no ipv6 installed
We are trying to turn off `accept_ra`, so if we get an error that the
option doesn't exist we can just ignore it.
2020-06-04 16:12:38 +00:00
Bryan Boreham 11d75b27a6 Merge branch '2.6' 2020-05-30 12:13:46 +00:00
Bryan Boreham 9be65b466b Merge pull request #3812 from weaveworks/improve-test-840
Kubernetes smoke-test improvements
2020-05-30 13:13:28 +01:00
Bryan Boreham c7a235a54a Add release v2.6.4 2020-05-30 10:11:08 +00:00
Bryan Boreham bef50d3730 Merge pull request #3811 from weaveworks/allow-dnat-127
Only drop traffic to the Weave Net port on 127.0.0.1
2020-05-30 11:07:13 +01:00
Bryan Boreham 9d669c3312 Merge branch '2.6' 2020-05-29 19:59:33 +00:00
Bryan Boreham d45579bf82 Allow time for network policy changes to take effect
Also change from waiting longer to polling until connections are
established after restarting Weave Net.
2020-05-29 19:59:13 +00:00
Bryan Boreham a46d18da0c Use a more targeted iptables rule to block access to control port
Only block the specific port Weave Net is listening on.
Add a comment so users know what the rule is for.

Remove the rule added in v2.6.3 because it was too coarse.
2020-05-29 19:58:41 +00:00
Bryan Boreham 95c020fbe0 Merge pull request #3809 from weaveworks/move-ansible-install
Move ansible install out from every CI run
2020-05-29 20:58:05 +01:00
Bryan Boreham 7c2084b9af Move ansible install out from every CI run
to only where we create images.
2020-05-29 13:33:30 +00:00
Bryan Boreham ac54cfb753 Merge branch '2.6' 2020-05-29 09:02:12 +00:00
Bryan Boreham f78c4dacc5 Add release v2.6.3 2020-05-28 10:12:54 +00:00
Bryan Boreham 9245b73913 Merge pull request #3805 from weaveworks/block-remote-localhost
Block non-local traffic to the Weave control port
2020-05-28 10:50:55 +01:00
Bryan Boreham 6ee961b068 Block non-local traffic to the Weave control port
We expect the loopback address 127.0.0.1 to be accessible only from
the local host.

We need to allow RELATED,ESTABLISHED traffic which may be the return
path of a Kubernetes HostPort.
2020-05-27 16:43:50 +00:00
Bryan Boreham 0d4099bba5 Clarify the purpose of the net-dev Slack channel 2020-05-27 10:58:59 +00:00
Bryan Boreham 21c7bb3ff6 Merge branch '2.6' 2020-05-26 08:31:53 +00:00
Bryan Boreham 1f920513de Merge pull request #3804 from weaveworks/npc-errors-metrics2
metric for NPC errors
2020-05-23 20:43:55 +01:00
Bryan Boreham 15f21f1899 Merge pull request #3801 from weaveworks/disable-accept-ra
Disable accept_ra on Weave Net interfaces
2020-05-22 11:00:50 +01:00
Bryan Boreham 09a204b978 NPC: increment metric each time an error is logged 2020-05-22 09:55:07 +00:00
Murali Reddy 77fbb2c12b introduce weavenpc_policy_enforcement_errors prometheus metric
to track number of errors occured during enforcing network policies

Fixes #3791
2020-05-22 09:54:11 +00:00
Bryan Boreham 6ad3e69faf Plumb through /proc path config to Docker plugin 2020-05-18 14:47:26 +00:00
Bryan Boreham e2088ef401 Disable accept_ra setting on interfaces we create 2020-05-14 10:21:41 +00:00
Bryan Boreham 0f3864968e refactor: supply /proc path to CreateAndAttachVeth()
Move the assumptions about where we're running up towards the caller.
2020-05-14 10:21:09 +00:00
Bryan Boreham ff9bcdf561 Merge branch '2.6' 2020-05-08 10:30:27 +00:00
Bryan Boreham 2f235daa1c Merge pull request #3777 from weaveworks/eks
add steps to install weave-net on EKS
2020-04-02 12:32:21 +01:00
Murali Reddy 438a5f5fd1 clarify pods connect to api server 2020-04-02 16:12:02 +05:30
Bryan Boreham b051ef0878 Merge pull request #3790 from weaveworks/npc-errors
Weave-npc: while logging differentiate between fatal and non-fatal errors
2020-04-02 11:24:10 +01:00
Murali Reddy 48015aa7be Weave-npc: while logging differentiate between fatal and non-fatal errors 2020-04-02 15:08:15 +05:30
Murali Reddy 0c4659c3b5 Merge branch '2.6' 2020-03-17 22:36:38 +05:30
Murali Reddy 14730f8572 Add release v2.6.2 2020-03-17 20:36:24 +05:30
Bryan Boreham 06b0a82465 Merge branch '2.6' 2020-03-12 10:38:59 +00:00
Bryan Boreham e7a24eaf0a Merge pull request #3783 from weaveworks/issue-3781
send FastDatapathCryptoInitSARemote control message only if encryption is enabled
2020-03-12 10:09:26 +00:00
Bryan Boreham 15ad210bec Merge pull request #3782 from weaveworks/fix-pcap-timeout
Reduce pcap timeout to avoid overflow
2020-03-11 16:32:32 +00:00
Murali Reddy 6bc0e5e71c send FastDatapathCryptoInitSARemote control message only if encryption is enabled
Fixes #3781
2020-03-11 21:26:09 +05:30
Bryan Boreham 0ca831f50b Reduce pcap timeout to avoid overflow
The value is passed by google/gopacket into a signed 32-bit int, so we
must pick a timeout which is less than 2^31 microseconds.

See https://github.com/google/gopacket/issues/708
2020-03-11 12:21:07 +00:00
Murali Reddy 6e1770d24d Merge branch '2.6' 2020-03-06 23:14:42 +05:30
Murali Reddy 57bca8e955 Add release v2.6.1 2020-03-06 18:36:33 +05:30
Alok Kumar Singh 733df28a65 Detailed updated info on monitoring weave net in Kubernetes 2020-03-06 00:05:02 +05:30
Bryan Boreham 709f820ab6 Merge pull request #3763 from weaveworks/no-lock-round-send
Move send of ipsec message outside lock
2020-03-05 10:21:18 +00:00
Alok Kumar Singh 6a1fbec5e2 Cross linked the weave net monitoring setup info 2020-03-05 09:08:29 +05:30
Alok Kumar Singh 35d8465376 Added weave net kube prometheus documentation link 2020-03-05 08:57:38 +05:30
Bryan Boreham 9f00f78d3b Merge branch '2.6' 2020-02-26 14:44:51 +00:00
Bryan Boreham 599b99a6c4 Merge pull request #3770 from weaveworks/fix-manifests
fix weave-kube manifests
2020-02-26 11:37:01 +00:00
Murali Reddy 4e3acfdc02 add note on apiserver being on EKS managed network 2020-02-26 10:29:50 +05:30
Murali Reddy 11915948a2 add steps to install weave-net on EKS 2020-02-26 10:27:01 +05:30
Bryan Boreham bb51a4f36d Merge pull request #3766 from weaveworks/static-ips-doc
Note different ways to ask for static IPs
2020-02-14 09:31:13 +00:00
Murali Reddy 5d0e44bb6f add missing dnsPolicy: ClusterFirstWithHostNet in weave-daemonset-k8s-1.11.yaml
update apiVersion from rbac.authorization.k8s.io/v1beta1 to rbac.authorization.k8s.io/v1
2020-02-11 13:15:33 +05:30
Bryan Boreham 6e7a469a62 Note different ways to ask for static IPs 2020-02-05 09:57:12 +00:00
Bryan Boreham ca0498b860 Fix warning log to use formatted variant 2020-01-28 15:15:28 +00:00
Bryan Boreham bbfa682083 Move send of ipsec message outside lock
The send may block, so do all changes to the forwarder object and
release the lock before attempting to send.
2020-01-28 15:13:33 +00:00
Bryan Boreham f763c40c10 Update connection limit in docs 2020-01-28 12:53:14 +00:00
Bryan Boreham 6a458d0712 Merge branch '2.6' 2020-01-27 17:51:32 +00:00
Bryan Boreham 67037b43b0 Merge pull request #3760 from weaveworks/update-ruby-262
Update Ruby version for Netlify build
2020-01-27 17:46:51 +00:00
Bryan Boreham 861395011c Update Ruby version for the benefit of Netlify build
Picked 2.6.2 based on message from Netlify build:
"Included versions: 2.3.6 2.5.4 2.4.5 2.4.3 2.2.9 2.6.2"
2020-01-27 17:05:46 +00:00
Bryan Boreham 8bdfcd3042 Merge pull request #3747 from weaveworks/iptables1.8
support Iptables 1.8 with legacy and nf_tables support
2020-01-08 10:46:41 +00:00
Murali Reddy 83024b946f use softlinks to link iptables to backend specific commands and update docs 2020-01-08 15:44:22 +05:30
Murali Reddy 4f48670345 set iptables backend to use if specified explicitly or auto-detect 2020-01-08 15:44:10 +05:30
Murali Reddy 4b30d97d4e update alpine base image to 3.10 that has iptables ver 1.8.3 2020-01-08 15:43:51 +05:30
Bryan Boreham c9e813cfcb Merge pull request #3740 from weaveworks/raise-cpu-requests
Raise Kubernetes CPU requests from 10m to 50m
2019-12-13 12:27:24 +00:00
Bryan Boreham 7c97bb5d30 Merge branch '2.6' 2019-12-13 12:00:07 +00:00
Bryan Boreham c97c50b76e Merge pull request #3735 from weaveworks/release-script-add-k11
Add weave-daemonset-k8s-1.11.yaml to release script
2019-12-13 11:37:09 +00:00
Bryan Boreham f919d06e2c Merge pull request #3745 from AlejoAsd/fix/site-kube-addon-md-link-fix
Fix kube-addon documentation broken markdown link
2019-12-13 11:32:47 +00:00
Bryan Boreham cee6929cb9 Merge pull request #3729 from weaveworks/simplify-test-320
Remove the need for a third host in test 320
2019-12-13 11:31:06 +00:00
Bryan Boreham 526538d9d1 Merge branch 'master' into 2.6 2019-12-07 11:55:16 +00:00
Bryan Boreham f43f3fc2e8 Merge pull request #3744 from weaveworks/issue-3741
upgrade to newer terraform that is compatible with google cloud API
2019-12-07 11:54:47 +00:00
Alejo Carballude 8b220f6383 Fix kube-addon documentation broken markdown link. 2019-12-06 16:00:03 -03:00
Murali Reddy d44e34584a Update tools submodule to latest commit 2a2df527894bcaa5d42ad80654c43e1e5a6b03d7 2019-12-06 18:48:49 +05:30
Murali Reddy 6d2366ca4c upgrade to newer terraform that is compatible with google cloud API
Fixes #3741
2019-12-06 10:19:27 +05:30
Bryan Boreham 7c1b615c98 Add a note about dropping CAP_NET_RAW in Kubernetes 2019-12-04 21:04:55 +00:00
Bryan Boreham 390a4099d0 Merge branch '2.6' 2019-11-28 20:47:39 +00:00
Bryan Boreham 01237446eb Update docs to match new memory requests 2019-11-22 23:23:55 +00:00
Bryan Boreham 18deb42df1 Raise Kubernetes CPU requests from 10m to 50m
This setting is passed by Kubelet to the Linux scheduler to ask for a share of
available CPU, so we should ask for a bit more than 1% of 1 CPU. Otherwise if a
CPU is contended Weave Net will get throttled frequently.

Weave Net in fastdp mode shouldn't need a lot of CPU most of the time, but at
startup there is quite a lot to do.

The setting is also used by the Kubernetes scheduler to decide how much will fit
on a node, so setting it much higher will reserve CPU that we shouldn't need most
of the time.
2019-11-22 22:30:03 +00:00
Bryan Boreham 5c508f837e Add manifest for Kubernetes 1.11 and above 2019-11-11 10:15:53 +00:00
Bryan Boreham e000472af7 Release 2.6 2019-11-05 19:40:45 +00:00
Bryan Boreham 6d70284c21 Increase default connection limit to 200
Improvements in resource consumption in larger clusters mean we can
raise this limit.
2019-11-05 19:40:45 +00:00
Bryan Boreham 9a6d0c9cf5 Remove the need for a third host in test 320
This was necessary when we didn't have ipam persistence, as the
comment said "to remember the IPAM CRDT when we stop host2".
But we have persistence to hold the CRDT so we don't need host3.

Rename the test so the test runner only gives it 2 hosts.
2019-11-04 16:13:46 +00:00
Bryan Boreham fdf881420c Remove some unused tools from the Weave docker containers
Use of `ethtool` was removed in #1958
`util-linux` was needed for `nsenter` which was removed in #3291
2019-03-26 18:42:14 +00:00
2421 changed files with 328272 additions and 290151 deletions

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
version: 2
defaults: &defaults
docker:
- image: weaveworks/weavebuild:go-1-13-1-5110a604
- image: weaveworks/weavebuild:master-1dfe1f3b
working_directory: /go/src/github.com/weaveworks/weave
jobs:
+1 -1
View File
@@ -1 +1 @@
2.3.0
2.6.2
+108
View File
@@ -1,3 +1,111 @@
## 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
+3 -3
View File
@@ -1,3 +1,3 @@
DOCKER_VERSION=17.06
KUBERNETES_VERSION=1.11.0
KUBERNETES_CNI_VERSION=0.6.0
DOCKER_VERSION=19.03.1
KUBERNETES_VERSION=1.14.0
KUBERNETES_CNI_VERSION=0.7.5
+1 -1
View File
@@ -25,7 +25,7 @@ ifeq ($(ARCH),amd64)
WEAVEEXEC_DOCKER_ARCH?=x86_64
# The name of the alpine baseimage to use as the base for weave images
ALPINE_BASEIMAGE?=alpine:3.8
ALPINE_BASEIMAGE?=alpine:3.10
# The extension for the made images
# Specifying none means for example weaveworks/weave:latest
+1 -1
View File
@@ -29,7 +29,7 @@ If you have any questions about, feedback for or a problem with Weave Net:
- Read [the Weave Net docs](https://www.weave.works/docs/net/latest/overview).
- Invite yourself to the <a href="https://slack.weave.works/" target="_blank">Weave Users Slack</a>.
- Ask a question on the [#net-dev](https://weave-community.slack.com/messages/net-dev/) slack channel.
- The channel for contributors and developers of Weave Net is [#net-dev](https://weave-community.slack.com/messages/net-dev/).
- Join the <a href="https://www.meetup.com/pro/Weave/"> Weave User Group </a> and get invited to online talks, hands-on training and meetups in your area.
- [File an issue](https://github.com/weaveworks/weave/issues/new).
+14
View File
@@ -0,0 +1,14 @@
# Security Policy
At Weaveworks we take security very seriously, and value our close relationship with members of the security community.
## Supported Versions
As an Open Source project, only the latest code has all fixes and security patches.
If you require a higher level of commitment, please [contact Weaveworks](https://www.weave.works/contact/) to discuss.
## Reporting a Vulnerability
To submit a security bug report please e-mail us at security@weave.works.
We also operate a Bug Bounty programme; see https://www.weave.works/bug-bounty/
+1 -9
View File
@@ -10,14 +10,7 @@ function signal_failure() {
trap signal_failure ERR
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
}
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
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
}
[ -n "$SECRET_KEY" ] || {
@@ -28,7 +21,6 @@ function install_ansible() {
source "$SRCDIR/bin/circle-env"
install_terraform
install_ansible
# Only attempt to create GCP image in first container, wait for it to be created otherwise:
[ "$CIRCLE_NODE_INDEX" != "0" ] && export CREATE_IMAGE=0
+15 -30
View File
@@ -89,10 +89,9 @@ build() {
## Inject the version numbers and build the distributables
## (library versions?)
sed -i.bak "/SCRIPT_VERSION=/ c\SCRIPT_VERSION=\"$VERSION\"" ./weave
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.6.yaml
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.7.yaml
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.8.yaml
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.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
if make tests; then
@@ -161,20 +160,6 @@ draft() {
--name "weave" \
--file "./weave"
github-release upload \
--user $GITHUB_USER \
--repo weave \
--tag $LATEST_TAG \
--name "weave-daemonset-k8s-1.6.yaml" \
--file "./prog/weave-kube/weave-daemonset-k8s-1.6.yaml"
github-release upload \
--user $GITHUB_USER \
--repo weave \
--tag $LATEST_TAG \
--name "weave-daemonset-k8s-1.7.yaml" \
--file "./prog/weave-kube/weave-daemonset-k8s-1.7.yaml"
github-release upload \
--user $GITHUB_USER \
--repo weave \
@@ -189,6 +174,13 @@ draft() {
--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 -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
}
@@ -276,20 +268,6 @@ publish() {
--name "weave" \
--file "./weave"
github-release upload \
--user $GITHUB_USER \
--repo weave \
--tag latest_release \
--name "weave-daemonset-k8s-1.6.yaml" \
--file "./prog/weave-kube/weave-daemonset-k8s-1.6.yaml"
github-release upload \
--user $GITHUB_USER \
--repo weave \
--tag latest_release \
--name "weave-daemonset-k8s-1.7.yaml" \
--file "./prog/weave-kube/weave-daemonset-k8s-1.7.yaml"
github-release upload \
--user $GITHUB_USER \
--repo weave \
@@ -304,6 +282,13 @@ publish() {
--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 -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/latest_release"
+1 -1
View File
@@ -1,4 +1,4 @@
FROM golang:1.13.3-buster
FROM golang:1.15.6-buster
# Support Raspberry Pi 2 and newer
ENV GOARM 7
+12
View File
@@ -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"
)
+6
View File
@@ -54,6 +54,12 @@ func SetLogLevel(levelname string) {
Log.Level = level
}
func CheckError(e error) {
if e != nil {
Log.Error(e)
}
}
func CheckFatal(e error) {
if e != nil {
Log.Fatal(e)
+65
View File
@@ -0,0 +1,65 @@
module github.com/weaveworks/weave
go 1.14
require (
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
github.com/Microsoft/go-winio v0.4.7 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/andybalholm/go-bit v0.0.0-20150501193155-34813fe0e46a
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
github.com/aws/aws-sdk-go v1.13.22
github.com/boltdb/bolt v1.3.1
github.com/containerd/continuity v0.0.0-20180322171221-3e8f2ea4b190 // indirect
github.com/containernetworking/cni v0.5.2
github.com/coreos/go-iptables v0.3.0
github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible // indirect
github.com/docker/docker v17.12.0-ce-rc1.0.20180328155642-38588656727d+incompatible
github.com/docker/go-connections v0.3.0 // indirect
github.com/docker/go-units v0.3.2 // indirect
github.com/docker/libnetwork v0.8.0-dev.2.0.20180212220201-119badbd737b
github.com/docker/machine v0.14.0
github.com/fsouza/go-dockerclient v1.2.0
github.com/go-ini/ini v1.33.0 // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/google/go-cmp v0.5.1 // indirect
github.com/google/gopacket v1.1.16
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f // indirect
github.com/gorilla/mux v1.6.1
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
github.com/hashicorp/go-cleanhttp v0.0.0-20171218145408-d5fe4b57a186 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 // indirect
github.com/mattn/go-colorable v0.0.9 // indirect
github.com/mattn/go-isatty v0.0.3 // indirect
github.com/mdlayher/raw v0.0.0-20181016155347-fa5ef3332ca9 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
github.com/miekg/dns v1.0.4
github.com/onsi/ginkgo v1.14.0 // indirect
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/opencontainers/runc v0.1.1 // indirect
github.com/opencontainers/selinux v1.6.0 // indirect
github.com/pkg/errors v0.9.1
github.com/pkg/profile v1.2.1
github.com/prometheus/client_golang v1.7.1
github.com/sirupsen/logrus v1.4.2
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/spf13/cobra v0.0.1
github.com/stretchr/testify v1.4.0
github.com/vishvananda/netlink v1.0.0
github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936
github.com/weaveworks/common v0.0.0-20180321110636-ebab3a78900a
github.com/weaveworks/go-checkpoint v0.0.0-20170503165305-ebbb8b0518ab
github.com/weaveworks/go-odp v0.0.0-20181017121109-6b0aa22550d9
github.com/weaveworks/mesh v0.0.0-20191105120815-58dbcc3e8e63
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384
gopkg.in/ini.v1 v1.57.0 // indirect
gotest.tools v2.2.0+incompatible // indirect
k8s.io/api v0.18.6
k8s.io/apimachinery v0.18.6
k8s.io/client-go v0.18.6
)
+411
View File
@@ -0,0 +1,411 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Microsoft/go-winio v0.4.7 h1:vOvDiY/F1avSWlCWiKJjdYKz2jVjTK3pWPHndeG4OAY=
github.com/Microsoft/go-winio v0.4.7/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andybalholm/go-bit v0.0.0-20150501193155-34813fe0e46a h1:yE4/B7ng2G9tr5DdT/x2bj3u6p3Rze2Ha/61eChret8=
github.com/andybalholm/go-bit v0.0.0-20150501193155-34813fe0e46a/go.mod h1:xPmFQkJW5/HS/ZMM6soMdODwdIOO9zs3yAhksnFQJE0=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aws/aws-sdk-go v1.13.22 h1:S18o71mCjRUw9bZzw61k2xjZx3/XtzwJKdAXx5CUf6s=
github.com/aws/aws-sdk-go v1.13.22/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/containerd/continuity v0.0.0-20180322171221-3e8f2ea4b190 h1:xySrq2Xw0gX07PHM/LS8kuGpRd3hKDz+0/QvIJRILYk=
github.com/containerd/continuity v0.0.0-20180322171221-3e8f2ea4b190/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containernetworking/cni v0.5.2 h1:/nFPNGJQu4yiNvXxH31qL05FIyGG5Y/p0YxuUutl+PE=
github.com/containernetworking/cni v0.5.2/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/coreos/go-iptables v0.3.0 h1:UTQkjHl9rPwwtXZhXbY3T932cV9aUnKlSsZ7YGfJVXM=
github.com/coreos/go-iptables v0.3.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible h1:W1rhCpxfWMU0CaZSFWpmWfmB68zYZVksig+VC1ZbgI4=
github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v17.12.0-ce-rc1.0.20180328155642-38588656727d+incompatible h1:C81UCfrC3AgecXLr1vYezUVtYqTPlizDRO67F/lRU2U=
github.com/docker/docker v17.12.0-ce-rc1.0.20180328155642-38588656727d+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.3.0 h1:3lOnM9cSzgGwx8VfK/NGOW5fLQ0GjIlCkaktF+n1M6o=
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.2 h1:Kjm80apys7gTtfVmCvVY8gwu10uofaFSrmAKOVrtueE=
github.com/docker/go-units v0.3.2/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/libnetwork v0.8.0-dev.2.0.20180212220201-119badbd737b h1:u7WZJnaLG9o39ZmpCJEwuFM6nCBuUQL0y/AbyE5sbaM=
github.com/docker/libnetwork v0.8.0-dev.2.0.20180212220201-119badbd737b/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
github.com/docker/machine v0.14.0 h1:7zMwMAz0XbL27Q4NPqtW7I0wuhOaGFpq5WfvrUfZROM=
github.com/docker/machine v0.14.0/go.mod h1:I8mPNDeK1uH+JTcUU7X0ZW8KiYz0jyAgNaeSJ1rCfDI=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsouza/go-dockerclient v1.2.0 h1:lmjnUbZFR+De5PfuXCk62hAIlkokNtD9CaGPR8Iu5UU=
github.com/fsouza/go-dockerclient v1.2.0/go.mod h1:KpcjM623fQYE9MZiTGzKhjfxXAV9wbyX2C1cyRHfhl0=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-ini/ini v1.33.0 h1:/0Y2X+/6jgfPYl2LOihvxikDfznXMufz0Zkr3mW+7Zg=
github.com/go-ini/ini v1.33.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gopacket v1.1.16 h1:u6Afvia5C5srlLcbTwpHaFW918asLYPxieziOaWwz8M=
github.com/google/gopacket v1.1.16/go.mod h1:UCLx9mCmAwsVbn6qQl1WIEt2SO7Nd2fD0th1TBAsqBw=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI=
github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f h1:9oNbS1z4rVpbnkHBdPZU4jo9bSmrLpII768arSyMFgk=
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.1 h1:KOwqsTYZdeuMacU7CxjMNYEKeBvLbxW+psodrbcEa3A=
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/hashicorp/go-cleanhttp v0.0.0-20171218145408-d5fe4b57a186 h1:URgjUo+bs1KwatoNbwG0uCO4dHN4r1jsp4a5AGgHRjo=
github.com/hashicorp/go-cleanhttp v0.0.0-20171218145408-d5fe4b57a186/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56 h1:742eGXur0715JMq73aD95/FU0XpVKXqNuTnEfXsLOYQ=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8 h1:12VvqtR6Aowv3l/EQUlocDHW2Cp4G9WJVH7uyH8QFJE=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mdlayher/raw v0.0.0-20181016155347-fa5ef3332ca9 h1:tOtO8DXiNGj9NshRKHWiZuGlSldPFzFCFYhNtsKTBCs=
github.com/mdlayher/raw v0.0.0-20181016155347-fa5ef3332ca9/go.mod h1:rC/yE65s/DoHB6BzVOUBNYBGTg772JVytyAytffIZkY=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.0.4 h1:Ec3LTJwwzqT1++63P12fhtdEbQhtPE7TBdD6rlhqrMM=
github.com/miekg/dns v1.0.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/selinux v1.6.0 h1:+bIAS/Za3q5FTwWym4fTB0vObnfCf3G/NC7K6Jx62mY=
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1 h1:F++O52m40owAmADcojzM+9gyjmMOY/T4oYJkgFDH8RE=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cobra v0.0.1 h1:zZh3X5aZbdnoj+4XkaBxKfhO4ot82icYdhhREIAXIj8=
github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM=
github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936 h1:J9gO8RJCAFlln1jsvRba/CWVUnMHwObklfxxjErl1uk=
github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
github.com/weaveworks/common v0.0.0-20180321110636-ebab3a78900a h1:dIOYWkmKCq9tU3DY96p1D/8xXFWkqt9Jd1ipu6sTLSk=
github.com/weaveworks/common v0.0.0-20180321110636-ebab3a78900a/go.mod h1:pSm+0KR57BG3pvGoJWFXJSAC7+sEPewcvdt5StevL3A=
github.com/weaveworks/go-checkpoint v0.0.0-20170503165305-ebbb8b0518ab h1:mW+hgchD9qUUBqnuaDBj7BkcpFPk/FxeFcUFI5lvvUw=
github.com/weaveworks/go-checkpoint v0.0.0-20170503165305-ebbb8b0518ab/go.mod h1:qkbvw5GPibQ/Nf7IZJL0UoLwmJ6858b4S/hUWRd+cH4=
github.com/weaveworks/go-odp v0.0.0-20181017121109-6b0aa22550d9 h1:7OqrOqOJkneFGUT7CoR3uZnZP3ZyuUtzWNfv7GIc3RE=
github.com/weaveworks/go-odp v0.0.0-20181017121109-6b0aa22550d9/go.mod h1:6/WClQKiVm/SQf6WJXv49l+9K9ONE2U8DYpeXEk3X7k=
github.com/weaveworks/mesh v0.0.0-20191105120815-58dbcc3e8e63 h1:s0fUBZ8Vhtc3ruFmLIr3qVTQUb/j6ySkPLHoKKitHeM=
github.com/weaveworks/mesh v0.0.0-20191105120815-58dbcc3e8e63/go.mod h1:RZebXKv56dax5zXcLIJZm1Awk28sx0XODXF94Z8WssY=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243 h1:R43TdZy32XXSXjJn7M/HhALJ9imq6ztLnChfYJpVDnM=
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc h1:c0o/qxkaO2LF5t6fQrT4b5hzyggAkLLlCUjqfRxd8Q4=
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww=
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.18.6 h1:osqrAXbOQjkKIWDTjrqxWQ3w0GkKb1KA1XkUGHHYpeE=
k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI=
k8s.io/apimachinery v0.18.6 h1:RtFHnfGNfd1N0LeSrKCUznz5xtUP1elRGvHJbL3Ntag=
k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
k8s.io/client-go v0.18.6 h1:I+oWqJbibLSGsZj8Xs8F0aWVXJVIoUHWaaJV3kUN/Zw=
k8s.io/client-go v0.18.6/go.mod h1:/fwtGLjYMS1MaM5oi+eXhKwG+1UHidUEXRh6cNsdO0Q=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6 h1:Oh3Mzx5pJ+yIumsAD0MOECPVeXsVot0UkiaCGVyfGQY=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
-15
View File
@@ -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
func (alloc *Allocator) cancelOps(ops *[]operation) {
for _, op := range *ops {
-2
View File
@@ -17,8 +17,6 @@ import (
const (
testStart1 = "10.0.1.0"
testStart2 = "10.0.2.0"
testStart3 = "10.0.3.0"
)
func returnFalse() bool { return false }
+10 -9
View File
@@ -1,6 +1,7 @@
package ipam
import (
"context"
"encoding/json"
"fmt"
"net/http"
@@ -41,7 +42,7 @@ func writeAddresses(w http.ResponseWriter, cidrs []address.CIDR) {
}
}
func hasBeenCancelled(dockerCli *docker.Client, closedChan <-chan bool, ident string, checkAlive bool) func() bool {
func hasBeenCancelled(dockerCli *docker.Client, closedChan <-chan struct{}, ident string, checkAlive bool) func() bool {
return func() bool {
select {
case <-closedChan:
@@ -63,9 +64,9 @@ func cancellationErr(w http.ResponseWriter, err error) bool {
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,
hasBeenCancelled(dockerCli, w.(http.CloseNotifier).CloseNotify(), ident, checkAlive))
hasBeenCancelled(dockerCli, ctx.Done(), ident, checkAlive))
if err != nil {
if !cancellationErr(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)
}
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,
hasBeenCancelled(dockerCli, w.(http.CloseNotifier).CloseNotify(), ident, checkAlive))
hasBeenCancelled(dockerCli, ctx.Done(), ident, checkAlive))
if err != nil {
if !cancellationErr(w, 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"]
checkAlive := r.FormValue("check-alive") == "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) {
vars := mux.Vars(r)
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) {
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) {
@@ -203,6 +204,6 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID
if alloc.tracker != nil {
tracker = alloc.tracker.String()
}
fmt.Fprintf(w, tracker)
fmt.Fprintln(w, tracker)
})
}
+4 -1
View File
@@ -1,6 +1,7 @@
package ipam
import (
"context"
"fmt"
"io"
"io/ioutil"
@@ -158,11 +159,13 @@ func TestHTTPCancel(t *testing.T) {
// Ask the http server for a new address
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
go func() {
time.Sleep(100 * time.Millisecond)
common.Log.Debug("Cancelling allocate")
http.DefaultTransport.(*http.Transport).CancelRequest(req)
cancel()
}()
res, _ := http.DefaultClient.Do(req)
-10
View File
@@ -56,16 +56,6 @@ func (m *Model) addLink(a, b *TestNode) {
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 {
// Number of nodes
nodeCount uint
+1 -1
View File
@@ -560,7 +560,7 @@ func (r *Ring) ChoosePeersToAskForSpace(start, end address.Address) []mesh.PeerN
break
}
// Ignore ranges with no free space
if entry.Free <= 0 {
if entry.Free == 0 {
continue
}
+2 -2
View File
@@ -73,7 +73,7 @@ func TestLowlevel(t *testing.T) {
// test Donate when addresses are scarce
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")
s.Add(0, 3)
require.NoError(t, s.Claim(0))
@@ -81,7 +81,7 @@ func TestLowlevel(t *testing.T) {
r, ok = s.Donate(address.NewRange(0, 1000))
require.True(t, ok, "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")
}
-25
View File
@@ -24,14 +24,6 @@ func (m *mockMessage) String() string {
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 {
sync.RWMutex
*testing.T
@@ -100,14 +92,6 @@ func (m *mockGossipComms) GossipUnicast(dstPeerName mesh.PeerName, buf []byte) e
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) {
m := alloc.gossip.(*mockGossipComms)
m.Lock()
@@ -208,15 +192,6 @@ func AssertNothingSent(t *testing.T, ch <-chan bool) {
}
}
func AssertNothingSentErr(t *testing.T, ch <-chan error) {
select {
case val := <-ch:
require.FailNow(t, fmt.Sprintf("Unexpected value on channel: %v", val))
default:
// no message received
}
}
func makeNetworkOfAllocators(size int, cidr string, preClaims ...[]PreClaim) ([]*Allocator, *gossip.TestRouter, address.CIDR) {
gossipRouter := gossip.NewTestRouter(0.0)
allocs := make([]*Allocator, size)
+1 -1
View File
@@ -84,7 +84,7 @@ func NewAWSVPCTracker(bridgeName string) (*AWSVPCTracker, error) {
func (t *AWSVPCTracker) HandleUpdate(prevRanges, currRanges []address.Range, local bool) error {
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
// because of the 50 routes limit. However, in such case a container might
-52
View File
@@ -1,52 +0,0 @@
package tracker
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/weaveworks/weave/net/address"
)
var (
r0to127 = cidr("10.0.0.0", "10.0.0.127")
r128to255 = cidr("10.0.0.128", "10.0.0.255")
r0to255 = cidr("10.0.0.0", "10.0.0.255")
r1dot0to255 = cidr("10.0.1.0", "10.0.1.255")
r2dot0to255 = cidr("10.0.2.0", "10.0.2.255")
)
func TestRemoveCommon(t *testing.T) {
a := []address.CIDR{r0to127, r1dot0to255}
b := []address.CIDR{r1dot0to255, r2dot0to255}
newA, newB := RemoveCommon(a, b)
require.Equal(t, []address.CIDR{r0to127}, newA)
require.Equal(t, []address.CIDR{r2dot0to255}, newB)
}
func TestMerge(t *testing.T) {
ranges := []address.Range{
r0to127.Range(),
r128to255.Range(),
r2dot0to255.Range(),
}
require.Equal(t, []address.Range{r0to255.Range(), r2dot0to255.Range()}, Merge(ranges))
}
// Helper
// TODO(mp) DRY with helpers of other tests.
func ip(s string) address.Address {
addr, _ := address.ParseIP(s)
return addr
}
// [start; end]
func cidr(start, end string) address.CIDR {
c := address.Range{Start: ip(start), End: ip(end) + 1}.CIDRs()
if len(c) != 1 {
panic("invalid cidr")
}
return c[0]
}
+5 -1
View File
@@ -90,7 +90,7 @@ type DNSServer struct {
ns *Nameserver
domain string
ttl uint32
address string
address string // listen address and port, e.g. 1.2.3.4:53
servers []*dns.Server
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) {
if _, _, err := net.SplitHostPort(address); err != nil {
return nil, fmt.Errorf("invalid DNS listen address %q: %v", address, err)
}
s := &DNSServer{
ns: ns,
domain: dns.Fqdn(domain),
-2
View File
@@ -41,9 +41,7 @@ func TestTruncation(t *testing.T) {
defer dnsserver.Stop()
// Add 100 mappings to nameserver
addrs := []address.Address{}
for i := address.Address(0); i < 100; i++ {
addrs = append(addrs, i)
nameserver.AddEntry("foo.weave.local.", "", mesh.UnknownPeerName, i)
}
+11
View File
@@ -3,6 +3,7 @@ package nameserver
import (
"encoding/json"
"fmt"
"net"
"net/http"
"github.com/gorilla/mux"
@@ -84,3 +85,13 @@ func (n *Nameserver) HandleHTTP(router *mux.Router, dockerCli *docker.Client) {
}
})
}
func (d *DNSServer) HandleHTTP(router *mux.Router) {
router.Methods("GET").Path("/dns-address-port").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, d.address)
})
router.Methods("GET").Path("/dns-address").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
host, _, _ := net.SplitHostPort(d.address) // address is validated in NewDNSServer()
fmt.Fprint(w, host)
})
}
@@ -1,13 +1,9 @@
package tracker
import (
"github.com/weaveworks/weave/net/address"
)
package 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
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 {
@@ -22,7 +18,7 @@ func Merge(r []address.Range) []address.Range {
// RemoveCommon filters out CIDR ranges which are contained in both a and b slices.
// Both slices have to be sorted in increasing order.
func RemoveCommon(a, b []address.CIDR) (newA, newB []address.CIDR) {
func RemoveCommon(a, b []CIDR) (newA, newB []CIDR) {
i, j := 0, 0
for i < len(a) && j < len(b) {
+43
View File
@@ -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]
}
+8
View File
@@ -41,3 +41,11 @@ func sysctl(procPath, variable, value string) error {
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
}
+84 -45
View File
@@ -11,14 +11,12 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
"k8s.io/apimachinery/pkg/types"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/common/chains"
"github.com/weaveworks/weave/common/odp"
"github.com/weaveworks/weave/ipam/tracker"
"github.com/weaveworks/weave/net/address"
"github.com/weaveworks/weave/net/ipset"
"github.com/weaveworks/weave/npc"
)
/* This code implements three possible configurations to connect
@@ -63,10 +61,10 @@ const (
)
type Bridge interface {
init(config *BridgeConfig) error // create and initialise bridge device(s)
attach(veth *netlink.Veth) error // attach veth to bridge
IsFastdp() bool // does this bridge use fastdp?
String() string // human-readable type string
init(procPath string, config *BridgeConfig) error // create and initialise bridge device(s)
attach(veth *netlink.Veth) error // attach veth to bridge
IsFastdp() bool // does this bridge use fastdp?
String() string // human-readable type string
}
// Used to indicate a fallback to the Bridge type
@@ -221,6 +219,7 @@ type BridgeConfig struct {
MTU int
Mac string
Port int
ControlPort string
NoMasqLocal bool
}
@@ -250,7 +249,7 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
}
for {
if err := bridgeType.init(config); err != nil {
if err := bridgeType.init(procPath, config); err != nil {
if errors.Cause(err) == errBridgeNotSupported {
log.Warnf("Skipping bridge creation of %q due to: %s", bridgeType, err)
bridgeType = bridgeImpl{}
@@ -261,7 +260,7 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
break
}
if err := configureIPTables(config, ips); err != nil {
if err := ConfigureIPTables(config, ips); err != nil {
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")
}
}
// 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 {
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)
}
// NB: No concurrent call to Expose is possible, as EnsureBridge is called
// before any service has been started.
if err := reexpose(config, log); err != nil {
if err := Reexpose(config, log); err != nil {
return bridgeType, err
}
@@ -345,11 +346,11 @@ func (b bridgeImpl) initPrep(config *BridgeConfig) error {
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 {
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)
}); err != nil {
return errors.Wrap(err, "creating pcap veth pair")
@@ -361,7 +362,7 @@ func (b bridgeImpl) init(config *BridgeConfig) error {
return nil
}
func (f fastdpImpl) init(config *BridgeConfig) error {
func (f fastdpImpl) init(procPath string, config *BridgeConfig) error {
odpSupported, err := odp.CreateDatapath(f.datapathName)
if !odpSupported {
msg := ""
@@ -392,14 +393,14 @@ func (f fastdpImpl) init(config *BridgeConfig) error {
return nil
}
func (bf bridgedFastdpImpl) init(config *BridgeConfig) error {
if err := bf.fastdpImpl.init(config); err != nil {
func (bf bridgedFastdpImpl) init(procPath string, config *BridgeConfig) error {
if err := bf.fastdpImpl.init(procPath, config); err != nil {
return err
}
if err := bf.bridgeImpl.initPrep(config); err != nil {
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 {
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)
}
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()
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!
@@ -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 {
// 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
}
// 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
}
fwdRules = append(fwdRules,
@@ -482,11 +525,11 @@ func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
// ACCEPT in WEAVE-NPC-EGRESS chain
{"-i", config.WeaveBridgeName,
"-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
{"-o", config.WeaveBridgeName,
"-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, "-j", "DROP"},
}...)
@@ -498,8 +541,8 @@ func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
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 := ensureChains(ipt, "filter", "WEAVE-EXPOSE"); err != nil {
return errors.Wrap(err, "failed to ensure existence of filter/WEAVE-EXPOSE chain")
}
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
if err := ipt.ClearChain("nat", "WEAVE"); err != nil {
return errors.Wrap(err, "failed to clear/create nat/WEAVE chain")
if err := ensureChains(ipt, "nat", "WEAVE"); err != nil {
return errors.Wrap(err, "failed to ensure existence of nat/WEAVE chain")
}
if err := ipt.AppendUnique("nat", "POSTROUTING", "-j", "WEAVE"); err != nil {
return err
}
// For the cases where the weave bridge is the default gateway for
// containers (e.g. Kubernetes): create the ipset to store CIDRs allocated
// by IPAM for local containers. In the case of Kubernetes, external traffic
// sent to these CIDRs avoids SNAT'ing so that NodePort with
// `"externalTrafficPolicy":"Local"` would receive packets with correct
// src IP addr.
// containers (e.g. Kubernetes): In `ResetIPTables` (which we assume
// to have been called at this point) we create an ipset to store CIDRs
// allocated by IPAM for local containers.
// In the case of Kubernetes, external traffic sent to these CIDRs
// avoids SNAT'ing so that NodePort with `"externalTrafficPolicy":"Local"`
// would receive packets with correct src IP addr.
if config.NoMasqLocal {
ips := ipset.New(common.LogLogger(), 0)
_ = ips.Destroy(NoMasqLocalIpset)
if err := ips.Create(NoMasqLocalIpset, ipset.HashNet); err != nil {
return err
}
if err := ipt.Insert("nat", "WEAVE", 1,
if err := ipt.AppendUnique("nat", "WEAVE",
"-m", "set", "--match-set", string(NoMasqLocalIpset), "dst",
"-m", "comment", "--comment", "Prevent SNAT to locally running containers",
"-j", "RETURN"); err != nil {
@@ -547,13 +586,13 @@ func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
type NoMasqLocalTracker struct {
ips ipset.Interface
owner types.UID
owner ipset.UID
}
func NewNoMasqLocalTracker(ips ipset.Interface) *NoMasqLocalTracker {
return &NoMasqLocalTracker{
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
}
prev, curr := tracker.RemoveCommon(
address.NewCIDRs(tracker.Merge(prevRanges)),
address.NewCIDRs(tracker.Merge(currRanges)))
prev, curr := address.RemoveCommon(
address.NewCIDRs(address.Merge(prevRanges)),
address.NewCIDRs(address.Merge(currRanges)))
for _, cidr := range curr {
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)
}
func reexpose(config *BridgeConfig, log *logrus.Logger) error {
func Reexpose(config *BridgeConfig, log *logrus.Logger) error {
// Get existing IP addrs of the weave bridge.
// If the bridge hasn't been exposed, then this functions does nothing.
//
+2 -7
View File
@@ -103,13 +103,8 @@ func addNatRule(ipt *iptables.IPTables, rulespec ...string) error {
// Loop until we get an exit code other than "temporarily unavailable"
for {
if err := ipt.AppendUnique("nat", "WEAVE", rulespec...); err != nil {
if ierr, ok := err.(*iptables.Error); ok {
if status, ok := ierr.ExitError.Sys().(syscall.WaitStatus); ok {
// (magic exit code 4 found in iptables source code; undocumented)
if status.ExitStatus() == 4 {
continue
}
}
if isResourceError(err) {
continue
}
return err
}
+9 -21
View File
@@ -85,7 +85,7 @@ func New(log *logrus.Logger) (*IPSec, error) {
// InitSALocal initializes inbound ipsec from remotePeer and triggers
// 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
spiID := getSPIId(remotePeer, localPeer, connUID)
@@ -95,17 +95,17 @@ func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uin
// Derive SA key
nonce, err := genNonce()
if err != nil {
return errors.Wrap(err, "generate nonce")
return nil, errors.Wrap(err, "generate nonce")
}
key, err := deriveKey(sessionKey[:], nonce, localPeer)
if err != nil {
return errors.Wrap(err, "derive key")
return nil, errors.Wrap(err, "derive key")
}
// Allocate SA
sa, err := netlink.XfrmStateAllocSpi(xfrmAllocSpiState(remoteIP, localIP))
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
@@ -117,28 +117,24 @@ func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uin
// Create SA
if sa, err := xfrmState(remoteIP, localIP, spi, false, key); 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 {
return errors.Wrap(err, "new xfrm state (in)")
return nil, errors.Wrap(err, "new xfrm state (in)")
}
// Install iptables rules
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}
ipsec.spiInfo[spiID] = 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}
if err := initRemote(msg.serialize()); err != nil {
return errors.Wrap(err, "send InitSARemote")
}
return nil
return msg.serialize(), nil
}
// InitSARemote initializes outbound ipsec to remotePeer.
@@ -434,14 +430,6 @@ func (ipsec *IPSec) removeDropNonEncrypted(srcIP, dstIP net.IP, udpPort int, inS
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
func xfrmAllocSpiState(srcIP, dstIP net.IP) *netlink.XfrmState {
+46 -17
View File
@@ -7,26 +7,31 @@ import (
"log"
"os/exec"
"strings"
"time"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/types"
)
type Name string
type Type string
type UID string
const (
ListSet = Type("list:set")
HashIP = Type("hash:ip")
HashNet = Type("hash:net")
DestroyRetrySleepMs = 100
)
type Interface interface {
Create(ipsetName Name, ipsetType Type) error
AddEntry(user types.UID, ipsetName Name, entry string, comment string) error
DelEntry(user types.UID, ipsetName Name, entry string) error
Exist(user types.UID, ipsetName Name, entry string) bool
AddEntry(user UID, ipsetName Name, entry string, comment string) error
DelEntry(user UID, ipsetName Name, entry string) error
EntryExists(user UID, ipsetName Name, entry string) bool
Exists(ipsetName Name) (bool, error)
Flush(ipsetName Name) error
Destroy(ipsetName Name) error
@@ -49,7 +54,7 @@ type ipset struct {
// There might be multiple users for the same ipset & entry pair because
// events from k8s API server might be out of order causing duplicate IPs:
// https://github.com/weaveworks/weave/issues/2792.
users map[entryKey]map[types.UID]struct{}
users map[entryKey]map[UID]struct{}
}
func New(logger *log.Logger, maxListSize int) Interface {
@@ -57,7 +62,7 @@ func New(logger *log.Logger, maxListSize int) Interface {
Logger: logger,
enableComments: true,
maxListSize: maxListSize,
users: make(map[entryKey]map[types.UID]struct{}),
users: make(map[entryKey]map[UID]struct{}),
}
// Check for comment support
@@ -93,7 +98,7 @@ func (i *ipset) Create(ipsetName Name, ipsetType Type) error {
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)
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...)
}
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)
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)
}
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)
}
// 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 {
i.removeSetFromUsers(ipsetName)
return doExec("flush", string(ipsetName))
}
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")
}
func (i *ipset) Destroy(ipsetName Name) error {
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 {
i.users = make(map[entryKey]map[types.UID]struct{})
return doExec("destroy")
i.users = make(map[entryKey]map[UID]struct{})
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
@@ -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).
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}
add := false
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 {
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).
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}
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)
}
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]
return ok
}
+120
View File
@@ -2,9 +2,13 @@ package net
import (
"strings"
"syscall"
"time"
"github.com/coreos/go-iptables/iptables"
"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.
@@ -104,3 +108,119 @@ func ensureRulesAtTop(table, chain string, rulespecs [][]string, ipt *iptables.I
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
View File
@@ -55,9 +55,9 @@ func WithNetNSByPath(path string, work func() error) error {
}
func NSPathByPid(pid int) string {
return NSPathByPidWithRoot("/", pid)
return NSPathByPidWithProc("/proc", pid)
}
func NSPathByPidWithRoot(root string, pid int) string {
return filepath.Join(root, fmt.Sprintf("/proc/%d/ns/net", pid))
func NSPathByPidWithProc(procPath string, pid int) string {
return filepath.Join(procPath, fmt.Sprint(pid), "/ns/net")
}
+17 -8
View File
@@ -13,7 +13,7 @@ import (
)
// 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)
if err != nil {
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 {
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 err := EthtoolTXOff(veth.PeerName); err != nil {
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 {
// AttachContainer expects to be called in host pid namespace
const procPath = "/proc"
ns, err := netns.GetFromPath(netNSPath)
if err != nil {
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
}
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 {
return fmt.Errorf("failed to move veth to container netns: %s", err)
}
if err := WithNetNS(ns, func() error {
return setupIface(peerName, ifName)
return setupIface(procPath, peerName, ifName)
}); err != nil {
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
func setupIface(ifaceName, newIfName string) error {
func setupIface(procPath, ifaceName, newIfName string) error {
ipt, err := iptables.New()
if err != nil {
return err
@@ -219,15 +229,14 @@ func setupIface(ifaceName, newIfName string) error {
if err := netlink.LinkSetName(link, newIfName); err != nil {
return err
}
// This is only called by AttachContainer which is only called in host pid namespace
if err := configureARPCache("/proc", newIfName); err != nil {
if err := configureARPCache(procPath, newIfName); err != nil {
return err
}
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
func ConfigureARP(prefix, rootPath string) error {
func ConfigureARP(prefix, procPath string) error {
links, err := netlink.LinkList()
if err != nil {
return err
@@ -235,7 +244,7 @@ func ConfigureARP(prefix, rootPath string) error {
for _, link := range links {
ifName := link.Attrs().Name
if strings.HasPrefix(ifName, prefix) {
configureARPCache(rootPath+"/proc", ifName)
configureARPCache(procPath, ifName)
if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil {
for _, addr := range addrs {
arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName)
+1 -10
View File
@@ -2,16 +2,7 @@ package npc
const (
TableFilter = "filter"
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"
EgressMark = "0x40000/0x40000"
IpsetNamePrefix = "weave-"
+51 -38
View File
@@ -1,6 +1,7 @@
package npc
import (
"context"
"fmt"
"sync"
@@ -12,22 +13,23 @@ import (
"k8s.io/client-go/kubernetes"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/common/chains"
"github.com/weaveworks/weave/net/ipset"
"github.com/weaveworks/weave/npc/iptables"
)
type NetworkPolicyController interface {
AddNamespace(ns *coreapi.Namespace) error
UpdateNamespace(oldObj, newObj *coreapi.Namespace) error
DeleteNamespace(ns *coreapi.Namespace) error
AddNamespace(ctx context.Context, ns *coreapi.Namespace) error
UpdateNamespace(ctx context.Context, oldObj, newObj *coreapi.Namespace) error
DeleteNamespace(ctx context.Context, ns *coreapi.Namespace) error
AddPod(obj *coreapi.Pod) error
UpdatePod(oldObj, newObj *coreapi.Pod) error
DeletePod(obj *coreapi.Pod) error
AddPod(ctx context.Context, obj *coreapi.Pod) error
UpdatePod(ctx context.Context, oldObj, newObj *coreapi.Pod) error
DeletePod(ctx context.Context, obj *coreapi.Pod) error
AddNetworkPolicy(obj interface{}) error
UpdateNetworkPolicy(oldObj, newObj interface{}) error
DeleteNetworkPolicy(obj interface{}) error
AddNetworkPolicy(ctx context.Context, obj interface{}) error
UpdateNetworkPolicy(ctx context.Context, oldObj, newObj interface{}) error
DeleteNetworkPolicy(ctx context.Context, obj interface{}) error
}
type controller struct {
@@ -60,9 +62,9 @@ func New(nodeName string, ipt iptables.Interface, ips ipset.Interface, clientset
func (npc *controller) onNewNsSelector(selector *selector) error {
for _, ns := range npc.nss {
if ns.namespace != nil {
if selector.matchesNamespaceSelector(ns.namespace.ObjectMeta.Labels) {
if err := selector.addEntry(ns.namespace.ObjectMeta.UID, string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil {
if ns.namespaceUID != "" {
if selector.matchesNamespaceSelector(ns.namespaceLabels) {
if err := selector.addEntry(ns.namespaceUID, string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil {
return err
}
}
@@ -73,11 +75,11 @@ func (npc *controller) onNewNsSelector(selector *selector) error {
func (npc *controller) onNewNamespacePodsSelector(selector *selector) error {
for _, ns := range npc.nss {
if ns.namespace != nil && len(ns.pods) > 0 {
if ns.namespaceUID != "" && len(ns.pods) > 0 {
for _, pod := range ns.pods {
if hasIP(pod) {
if selector.matchesNamespacedPodSelector(pod.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels) {
if err := selector.addEntry(pod.ObjectMeta.UID, pod.Status.PodIP, podComment(pod)); err != nil {
if selector.matchesNamespacedPodSelector(pod.ObjectMeta.Labels, ns.namespaceLabels) {
if err := selector.addEntry(uid(pod), pod.Status.PodIP, podComment(pod)); err != nil {
return err
}
@@ -89,10 +91,10 @@ func (npc *controller) onNewNamespacePodsSelector(selector *selector) error {
return nil
}
func (npc *controller) withNS(name string, f func(ns *ns) error) error {
func (npc *controller) withNS(ctx context.Context, name string, f func(ns *ns) error) error {
ns, found := npc.nss[name]
if !found {
namespace, err := npc.clientset.CoreV1().Namespaces().Get(name, metav1.GetOptions{})
namespace, err := npc.clientset.CoreV1().Namespaces().Get(ctx, name, metav1.GetOptions{})
if err != nil {
return err
}
@@ -115,37 +117,37 @@ func (npc *controller) withNS(name string, f func(ns *ns) error) error {
return nil
}
func (npc *controller) AddPod(obj *coreapi.Pod) error {
func (npc *controller) AddPod(ctx context.Context, obj *coreapi.Pod) error {
npc.Lock()
defer npc.Unlock()
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")
})
}
func (npc *controller) UpdatePod(oldObj, newObj *coreapi.Pod) error {
func (npc *controller) UpdatePod(ctx context.Context, oldObj, newObj *coreapi.Pod) error {
npc.Lock()
defer npc.Unlock()
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")
})
}
func (npc *controller) DeletePod(obj *coreapi.Pod) error {
func (npc *controller) DeletePod(ctx context.Context, obj *coreapi.Pod) error {
npc.Lock()
defer npc.Unlock()
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")
})
}
func (npc *controller) AddNetworkPolicy(obj interface{}) error {
func (npc *controller) AddNetworkPolicy(ctx context.Context, obj interface{}) error {
npc.Lock()
defer npc.Unlock()
@@ -156,12 +158,15 @@ func (npc *controller) AddNetworkPolicy(obj interface{}) error {
return err
}
if egressNetworkPolicy {
npc.defaultEgressDrop = true
if err := npc.ipt.Append(TableFilter, EgressChain,
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 {
npc.defaultEgressDrop = false
return fmt.Errorf("Failed to add iptable rule to drop egress traffic from the pods by default due to %s", err.Error())
}
npc.defaultEgressDrop = true
}
}
@@ -170,12 +175,12 @@ func (npc *controller) AddNetworkPolicy(obj interface{}) error {
return err
}
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")
})
}
func (npc *controller) UpdateNetworkPolicy(oldObj, newObj interface{}) error {
func (npc *controller) UpdateNetworkPolicy(ctx context.Context, oldObj, newObj interface{}) error {
npc.Lock()
defer npc.Unlock()
@@ -185,12 +190,12 @@ func (npc *controller) UpdateNetworkPolicy(oldObj, newObj interface{}) error {
}
common.Log.Infof("EVENT UpdateNetworkPolicy %s %s", js(oldObj), js(newObj))
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")
})
}
func (npc *controller) DeleteNetworkPolicy(obj interface{}) error {
func (npc *controller) DeleteNetworkPolicy(ctx context.Context, obj interface{}) error {
npc.Lock()
defer npc.Unlock()
@@ -200,37 +205,37 @@ func (npc *controller) DeleteNetworkPolicy(obj interface{}) error {
}
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")
})
}
func (npc *controller) AddNamespace(obj *coreapi.Namespace) error {
func (npc *controller) AddNamespace(ctx context.Context, obj *coreapi.Namespace) error {
npc.Lock()
defer npc.Unlock()
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")
})
}
func (npc *controller) UpdateNamespace(oldObj, newObj *coreapi.Namespace) error {
func (npc *controller) UpdateNamespace(ctx context.Context, oldObj, newObj *coreapi.Namespace) error {
npc.Lock()
defer npc.Unlock()
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")
})
}
func (npc *controller) DeleteNamespace(obj *coreapi.Namespace) error {
func (npc *controller) DeleteNamespace(ctx context.Context, obj *coreapi.Namespace) error {
npc.Lock()
defer npc.Unlock()
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")
})
}
@@ -262,3 +267,11 @@ func isEgressNetworkPolicy(obj interface{}) (bool, error) {
}
return false, errInvalidNetworkPolicyObjType
}
func uid(pod *coreapi.Pod) ipset.UID {
return ipset.UID(pod.UID)
}
func nsuid(ns *coreapi.Namespace) ipset.UID {
return ipset.UID(ns.UID)
}
+113 -93
View File
@@ -1,6 +1,7 @@
package npc
import (
"context"
"fmt"
"log"
"strings"
@@ -8,11 +9,11 @@ import (
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
"github.com/weaveworks/weave/common/chains"
"github.com/weaveworks/weave/net/ipset"
coreapi "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/kubernetes/fake"
)
@@ -20,7 +21,7 @@ import (
type mockSet struct {
name ipset.Name
setType ipset.Type
subSets map[string]map[types.UID]bool
subSets map[string]map[ipset.UID]bool
}
type mockIPSet struct {
@@ -35,17 +36,17 @@ func (i *mockIPSet) Create(ipsetName ipset.Name, ipsetType ipset.Type) error {
if _, ok := i.sets[string(ipsetName)]; ok {
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
}
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)
if _, ok := i.sets[string(ipsetName)]; !ok {
return errors.Errorf("%s does not exist", entry)
}
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 {
return errors.Errorf("user %s already owns entry %s", user, entry)
@@ -55,7 +56,7 @@ func (i *mockIPSet) AddEntry(user types.UID, ipsetName ipset.Name, entry string,
return nil
}
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)
if _, ok := i.sets[string(ipsetName)]; !ok {
return errors.Errorf("ipset %s does not exist", ipsetName)
@@ -72,12 +73,17 @@ func (i *mockIPSet) DelEntry(user types.UID, ipsetName ipset.Name, entry string)
return nil
}
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]
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
}
@@ -155,6 +161,7 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
sourceNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "source",
UID: "source",
Labels: map[string]string{
"app": "source",
},
@@ -164,6 +171,7 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
destinationNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "destination",
UID: "destination",
},
}
@@ -200,19 +208,20 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
// Namespaces first
m := newMockIPSet()
client := fake.NewSimpleClientset()
ctx := context.Background()
controller := New("foo", newMockIPTables(), &m, client)
client.CoreV1().Namespaces().Create(sourceNamespace)
client.CoreV1().Namespaces().Create(destinationNamespace)
client.CoreV1().Namespaces().Create(ctx, sourceNamespace, metav1.CreateOptions{})
client.CoreV1().Namespaces().Create(ctx, destinationNamespace, metav1.CreateOptions{})
const (
selectorIPSetName = "weave-I239Zp%sCvoVt*D6u=A!2]YEk"
sourceIPSetName = "weave-HboJG1fGgG]/SR%k9H#hv5e96"
)
controller.AddNamespace(sourceNamespace)
controller.AddNamespace(destinationNamespace)
controller.AddNamespace(ctx, sourceNamespace)
controller.AddNamespace(ctx, destinationNamespace)
controller.AddNetworkPolicy(networkPolicy)
controller.AddNetworkPolicy(ctx, networkPolicy)
require.Equal(t, true, len(m.sets[selectorIPSetName].subSets[sourceIPSetName]) > 0)
@@ -220,10 +229,10 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
m = newMockIPSet()
controller = New("foo", newMockIPTables(), &m, &fake.Clientset{})
controller.AddNetworkPolicy(networkPolicy)
controller.AddNetworkPolicy(ctx, networkPolicy)
controller.AddNamespace(sourceNamespace)
controller.AddNamespace(destinationNamespace)
controller.AddNamespace(ctx, sourceNamespace)
controller.AddNamespace(ctx, destinationNamespace)
require.Equal(t, true, len(m.sets[selectorIPSetName].subSets[sourceIPSetName]) > 0)
}
@@ -241,12 +250,14 @@ func TestDefaultAllow(t *testing.T) {
m := newMockIPSet()
controller := New("bar", newMockIPTables(), &m, &fake.Clientset{})
ctx := context.Background()
defaultNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
UID: "default",
},
}
controller.AddNamespace(defaultNamespace)
controller.AddNamespace(ctx, defaultNamespace)
// Should create an ipset for default-allow
require.Contains(t, m.sets, ingressDefaultAllowIPSetName)
@@ -259,11 +270,11 @@ func TestDefaultAllow(t *testing.T) {
Name: "foo",
Labels: map[string]string{"run": "foo"}},
Status: coreapi.PodStatus{PodIP: fooPodIP}}
controller.AddPod(podFoo)
controller.AddPod(ctx, podFoo)
// Should add the foo pod to default-allow
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, fooPodIP))
require.True(t, m.entryExists(egressDefaultAllowIPSetName, fooPodIP))
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, fooPodIP))
require.True(t, m.entriesExist(egressDefaultAllowIPSetName, fooPodIP))
podBar := &coreapi.Pod{
ObjectMeta: metav1.ObjectMeta{
@@ -273,13 +284,13 @@ func TestDefaultAllow(t *testing.T) {
Labels: map[string]string{"run": "bar"}},
Status: coreapi.PodStatus{PodIP: barPodIP}}
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
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, barPodIP))
require.True(t, m.entryExists(egressDefaultAllowIPSetName, barPodIP))
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, barPodIP))
require.True(t, m.entriesExist(egressDefaultAllowIPSetName, barPodIP))
// Allow access from the bar pod to the foo pod
netpol := &networkingv1.NetworkPolicy{
@@ -307,53 +318,53 @@ func TestDefaultAllow(t *testing.T) {
}},
},
}
controller.AddNetworkPolicy(netpol)
controller.AddNetworkPolicy(ctx, netpol)
// Should remove the foo pod from default-allow as the netpol selects it
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, fooPodIP))
require.False(t, m.entryExists(egressDefaultAllowIPSetName, fooPodIP))
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, barPodIP))
require.True(t, m.entryExists(egressDefaultAllowIPSetName, barPodIP))
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, fooPodIP))
require.False(t, m.entriesExist(egressDefaultAllowIPSetName, fooPodIP))
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, barPodIP))
require.True(t, m.entriesExist(egressDefaultAllowIPSetName, barPodIP))
podBarWithNewIP := *podBar
podBarWithNewIP.Status.PodIP = barPodNewIP
controller.UpdatePod(podBar, &podBarWithNewIP)
controller.UpdatePod(ctx, podBar, &podBarWithNewIP)
// Should update IP addr of the bar pod in default-allow
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, barPodIP))
require.False(t, m.entryExists(egressDefaultAllowIPSetName, barPodIP))
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, barPodNewIP))
require.True(t, m.entryExists(egressDefaultAllowIPSetName, barPodNewIP))
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, barPodIP))
require.False(t, m.entriesExist(egressDefaultAllowIPSetName, barPodIP))
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, 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
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, barPodNewIP))
require.False(t, m.entryExists(egressDefaultAllowIPSetName, barPodNewIP))
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, barPodNewIP))
require.False(t, m.entriesExist(egressDefaultAllowIPSetName, barPodNewIP))
podFooWithNewLabel := *podFoo
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
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, fooPodIP))
require.True(t, m.entryExists(egressDefaultAllowIPSetName, fooPodIP))
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, 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
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, fooPodIP))
require.False(t, m.entryExists(egressDefaultAllowIPSetName, fooPodIP))
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, 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
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, fooPodIP))
require.True(t, m.entryExists(egressDefaultAllowIPSetName, fooPodIP))
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, fooPodIP))
require.True(t, m.entriesExist(egressDefaultAllowIPSetName, fooPodIP))
controller.DeletePod(podFoo)
controller.DeletePod(ctx, podFoo)
// Should remove foo pod from default-allow
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, fooPodIP))
require.False(t, m.entryExists(egressDefaultAllowIPSetName, fooPodIP))
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, fooPodIP))
require.False(t, m.entriesExist(egressDefaultAllowIPSetName, fooPodIP))
controller.DeleteNamespace(defaultNamespace)
controller.DeleteNamespace(ctx, defaultNamespace)
// Should remove default ipset
require.NotContains(t, m.sets, ingressDefaultAllowIPSetName)
require.NotContains(t, m.sets, egressDefaultAllowIPSetName)
@@ -369,14 +380,16 @@ func TestOutOfOrderPodEvents(t *testing.T) {
m := newMockIPSet()
client := fake.NewSimpleClientset()
controller := New("qux", newMockIPTables(), &m, client)
ctx := context.Background()
defaultNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
UID: "default",
},
}
client.CoreV1().Namespaces().Create(defaultNamespace)
controller.AddNamespace(defaultNamespace)
client.CoreV1().Namespaces().Create(ctx, defaultNamespace, metav1.CreateOptions{})
controller.AddNamespace(ctx, defaultNamespace)
podFoo := &coreapi.Pod{
ObjectMeta: metav1.ObjectMeta{
@@ -385,10 +398,10 @@ func TestOutOfOrderPodEvents(t *testing.T) {
Name: "foo",
Labels: map[string]string{"run": "foo"}},
Status: coreapi.PodStatus{PodIP: podIP}}
controller.AddPod(podFoo)
controller.AddPod(ctx, 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{
ObjectMeta: metav1.ObjectMeta{
@@ -407,10 +420,10 @@ func TestOutOfOrderPodEvents(t *testing.T) {
}},
},
}
controller.AddNetworkPolicy(netpol)
controller.AddNetworkPolicy(ctx, netpol)
// Shouldn't be in default-allow as netpol above selects podFoo
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
podBar := &coreapi.Pod{
ObjectMeta: metav1.ObjectMeta{
@@ -419,28 +432,28 @@ func TestOutOfOrderPodEvents(t *testing.T) {
Name: "bar",
Labels: map[string]string{"run": "bar"}},
Status: coreapi.PodStatus{PodIP: podIP}}
controller.AddPod(podBar)
controller.AddPod(ctx, podBar)
// Should be in default-allow as no netpol selects podBar
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
require.True(t, m.Exist(podBar.ObjectMeta.UID, ingressDefaultAllowIPSetName, podIP))
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
require.True(t, m.EntryExists(uid(podBar), ingressDefaultAllowIPSetName, podIP))
// 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
controller.DeletePod(podFoo)
controller.DeletePod(podFoo)
controller.DeletePod(ctx, podFoo)
controller.DeletePod(ctx, podFoo)
// Should be in default-allow as no netpol selects podBar and podFoo removal
// 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
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
@@ -453,14 +466,16 @@ func TestNewTargetSelector(t *testing.T) {
m := newMockIPSet()
client := fake.NewSimpleClientset()
controller := New("baz", newMockIPTables(), &m, client)
ctx := context.Background()
defaultNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
UID: "default",
},
}
client.CoreV1().Namespaces().Create(defaultNamespace)
controller.AddNamespace(defaultNamespace)
client.CoreV1().Namespaces().Create(ctx, defaultNamespace, metav1.CreateOptions{})
controller.AddNamespace(ctx, defaultNamespace)
podFoo := &coreapi.Pod{
ObjectMeta: metav1.ObjectMeta{
@@ -469,9 +484,9 @@ func TestNewTargetSelector(t *testing.T) {
Name: "foo",
Labels: map[string]string{"run": "foo"}},
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{
ObjectMeta: metav1.ObjectMeta{
@@ -489,10 +504,10 @@ func TestNewTargetSelector(t *testing.T) {
}},
},
}
controller.AddNetworkPolicy(netpolBar)
controller.AddNetworkPolicy(ctx, netpolBar)
// netpolBar target selector selects podFoo
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
netpolFoo := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
@@ -510,14 +525,14 @@ func TestNewTargetSelector(t *testing.T) {
}},
},
}
controller.AddNetworkPolicy(netpolFoo)
controller.AddNetworkPolicy(ctx, netpolFoo)
controller.DeleteNetworkPolicy(netpolBar)
controller.DeleteNetworkPolicy(ctx, netpolBar)
// netpolFoo target-selects podFoo
require.False(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
controller.DeleteNetworkPolicy(netpolFoo)
require.False(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
controller.DeleteNetworkPolicy(ctx, netpolFoo)
// No netpol target-selects podFoo
require.True(t, m.entryExists(ingressDefaultAllowIPSetName, podIP))
require.True(t, m.entriesExist(ingressDefaultAllowIPSetName, podIP))
}
func TestEgressPolicyWithIPBlock(t *testing.T) {
@@ -531,19 +546,22 @@ func TestEgressPolicyWithIPBlock(t *testing.T) {
ipt := newMockIPTables()
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(defaultNamespace)
client.CoreV1().Namespaces().Create(nonDefaultNamespace)
client.CoreV1().Namespaces().Create(ctx, defaultNamespace, metav1.CreateOptions{})
client.CoreV1().Namespaces().Create(ctx, nonDefaultNamespace, metav1.CreateOptions{})
netpolFoo := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
@@ -569,16 +587,16 @@ func TestEgressPolicyWithIPBlock(t *testing.T) {
}},
},
}
err := controller.AddNetworkPolicy(netpolFoo)
err := controller.AddNetworkPolicy(ctx, netpolFoo)
require.NoError(t, err)
require.Equal(t, 2, len(m.sets[exceptIPSetName].subSets))
require.True(t, m.entryExists(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.1/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).
require.Equal(t, 2, len(ipt.rules[EgressCustomChain]))
for rule := range ipt.rules[EgressCustomChain] {
require.Equal(t, 2, len(ipt.rules[chains.EgressCustomChain]))
for rule := range ipt.rules[chains.EgressCustomChain] {
require.Contains(t, rule, "-d 192.168.48.0/24 -m set ! --match-set "+exceptIPSetName+" dst")
}
@@ -610,7 +628,7 @@ func TestEgressPolicyWithIPBlock(t *testing.T) {
}},
},
}
err = controller.AddNetworkPolicy(netpolBar)
err = controller.AddNetworkPolicy(ctx, netpolBar)
require.NoError(t, err)
require.Equal(t, 2, len(m.sets[exceptIPSetNameInNonDefault].subSets))
}
@@ -626,14 +644,16 @@ func TestIngressPolicyWithIPBlockAndPortSpecified(t *testing.T) {
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(defaultNamespace)
client.CoreV1().Namespaces().Create(ctx, defaultNamespace, metav1.CreateOptions{})
podBar := &coreapi.Pod{
ObjectMeta: metav1.ObjectMeta{
@@ -642,8 +662,8 @@ func TestIngressPolicyWithIPBlockAndPortSpecified(t *testing.T) {
Name: "bar",
Labels: map[string]string{"run": "bar"}},
Status: coreapi.PodStatus{PodIP: barPodIP}}
controller.AddPod(podBar)
defer controller.DeletePod(podBar)
controller.AddPod(ctx, podBar)
defer controller.DeletePod(ctx, podBar)
portProtocol := coreapi.ProtocolTCP
port := intstr.FromInt(80)
@@ -678,15 +698,15 @@ func TestIngressPolicyWithIPBlockAndPortSpecified(t *testing.T) {
},
}
err := controller.AddNetworkPolicy(netpolicty)
err := controller.AddNetworkPolicy(ctx, netpolicty)
require.NoError(t, err)
defer controller.DeleteNetworkPolicy(netpolicty)
defer controller.DeleteNetworkPolicy(ctx, netpolicty)
require.Equal(t, 1, len(m.sets[runBarIPSetName].subSets))
require.True(t, m.entryExists(runBarIPSetName, barPodIP))
require.True(t, m.entriesExist(runBarIPSetName, barPodIP))
require.Equal(t, 1, len(ipt.rules[IngressChain]))
for rule := range ipt.rules[IngressChain] {
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")
}
}
+5 -6
View File
@@ -6,7 +6,6 @@ import (
"strings"
networkingv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/types"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/net/ipset"
@@ -51,17 +50,17 @@ func (spec *ipBlockSpec) getRuleSpec(src bool) ([]string, string) {
type ipBlockSet struct {
ips ipset.Interface
users map[string]map[types.UID]struct{}
users map[string]map[ipset.UID]struct{}
}
func newIPBlockSet(ips ipset.Interface) *ipBlockSet {
return &ipBlockSet{
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 {
if key == "" {
continue
@@ -83,7 +82,7 @@ func (s *ipBlockSet) deprovision(user types.UID, current, desired map[string]*ip
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 {
if key == "" {
// 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{}{}
}
+9
View File
@@ -22,6 +22,12 @@ var (
},
[]string{"protocol", "dport"},
)
PolicyEnforcementErrors = prometheus.NewCounter(
prometheus.CounterOpts{
Name: "weavenpc_policy_enforcement_errors",
Help: "Errors occured in enforcing the network policies.",
},
)
)
func gatherMetrics() {
@@ -95,6 +101,9 @@ func Start(addr string) error {
if err := prometheus.Register(blockedConnections); err != nil {
return err
}
if err := prometheus.Register(PolicyEnforcementErrors); err != nil {
return err
}
http.Handle("/metrics", promhttp.Handler())
+62 -66
View File
@@ -8,10 +8,10 @@ import (
extnapi "k8s.io/api/extensions/v1beta1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/uuid"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/common/chains"
"github.com/weaveworks/weave/net/ipset"
"github.com/weaveworks/weave/npc/iptables"
)
@@ -22,13 +22,14 @@ type ns struct {
ipt iptables.Interface // interface to iptables
ips ipset.Interface // interface to ipset
name string // k8s Namespace name
nodeName string // my node name
namespace *coreapi.Namespace // k8s Namespace object
pods map[types.UID]*coreapi.Pod // k8s Pod objects by UID
policies map[types.UID]interface{} // k8s NetworkPolicy objects by UID
name string // k8s Namespace name
nodeName string // my node name
namespaceUID ipset.UID // k8s Namespace UID
namespaceLabels map[string]string // k8s Namespace labels
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
// stores IP addrs of pods which are not selected by any target podSelector of
@@ -54,11 +55,12 @@ func newNS(name, nodeName string, ipt iptables.Interface, ips ipset.Interface, n
ipt: ipt,
ips: ips,
name: name,
namespace: namespaceObj,
namespaceUID: nsuid(namespaceObj),
namespaceLabels: namespaceObj.ObjectMeta.Labels,
nodeName: nodeName,
pods: make(map[types.UID]*coreapi.Pod),
policies: make(map[types.UID]interface{}),
uid: uuid.NewUUID(),
pods: make(map[ipset.UID]*coreapi.Pod),
policies: make(map[ipset.UID]interface{}),
uid: ipset.UID(uuid.NewUUID()),
allPods: allPods,
nsSelectors: nsSelectors,
namespacedPodsSelectors: namespacedPodsSelectors,
@@ -88,7 +90,7 @@ func newNS(name, nodeName string, ipt iptables.Interface, ips ipset.Interface, n
}
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 {
@@ -99,7 +101,7 @@ func (ns *ns) onNewPodSelector(selector *selector) error {
for _, pod := range ns.pods {
if hasIP(pod) {
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
}
@@ -115,7 +117,7 @@ func (ns *ns) onNewTargetPodSelector(selector *selector, policyType policyType)
// Remove the pod from default-allow if dst podselector matches the pod
ipset := ns.defaultAllowIPSetName(policyType)
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
}
}
@@ -151,44 +153,37 @@ func (ns *ns) addToDefaultAllowIfNoMatching(pod *coreapi.Pod, policyType policyT
}
if !found {
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 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 {
ns.pods[obj.ObjectMeta.UID] = obj
ns.pods[uid(obj)] = obj
if !hasIP(obj) {
return nil
}
foundIngress, foundEgress, err := ns.podSelectors.addToMatchingPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
foundIngress, foundEgress, err := ns.podSelectors.addToMatchingPodSelector(uid(obj), obj.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
if err != nil {
return err
}
// If there are no matching target selectors, add the pod to default-allow
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
}
}
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
}
}
err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(uid(obj), obj.ObjectMeta.Labels, ns.namespaceLabels, obj.Status.PodIP, podComment(obj))
if err != nil {
return err
}
@@ -197,44 +192,44 @@ func (ns *ns) addPod(obj *coreapi.Pod) error {
}
func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
delete(ns.pods, oldObj.ObjectMeta.UID)
ns.pods[newObj.ObjectMeta.UID] = newObj
delete(ns.pods, uid(oldObj))
ns.pods[uid(newObj)] = newObj
if !hasIP(oldObj) && !hasIP(newObj) {
return nil
}
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
}
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(oldObj.ObjectMeta.UID, oldObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, oldObj.Status.PodIP); err != nil {
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(uid(oldObj), oldObj.ObjectMeta.Labels, ns.namespaceLabels, oldObj.Status.PodIP); err != nil {
return err
}
return ns.podSelectors.delFromMatchingPodSelector(oldObj.ObjectMeta.UID, oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
return ns.podSelectors.delFromMatchingPodSelector(uid(oldObj), oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
}
if !hasIP(oldObj) && hasIP(newObj) {
foundIngress, foundEgress, err := ns.podSelectors.addToMatchingPodSelector(newObj.ObjectMeta.UID, newObj.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
foundIngress, foundEgress, err := ns.podSelectors.addToMatchingPodSelector(uid(newObj), newObj.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
if err != nil {
return err
}
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
}
}
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
}
}
err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(newObj.ObjectMeta.UID, newObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(uid(newObj), newObj.ObjectMeta.Labels, ns.namespaceLabels, newObj.Status.PodIP, podComment(newObj))
if err != nil {
return err
}
@@ -261,12 +256,12 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
continue
}
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
}
}
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
}
}
@@ -279,18 +274,18 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
}
}
for _, ps := range ns.namespacedPodsSelectors.entries {
oldMatch := ps.matchesNamespacedPodSelector(oldObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels)
newMatch := ps.matchesNamespacedPodSelector(newObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels)
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(oldObj.ObjectMeta.UID, oldObj.Status.PodIP); err != nil {
if err := ps.delEntry(uid(oldObj), oldObj.Status.PodIP); err != nil {
return err
}
}
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
}
}
@@ -305,7 +300,7 @@ func (ns *ns) addOrRemoveToDefaultAllowIPSet(ps *selector, oldObj, newObj *corea
if ns.podSelectors.targetSelectorExist(ps, policyType) {
switch {
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
}
case oldMatch && !newMatch:
@@ -318,22 +313,22 @@ func (ns *ns) addOrRemoveToDefaultAllowIPSet(ps *selector, oldObj, newObj *corea
}
func (ns *ns) deletePod(obj *coreapi.Pod) error {
delete(ns.pods, obj.ObjectMeta.UID)
delete(ns.pods, uid(obj))
if !hasIP(obj) {
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
}
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
}
if err := ns.podSelectors.delFromMatchingPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP); err != nil {
if err := ns.podSelectors.delFromMatchingPodSelector(uid(obj), obj.ObjectMeta.Labels, obj.Status.PodIP); err != nil {
return err
}
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, obj.Status.PodIP); err != nil {
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(uid(obj), obj.ObjectMeta.Labels, ns.namespaceLabels, obj.Status.PodIP); err != nil {
return err
}
return nil
@@ -441,12 +436,12 @@ func (ns *ns) updateDefaultAllowIPSetEntry(oldObj, newObj *coreapi.Pod, ipsetNam
// Instead of iterating over all selectors we check whether old pod IP
// has been inserted into default-allow ipset to decide whether the IP
// 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
}
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
}
}
@@ -455,12 +450,12 @@ func (ns *ns) updateDefaultAllowIPSetEntry(oldObj, newObj *coreapi.Pod, ipsetNam
func bypassRules(namespace string, ingress, egress ipset.Name) map[string][][]string {
return map[string][][]string{
DefaultChain: {
chains.DefaultChain: {
{"-m", "set", "--match-set", string(ingress), "dst", "-j", "ACCEPT",
"-m", "comment", "--comment", "DefaultAllow ingress isolation for namespace: " + namespace},
},
EgressDefaultChain: {
{"-m", "set", "--match-set", string(egress), "src", "-j", EgressMarkChain,
chains.EgressDefaultChain: {
{"-m", "set", "--match-set", string(egress), "src", "-j", chains.EgressMarkChain,
"-m", "comment", "--comment", "DefaultAllow egress isolation for namespace: " + namespace},
{"-m", "set", "--match-set", string(egress), "src", "-j", "RETURN",
"-m", "comment", "--comment", "DefaultAllow egress isolation for namespace: " + namespace},
@@ -495,7 +490,8 @@ func (ns *ns) deleteBypassRules() error {
}
func (ns *ns) addNamespace(obj *coreapi.Namespace) error {
ns.namespace = obj
ns.namespaceUID = ipset.UID(obj.ObjectMeta.UID)
ns.namespaceLabels = obj.ObjectMeta.Labels
// Insert a rule to bypass policies
if err := ns.ensureBypassRules(); err != nil {
@@ -503,15 +499,15 @@ func (ns *ns) addNamespace(obj *coreapi.Namespace) error {
}
// Add namespace ipset to matching namespace selectors
err := ns.nsSelectors.addToMatchingNamespaceSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName), namespaceComment(ns))
err := ns.nsSelectors.addToMatchingNamespaceSelector(nsuid(obj), obj.ObjectMeta.Labels, string(ns.allPods.ipsetName), namespaceComment(ns))
return err
}
func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
ns.namespace = newObj
// Re-evaluate namespace selector membership if labels have changed
if !equals(oldObj.ObjectMeta.Labels, newObj.ObjectMeta.Labels) {
ns.namespaceLabels = newObj.ObjectMeta.Labels
for _, selector := range ns.nsSelectors.entries {
oldMatch := selector.matchesNamespaceSelector(oldObj.ObjectMeta.Labels)
newMatch := selector.matchesNamespaceSelector(newObj.ObjectMeta.Labels)
@@ -519,12 +515,12 @@ func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
continue
}
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
}
}
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
}
}
@@ -535,7 +531,7 @@ func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
}
func (ns *ns) deleteNamespace(obj *coreapi.Namespace) error {
ns.namespace = nil
ns.namespaceUID = ""
// Remove bypass rule
if err := ns.deleteBypassRules(); err != nil {
@@ -543,7 +539,7 @@ func (ns *ns) deleteNamespace(obj *coreapi.Namespace) error {
}
// Remove namespace ipset from any matching namespace selectors
err := ns.nsSelectors.delFromMatchingNamespaceSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
err := ns.nsSelectors.delFromMatchingNamespaceSelector(nsuid(obj), obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
if err != nil {
return err
}
@@ -593,7 +589,7 @@ func (ns *ns) defaultAllowIPSetName(pt policyType) ipset.Name {
}
func (ns *ns) analyse(obj interface{}) (
uid types.UID,
uid ipset.UID,
rules map[string]*ruleSpec,
nsSelectors, podSelectors, namespacedPodsSelectors map[string]*selectorSpec,
ipBlocks map[string]*ipBlockSpec,
@@ -601,9 +597,9 @@ func (ns *ns) analyse(obj interface{}) (
switch p := obj.(type) {
case *extnapi.NetworkPolicy:
uid = p.ObjectMeta.UID
uid = ipset.UID(p.ObjectMeta.UID)
case *networkingv1.NetworkPolicy:
uid = p.ObjectMeta.UID
uid = ipset.UID(p.ObjectMeta.UID)
default:
err = errInvalidNetworkPolicyObjType
return
+10 -10
View File
@@ -5,9 +5,9 @@ import (
"reflect"
"strings"
"k8s.io/apimachinery/pkg/types"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/common/chains"
"github.com/weaveworks/weave/net/ipset"
"github.com/weaveworks/weave/npc/iptables"
)
@@ -55,9 +55,9 @@ func newRuleSpec(policyType policyType, proto *string, srcHost, dstHost ruleHost
func (spec *ruleSpec) iptChain() string {
if spec.policyType == policyTypeEgress {
return EgressCustomChain
return chains.EgressCustomChain
}
return IngressChain
return chains.IngressChain
}
func (spec *ruleSpec) iptRuleSpecs() [][]string {
@@ -71,7 +71,7 @@ func (spec *ruleSpec) iptRuleSpecs() [][]string {
// policyTypeEgress
ruleMark := make([]string, len(spec.args))
copy(ruleMark, spec.args)
ruleMark = append(ruleMark, "-j", EgressMarkChain)
ruleMark = append(ruleMark, "-j", chains.EgressMarkChain)
ruleReturn := make([]string, len(spec.args))
copy(ruleReturn, spec.args)
ruleReturn = append(ruleReturn, "-j", "RETURN")
@@ -80,14 +80,14 @@ func (spec *ruleSpec) iptRuleSpecs() [][]string {
type ruleSet struct {
ipt iptables.Interface
users map[string]map[types.UID]struct{}
users map[string]map[ipset.UID]struct{}
}
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 {
if _, found := desired[key]; !found {
delete(rs.users[key], user)
@@ -108,7 +108,7 @@ func (rs *ruleSet) deprovision(user types.UID, current, desired map[string]*rule
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 {
if _, found := current[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
}
}
rs.users[key] = make(map[types.UID]struct{})
rs.users[key] = make(map[ipset.UID]struct{})
}
rs.users[key][user] = struct{}{}
}
+14 -15
View File
@@ -5,7 +5,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/net/ipset"
@@ -60,7 +59,7 @@ func (spec *selectorSpec) getRuleSpec(src bool) ([]string, string) {
}
rule := []string{"-m", "set", "--match-set", string(spec.ipsetName), dir}
comment := "anywhere"
var comment string
if spec.nsName != "" {
comment = fmt.Sprintf("pods: namespace: %s, selector: %s", spec.nsName, spec.key)
} else {
@@ -87,11 +86,11 @@ func (s *selector) matchesNamespacedPodSelector(podsLabelMap, namespaceLabelMap
return s.spec.podSelector.Matches(labels.Set(podsLabelMap)) && s.spec.namespaceSelector.Matches(labels.Set(namespaceLabelMap))
}
func (s *selector) addEntry(user types.UID, entry string, comment string) error {
func (s *selector) addEntry(user ipset.UID, entry string, comment string) error {
return s.ips.AddEntry(user, s.spec.ipsetName, entry, comment)
}
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)
}
@@ -107,7 +106,7 @@ type selectorSet struct {
// invoked after the last instance of target selector has been deprovisioned
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
// We need to keep track of target selector instances to be able to invoke
@@ -122,12 +121,12 @@ func newSelectorSet(ips ipset.Interface, onNewSelector selectorFn, onNewTargetSe
onNewSelector: onNewSelector,
onNewTargetSelector: onNewTargetSelector,
onDestroyTargetSelector: onDestroyTargetSelector,
users: make(map[string]map[types.UID]struct{}),
users: make(map[string]map[ipset.UID]struct{}),
entries: make(map[string]*selector),
targetSelectorsCount: make(map[string]map[policyType]int)}
}
func (ss *selectorSet) addToMatchingPodSelector(user types.UID, podLabelsMap map[string]string, entry string, comment string) (bool, bool, error) {
func (ss *selectorSet) addToMatchingPodSelector(user ipset.UID, podLabelsMap map[string]string, entry string, comment string) (bool, bool, error) {
foundIngress := false
foundEgress := false
for _, s := range ss.entries {
@@ -146,7 +145,7 @@ func (ss *selectorSet) addToMatchingPodSelector(user types.UID, podLabelsMap map
return foundIngress, foundEgress, nil
}
func (ss *selectorSet) addToMatchingNamespaceSelector(user types.UID, namespaceLabelsMap map[string]string, entry string, comment string) error {
func (ss *selectorSet) addToMatchingNamespaceSelector(user ipset.UID, namespaceLabelsMap map[string]string, entry string, comment string) error {
for _, s := range ss.entries {
if s.matchesNamespaceSelector(namespaceLabelsMap) {
if err := s.addEntry(user, entry, comment); err != nil {
@@ -157,7 +156,7 @@ func (ss *selectorSet) addToMatchingNamespaceSelector(user types.UID, namespaceL
return nil
}
func (ss *selectorSet) addToMatchingNamespacedPodSelector(user types.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string, comment string) error {
func (ss *selectorSet) addToMatchingNamespacedPodSelector(user ipset.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string, comment string) error {
for _, s := range ss.entries {
if s.matchesNamespacedPodSelector(podLabelsMap, namespaceLabelsMap) {
if err := s.addEntry(user, entry, comment); err != nil {
@@ -168,7 +167,7 @@ func (ss *selectorSet) addToMatchingNamespacedPodSelector(user types.UID, podLab
return nil
}
func (ss *selectorSet) delFromMatchingPodSelector(user types.UID, podLabelsMap map[string]string, entry string) error {
func (ss *selectorSet) delFromMatchingPodSelector(user ipset.UID, podLabelsMap map[string]string, entry string) error {
for _, s := range ss.entries {
if s.matchesPodSelector(podLabelsMap) {
if err := s.delEntry(user, entry); err != nil {
@@ -179,7 +178,7 @@ func (ss *selectorSet) delFromMatchingPodSelector(user types.UID, podLabelsMap m
return nil
}
func (ss *selectorSet) delFromMatchingNamespaceSelector(user types.UID, namespaceLabelsMap map[string]string, entry string) error {
func (ss *selectorSet) delFromMatchingNamespaceSelector(user ipset.UID, namespaceLabelsMap map[string]string, entry string) error {
for _, s := range ss.entries {
if s.matchesNamespaceSelector(namespaceLabelsMap) {
if err := s.delEntry(user, entry); err != nil {
@@ -190,7 +189,7 @@ func (ss *selectorSet) delFromMatchingNamespaceSelector(user types.UID, namespac
return nil
}
func (ss *selectorSet) delFromMatchingNamespacedPodSelector(user types.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string) error {
func (ss *selectorSet) delFromMatchingNamespacedPodSelector(user ipset.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string) error {
for _, s := range ss.entries {
if s.matchesNamespacedPodSelector(podLabelsMap, namespaceLabelsMap) {
if err := s.delEntry(user, entry); err != nil {
@@ -205,7 +204,7 @@ func (ss *selectorSet) targetSelectorExist(s *selector, policyType policyType) b
return ss.targetSelectorsCount[s.spec.key][policyType] > 0
}
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 {
if _, found := desired[key]; !found {
delete(ss.users[key], user)
@@ -233,7 +232,7 @@ func (ss *selectorSet) deprovision(user types.UID, current, desired map[string]*
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 {
if _, found := current[key]; !found {
selector := &selector{ss.ips, spec}
@@ -246,7 +245,7 @@ func (ss *selectorSet) provision(user types.UID, current, desired map[string]*se
if err := ss.onNewSelector(selector); err != nil {
return err
}
ss.users[key] = make(map[types.UID]struct{})
ss.users[key] = make(map[ipset.UID]struct{})
ss.entries[key] = selector
}
ss.users[key][user] = struct{}{}
+4 -2
View File
@@ -39,9 +39,10 @@ type driver struct {
// used only by plugin-v2
forceMulticast bool
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{
name: name,
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
forceMulticast: isPluginV2 && forceMulticast,
networks: make(map[string]network),
procPath: procPath,
}
// 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
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)
}
+24 -9
View File
@@ -29,6 +29,12 @@ func (w *watcher) ContainerStarted(id string) {
w.driver.warn("ContainerStarted", "error inspecting container %s: %s", id, err)
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
for _, net := range info.NetworkSettings.Networks {
network, err := w.driver.findNetworkInfo(net.NetworkID)
@@ -39,18 +45,27 @@ func (w *watcher) ContainerStarted(id string) {
if network.isOurs {
if w.driver.dns {
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 := "/"
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)
netNSPath := weavenet.NSPathByPidWithProc(w.driver.procPath, info.State.Pid)
if err := weavenet.WithNetNSByPath(netNSPath, func() error {
return weavenet.ConfigureARP(weavenet.VethName, rootDir)
return weavenet.ConfigureARP(weavenet.VethName, w.driver.procPath)
}); err != nil {
w.driver.warn("ContainerStarted", "unable to configure interfaces: %s", err)
}
+5 -4
View File
@@ -32,6 +32,7 @@ type Config struct {
EnableV2Multicast bool
DNS bool
DefaultSubnet string
ProcPath string // path to reach host /proc filesystem
}
type Plugin struct {
@@ -62,7 +63,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
endChan := make(chan error, 1)
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 {
return err
}
@@ -70,7 +71,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
defer globalListener.Close()
}
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 {
return err
}
@@ -87,7 +88,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
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
if isPluginV2 {
name = pluginV2Name
@@ -95,7 +96,7 @@ func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, 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 {
return nil, err
}
-18
View File
@@ -201,24 +201,6 @@ func (listener *listener) leaveEndpoint(w http.ResponseWriter, r *http.Request)
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) {
+13 -10
View File
@@ -6,6 +6,7 @@ Kubernetes uses etcd to distribute and synchronise these annotations so we don't
package main
import (
"context"
"log"
"time"
@@ -38,29 +39,31 @@ const (
retryPeriod = time.Second * 2
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
KubePeersPrefix = "kube-peers.weave.works/"
KubePeersPrefix = progName + "/"
// KubePeersAnnotationKey is the default annotation key
KubePeersAnnotationKey = KubePeersPrefix + "peers"
)
func (cml *configMapAnnotations) Init() error {
ctx := context.Background()
for {
// 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
// re-try to get the configmap.
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 !kubeErrors.IsNotFound(err) {
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{
Name: cml.ConfigMapName,
Namespace: cml.Namespace,
},
})
}, api.CreateOptions{FieldManager: progName})
if err != nil {
if kubeErrors.IsAlreadyExists(err) {
continue
@@ -95,29 +98,29 @@ func (cml *configMapAnnotations) GetAnnotation(key string) (string, bool) {
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 {
return errors.New("endpoint not initialized, call Init first")
}
// speculatively change the state, then replace with whatever comes back
// from Update(), which will be the latest on the server, or nil if error
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
}
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 {
return errors.New("endpoint not initialized, call Init first")
}
// speculatively change the state, then replace with whatever comes back
// from Update(), which will be the latest on the server, or nil if error
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
}
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 {
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
}
}
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
}
+28 -6
View File
@@ -6,6 +6,7 @@ This involves peer management, such as getting the latest peers or removing defu
package main
import (
"context"
"flag"
"fmt"
"math/rand"
@@ -34,7 +35,8 @@ type nodeInfo struct {
// return the IP addresses of all nodes in the cluster
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 {
return nil, err
}
@@ -155,6 +157,7 @@ func reclaimRemovedPeers(kube kubernetes.Interface, cml *configMapAnnotations, m
// Return a bool to show whether we attempted to change anything,
// and an error if something went wrong.
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)
okToRemove := false
nonExistentPeer := false
@@ -187,7 +190,7 @@ func reclaimPeer(weave weaveClient, cml *configMapAnnotations, peerName string,
if !found || nonExistentPeer {
// 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)
if err := cml.UpdateAnnotation(KubePeersPrefix+peerName, myPeerName); err == nil {
if err := cml.UpdateAnnotation(ctx, KubePeersPrefix+peerName, myPeerName); err == nil {
okToRemove = true
} else {
common.Log.Errorln("[kube-peers] error from UpdateAnnotation: ", err)
@@ -209,7 +212,7 @@ func reclaimPeer(weave weaveClient, cml *configMapAnnotations, peerName string,
}
err = cml.LoopUpdate(func() error {
// 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
}
// 7a. Remove X from peerList
@@ -219,14 +222,14 @@ func reclaimPeer(weave weaveClient, cml *configMapAnnotations, peerName string,
}
if storedPeerList.contains(peerName) {
storedPeerList.remove(peerName)
if err := cml.UpdatePeerList(*storedPeerList); err != nil {
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
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
@@ -311,6 +314,8 @@ func main() {
justReclaim bool
justCheck bool
justSetNodeStatus bool
justVersion bool
justUID bool
peerName string
nodeName string
logLevel string
@@ -320,6 +325,8 @@ func main() {
flag.BoolVar(&runReclaimDaemon, "run-reclaim-daemon", false, "run background process that reclaim IP space from dead peers ")
flag.BoolVar(&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(&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(&nodeName, "node-name", "unknown", "name of this Kubernetes node")
flag.StringVar(&logLevel, "log-level", "info", "logging level (debug, info, warning, error)")
@@ -368,9 +375,24 @@ func main() {
}
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)
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
stopCh := make(chan struct{})
rand.Seed(time.Now().UnixNano())
+3 -2
View File
@@ -1,10 +1,11 @@
package main
import (
"context"
"encoding/json"
"fmt"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
@@ -24,6 +25,6 @@ func setNodeNetworkUnavailableFalse(c kubernetes.Interface, nodeName string) err
return err
}
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
}
+4 -3
View File
@@ -4,6 +4,7 @@ This module deals with operations on the peerlist backed by Kubernetes' annotati
package main
import (
"context"
"encoding/json"
"github.com/pkg/errors"
@@ -62,12 +63,12 @@ func (cml *configMapAnnotations) GetPeerList() (*peerList, error) {
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)
if err != nil {
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
@@ -81,7 +82,7 @@ func addMyselfToPeerList(cml *configMapAnnotations, c kubernetes.Interface, peer
}
if !list.contains(peerName) {
list.add(peerName, name)
err = cml.UpdatePeerList(*list)
err = cml.UpdatePeerList(context.Background(), *list)
if err != nil {
return err
}
+2 -3
View File
@@ -1,6 +1,7 @@
package main
import (
"context"
"fmt"
"math/rand"
"sync"
@@ -16,8 +17,6 @@ const (
peerName3 = "03:00:00:00:00:00"
nodeName1 = "fake-node-1"
nodeName2 = "fake-node-2"
testIters = 1000
)
func TestPeerListBasic(t *testing.T) {
@@ -46,7 +45,7 @@ func TestPeerListBasic(t *testing.T) {
storedPeerList.remove(peerName1)
require.Equal(t, 1, len(storedPeerList.Peers))
err = cml.UpdatePeerList(*storedPeerList)
err = cml.UpdatePeerList(context.Background(), *storedPeerList)
require.NoError(t, err)
check1, err = checkIamInPeerList(cml, c, peerName1)
require.NoError(t, err)
+1 -1
View File
@@ -6,7 +6,7 @@ LABEL maintainer="Weaveworks <help@weave.works>" \
org.opencontainers.image.source="https://github.com/weaveworks/weave" \
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"]
# This label will change for every build, and should therefore be the last layer of the image:
+64
View File
@@ -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
+37 -52
View File
@@ -1,29 +1,41 @@
#!/bin/sh
# Launch of Weave Net pod - requires that init.sh has been run previously
set -e
modprobe_safe() {
modprobe $1 || echo "Ignore the error if \"$1\" is built-in in the kernel" >&2
}
# If this is run from an older manifest, run the init script here
[ "${INIT_CONTAINER}" = "true" ] || "$(dirname "$0")/init.sh"
# Check whether xt_set actually exists
xt_set_exists() {
# Clean everything up in advance, in case there's leftovers
iptables -F WEAVE-KUBE-TEST 2>/dev/null || true
iptables -X WEAVE-KUBE-TEST 2>/dev/null || true
ipset destroy weave-kube-test 2>/dev/null || true
ipset create weave-kube-test hash:ip
iptables -t filter -N WEAVE-KUBE-TEST
if ! iptables -A WEAVE-KUBE-TEST -m set --match-set weave-kube-test src -j DROP; then
NOT_EXIST=1
# 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
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
IPALLOC_RANGE=${IPALLOC_RANGE:-10.32.0.0/12}
HTTP_ADDR=${WEAVE_HTTP_ADDR:-127.0.0.1:6784}
@@ -38,22 +50,6 @@ DB_PREFIX=${DB_PREFIX:-/weavedb/weave-net}
# 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
STATUS_OPTS="--metrics-addr=$METRICS_ADDR"
# --status-addr exposes internal information, so only turn it on if asked to.
if [ -n "${WEAVE_STATUS_ADDR}" ]; then
@@ -66,9 +62,9 @@ if [ "${EXPECT_NPC}" = "0" ]; then
WEAVE_NPC_OPTS=""
fi
NO_MASQ_LOCAL_OPT=""
if [ -n "${NO_MASQ_LOCAL}" ]; then
NO_MASQ_LOCAL_OPT="--no-masq-local"
NO_MASQ_LOCAL_OPT="--no-masq-local"
if [ "${NO_MASQ_LOCAL}" = "0" ]; then
NO_MASQ_LOCAL_OPT=""
fi
# Kubernetes sets HOSTNAME to the host's hostname
@@ -122,6 +118,10 @@ fi
# 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
# 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() {
# Wait for weave process to become responsive
while true ; do
@@ -129,20 +129,6 @@ post_start_actions() {
sleep 1
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
/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) \
--name="$PEERNAME" \
--host-root=$HOST_ROOT \
--http-addr=$HTTP_ADDR $STATUS_OPTS --docker-api='' --no-dns \
--db-prefix="$DB_PREFIX" \
--ipalloc-range=$IPALLOC_RANGE $NICKNAME_ARG \
+38 -15
View File
@@ -8,7 +8,7 @@ items:
labels:
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: weave-net
@@ -48,7 +48,7 @@ items:
verbs:
- patch
- update
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: weave-net
@@ -62,7 +62,7 @@ items:
- kind: ServiceAccount
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: weave-net
@@ -85,7 +85,7 @@ items:
- configmaps
verbs:
- create
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: weave-net
@@ -118,11 +118,34 @@ items:
labels:
name: weave-net
spec:
initContainers:
- name: weave-init
image: 'weaveworks/weave-kube:latest'
imagePullPolicy: Always
command:
- /home/weave/init.sh
env:
securityContext:
privileged: true
volumeMounts:
- name: cni-bin
mountPath: /host/opt
- name: cni-bin2
mountPath: /host/home
- name: cni-conf
mountPath: /host/etc
- name: lib-modules
mountPath: /lib/modules
- name: xtables-lock
mountPath: /run/xtables.lock
readOnly: false
containers:
- name: weave
command:
- /home/weave/launch.sh
env:
- name: INIT_CONTAINER
value: "true"
- name: HOSTNAME
valueFrom:
fieldRef:
@@ -137,22 +160,18 @@ items:
port: 6784
resources:
requests:
cpu: 10m
cpu: 50m
securityContext:
privileged: true
volumeMounts:
- name: weavedb
mountPath: /weavedb
- name: cni-bin
mountPath: /host/opt
- name: cni-bin2
mountPath: /host/home
- name: cni-conf
mountPath: /host/etc
- name: dbus
mountPath: /host/var/lib/dbus
- name: lib-modules
mountPath: /lib/modules
readOnly: true
- mountPath: /host/etc/machine-id
name: cni-machine-id
readOnly: true
- name: xtables-lock
mountPath: /run/xtables.lock
readOnly: false
@@ -168,7 +187,7 @@ items:
#npc-args
resources:
requests:
cpu: 10m
cpu: 50m
securityContext:
privileged: true
volumeMounts:
@@ -176,7 +195,8 @@ items:
mountPath: /run/xtables.lock
readOnly: false
hostNetwork: true
hostPID: true
dnsPolicy: ClusterFirstWithHostNet
hostPID: false
restartPolicy: Always
securityContext:
seLinuxOptions: {}
@@ -199,6 +219,9 @@ items:
- name: cni-conf
hostPath:
path: /etc
- name: cni-machine-id
hostPath:
path: /etc/machine-id
- name: dbus
hostPath:
path: /var/lib/dbus
@@ -1,181 +0,0 @@
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ServiceAccount
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: weave-net
labels:
name: weave-net
rules:
- apiGroups:
- ''
resources:
- pods
- namespaces
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- networkpolicies
verbs:
- get
- list
- watch
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: weave-net
labels:
name: weave-net
roleRef:
kind: ClusterRole
name: weave-net
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: weave-net-kube-peer
namespace: kube-system
labels:
name: weave-net-kube-peer
rules:
- apiGroups:
- ''
resources:
- configmaps
resourceNames:
- weave-net
verbs:
- get
- update
- apiGroups:
- ''
resources:
- configmaps
verbs:
- create
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: weave-net-kube-peer
namespace: kube-system
labels:
name: weave-net-kube-peer
roleRef:
kind: Role
name: weave-net-kube-peer
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: weave-net
namespace: kube-system
- apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
spec:
template:
metadata:
labels:
name: weave-net
spec:
containers:
- name: weave
command:
- /home/weave/launch.sh
env:
- name: HOSTNAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: 'weaveworks/weave-kube:latest'
imagePullPolicy: Always
readinessProbe:
httpGet:
host: 127.0.0.1
path: /status
port: 6784
resources:
requests:
cpu: 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
- effect: NoExecute
operator: Exists
volumes:
- name: weavedb
hostPath:
path: /var/lib/weave
- name: cni-bin
hostPath:
path: /opt
- name: cni-bin2
hostPath:
path: /home
- name: cni-conf
hostPath:
path: /etc
- name: dbus
hostPath:
path: /var/lib/dbus
- name: lib-modules
hostPath:
path: /lib/modules
updateStrategy:
type: RollingUpdate
@@ -1,200 +0,0 @@
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ServiceAccount
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: weave-net
labels:
name: weave-net
rules:
- apiGroups:
- ''
resources:
- pods
- namespaces
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- 'networking.k8s.io'
resources:
- networkpolicies
verbs:
- get
- list
- watch
- apiGroups:
- ''
resources:
- nodes/status
verbs:
- patch
- update
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: weave-net
labels:
name: weave-net
roleRef:
kind: ClusterRole
name: weave-net
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: weave-net
namespace: kube-system
labels:
name: weave-net
rules:
- apiGroups:
- ''
resources:
- configmaps
resourceNames:
- weave-net
verbs:
- get
- update
- apiGroups:
- ''
resources:
- configmaps
verbs:
- create
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: weave-net
namespace: kube-system
labels:
name: weave-net
roleRef:
kind: Role
name: weave-net
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: weave-net
namespace: kube-system
- apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
spec:
# Wait 5 seconds to let pod connect before rolling next pod
minReadySeconds: 5
template:
metadata:
labels:
name: weave-net
spec:
containers:
- name: weave
command:
- /home/weave/launch.sh
env:
- name: HOSTNAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: 'weaveworks/weave-kube:latest'
imagePullPolicy: Always
readinessProbe:
httpGet:
host: 127.0.0.1
path: /status
port: 6784
resources:
requests:
cpu: 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
- effect: NoExecute
operator: Exists
volumes:
- name: weavedb
hostPath:
path: /var/lib/weave
- name: cni-bin
hostPath:
path: /opt
- name: cni-bin2
hostPath:
path: /home
- name: cni-conf
hostPath:
path: /etc
- name: dbus
hostPath:
path: /var/lib/dbus
- name: lib-modules
hostPath:
path: /lib/modules
- name: xtables-lock
hostPath:
path: /run/xtables.lock
updateStrategy:
type: RollingUpdate
+37 -15
View File
@@ -8,7 +8,7 @@ items:
labels:
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: weave-net
@@ -48,7 +48,7 @@ items:
verbs:
- patch
- update
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: weave-net
@@ -62,7 +62,7 @@ items:
- kind: ServiceAccount
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: weave-net
@@ -85,7 +85,7 @@ items:
- configmaps
verbs:
- create
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: weave-net
@@ -115,11 +115,34 @@ items:
labels:
name: weave-net
spec:
initContainers:
- name: weave-init
image: 'weaveworks/weave-kube:latest'
imagePullPolicy: Always
command:
- /home/weave/init.sh
env:
securityContext:
privileged: true
volumeMounts:
- name: cni-bin
mountPath: /host/opt
- name: cni-bin2
mountPath: /host/home
- name: cni-conf
mountPath: /host/etc
- name: lib-modules
mountPath: /lib/modules
- name: xtables-lock
mountPath: /run/xtables.lock
readOnly: false
containers:
- name: weave
command:
- /home/weave/launch.sh
env:
- name: INIT_CONTAINER
value: "true"
- name: HOSTNAME
valueFrom:
fieldRef:
@@ -134,22 +157,18 @@ items:
port: 6784
resources:
requests:
cpu: 10m
cpu: 50m
securityContext:
privileged: true
volumeMounts:
- name: weavedb
mountPath: /weavedb
- name: cni-bin
mountPath: /host/opt
- name: cni-bin2
mountPath: /host/home
- name: cni-conf
mountPath: /host/etc
- name: dbus
mountPath: /host/var/lib/dbus
- name: lib-modules
mountPath: /lib/modules
readOnly: true
- mountPath: /host/etc/machine-id
name: cni-machine-id
readOnly: true
- name: xtables-lock
mountPath: /run/xtables.lock
readOnly: false
@@ -165,7 +184,7 @@ items:
#npc-args
resources:
requests:
cpu: 10m
cpu: 50m
securityContext:
privileged: true
volumeMounts:
@@ -173,7 +192,7 @@ items:
mountPath: /run/xtables.lock
readOnly: false
hostNetwork: true
hostPID: true
hostPID: false
restartPolicy: Always
securityContext:
seLinuxOptions: {}
@@ -196,6 +215,9 @@ items:
- name: cni-conf
hostPath:
path: /etc
- name: cni-machine-id
hostPath:
path: /etc/machine-id
- name: dbus
hostPath:
path: /var/lib/dbus
+37 -15
View File
@@ -8,7 +8,7 @@ items:
labels:
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: weave-net
@@ -48,7 +48,7 @@ items:
verbs:
- patch
- update
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: weave-net
@@ -62,7 +62,7 @@ items:
- kind: ServiceAccount
name: weave-net
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: weave-net
@@ -85,7 +85,7 @@ items:
- configmaps
verbs:
- create
- apiVersion: rbac.authorization.k8s.io/v1beta1
- apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: weave-net
@@ -118,11 +118,34 @@ items:
labels:
name: weave-net
spec:
initContainers:
- name: weave-init
image: 'weaveworks/weave-kube:latest'
imagePullPolicy: Always
command:
- /home/weave/init.sh
env:
securityContext:
privileged: true
volumeMounts:
- name: cni-bin
mountPath: /host/opt
- name: cni-bin2
mountPath: /host/home
- name: cni-conf
mountPath: /host/etc
- name: lib-modules
mountPath: /lib/modules
- name: xtables-lock
mountPath: /run/xtables.lock
readOnly: false
containers:
- name: weave
command:
- /home/weave/launch.sh
env:
- name: INIT_CONTAINER
value: "true"
- name: HOSTNAME
valueFrom:
fieldRef:
@@ -137,22 +160,18 @@ items:
port: 6784
resources:
requests:
cpu: 10m
cpu: 50m
securityContext:
privileged: true
volumeMounts:
- name: weavedb
mountPath: /weavedb
- name: cni-bin
mountPath: /host/opt
- name: cni-bin2
mountPath: /host/home
- name: cni-conf
mountPath: /host/etc
- name: dbus
mountPath: /host/var/lib/dbus
- name: lib-modules
mountPath: /lib/modules
readOnly: true
- mountPath: /host/etc/machine-id
name: cni-machine-id
readOnly: true
- name: xtables-lock
mountPath: /run/xtables.lock
readOnly: false
@@ -168,7 +187,7 @@ items:
#npc-args
resources:
requests:
cpu: 10m
cpu: 50m
securityContext:
privileged: true
volumeMounts:
@@ -177,7 +196,7 @@ items:
readOnly: false
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
hostPID: true
hostPID: false
restartPolicy: Always
securityContext:
seLinuxOptions: {}
@@ -200,6 +219,9 @@ items:
- name: cni-conf
hostPath:
path: /etc
- name: cni-machine-id
hostPath:
path: /etc/machine-id
- name: dbus
hostPath:
path: /var/lib/dbus
+30
View File
@@ -2,5 +2,35 @@
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 $@
+70 -54
View File
@@ -1,8 +1,11 @@
package main
import (
"context"
"fmt"
"os"
"os/signal"
goruntime "runtime"
"syscall"
"github.com/coreos/go-iptables/iptables"
@@ -17,6 +20,7 @@ import (
"k8s.io/client-go/tools/cache"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/common/chains"
"github.com/weaveworks/weave/net"
"github.com/weaveworks/weave/net/ipset"
"github.com/weaveworks/weave/npc"
@@ -34,7 +38,14 @@ var (
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,
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 {
// 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
}
if err := ipt.ClearChain(npc.TableFilter, npc.DefaultChain); err != nil {
if err := ipt.ClearChain(npc.TableFilter, chains.DefaultChain); err != nil {
return err
}
if err := ipt.ClearChain(npc.TableFilter, npc.MainChain); err != nil {
if err := ipt.ClearChain(npc.TableFilter, chains.MainChain); err != nil {
return err
}
if err := ipt.ClearChain(npc.TableFilter, npc.EgressMarkChain); err != nil {
if err := ipt.ClearChain(npc.TableFilter, chains.EgressMarkChain); err != nil {
return err
}
if err := ipt.ClearChain(npc.TableFilter, npc.EgressCustomChain); err != nil {
if err := ipt.ClearChain(npc.TableFilter, chains.EgressCustomChain); err != nil {
return err
}
if err := ipt.ClearChain(npc.TableFilter, npc.EgressDefaultChain); err != nil {
if err := ipt.ClearChain(npc.TableFilter, chains.EgressDefaultChain); err != nil {
return err
}
@@ -114,35 +125,35 @@ func resetIPSets(ips ipset.Interface) error {
func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
// 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 {
return err
}
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 {
return err
}
}
// 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 {
return err
}
if err := ipt.Append(npc.TableFilter, npc.MainChain,
"-m", "state", "--state", "NEW", "-j", string(npc.DefaultChain)); err != nil {
if err := ipt.Append(npc.TableFilter, chains.MainChain,
"-m", "state", "--state", "NEW", "-j", chains.DefaultChain); err != nil {
return err
}
if err := ipt.Append(npc.TableFilter, npc.MainChain,
"-m", "state", "--state", "NEW", "-j", string(npc.IngressChain)); err != nil {
if err := ipt.Append(npc.TableFilter, chains.MainChain,
"-m", "state", "--state", "NEW", "-j", chains.IngressChain); err != nil {
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 {
return err
}
@@ -180,16 +191,15 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
ruleSpecs = append(ruleSpecs, []string{"-d", "224.0.0.0/4", "-j", "RETURN"})
}
ruleSpecs = append(ruleSpecs, [][]string{
{"-m", "state", "--state", "NEW", "-j", string(npc.EgressDefaultChain)},
{"-m", "state", "--state", "NEW", "-m", "mark", "!", "--mark", npc.EgressMark, "-j", string(npc.EgressCustomChain)},
{"-m", "state", "--state", "NEW", "-m", "mark", "!", "--mark", npc.EgressMark, "-j", "NFLOG", "--nflog-group", "86"},
{"-m", "state", "--state", "NEW", "-j", chains.EgressDefaultChain},
{"-m", "state", "--state", "NEW", "-m", "mark", "!", "--mark", npc.EgressMark, "-j", chains.EgressCustomChain},
}...)
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
}
// 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 {
common.Log.Errorf("Failed to look if ipset '%s' exists", npc.LocalIpset)
} else if weaveLocalPodExist {
@@ -202,20 +212,17 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
return nil
}
// Dummy way to check whether a given ipset exists.
// TODO(brb) Use "ipset -exist create <..>" for our purpose instead (for some reasons
// creating an ipset with -exist fails).
func ipsetExist(ips ipset.Interface, name ipset.Name) (bool, error) {
sets, err := ips.List(string(name))
if err != nil {
return false, err
// Indirection in case we come up with a more interesting requirement
func hCtx() context.Context {
return context.Background()
}
func stopOnPanicRecover() {
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) {
@@ -240,79 +247,88 @@ func root(cmd *cobra.Command, args []string) {
}
config, err := rest.InClusterConfig()
handleError(err)
handleFatal(err)
client, err := kubernetes.NewForConfig(config)
handleError(err)
handleFatal(err)
ipt, err := iptables.New()
handleError(err)
handleFatal(err)
ips := ipset.New(common.LogLogger(), maxList)
handleError(resetIPTables(ipt))
handleError(resetIPSets(ips))
handleError(createBaseRules(ipt, ips))
handleFatal(resetIPTables(ipt))
handleFatal(resetIPSets(ips))
handleFatal(createBaseRules(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{
AddFunc: func(obj interface{}) {
handleError(npc.AddNamespace(obj.(*coreapi.Namespace)))
defer stopOnPanicRecover()
handleError(npc.AddNamespace(hCtx(), obj.(*coreapi.Namespace)))
},
DeleteFunc: func(obj interface{}) {
defer stopOnPanicRecover()
switch obj := obj.(type) {
case *coreapi.Namespace:
handleError(npc.DeleteNamespace(obj))
handleError(npc.DeleteNamespace(hCtx(), obj))
case cache.DeletedFinalStateUnknown:
// 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
// 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{}) {
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{
AddFunc: func(obj interface{}) {
handleError(npc.AddPod(obj.(*coreapi.Pod)))
defer stopOnPanicRecover()
handleError(npc.AddPod(hCtx(), obj.(*coreapi.Pod)))
},
DeleteFunc: func(obj interface{}) {
defer stopOnPanicRecover()
switch obj := obj.(type) {
case *coreapi.Pod:
handleError(npc.DeletePod(obj))
handleError(npc.DeletePod(hCtx(), obj))
case cache.DeletedFinalStateUnknown:
// 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
// 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{}) {
handleError(npc.UpdatePod(old.(*coreapi.Pod), new.(*coreapi.Pod)))
defer stopOnPanicRecover()
handleError(npc.UpdatePod(hCtx(), old.(*coreapi.Pod), new.(*coreapi.Pod)))
}})
npHandlers := cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
handleError(npc.AddNetworkPolicy(obj))
defer stopOnPanicRecover()
handleError(npc.AddNetworkPolicy(hCtx(), obj))
},
DeleteFunc: func(obj interface{}) {
defer stopOnPanicRecover()
switch obj := obj.(type) {
case cache.DeletedFinalStateUnknown:
// 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
// that we have, which is good enough for our cleanup.
handleError(npc.DeleteNetworkPolicy(obj.Obj))
handleError(npc.DeleteNetworkPolicy(hCtx(), obj.Obj))
default:
handleError(npc.DeleteNetworkPolicy(obj))
handleError(npc.DeleteNetworkPolicy(hCtx(), obj))
}
},
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)
@@ -339,5 +355,5 @@ func main() {
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")
handleError(rootCmd.Execute())
handleFatal(rootCmd.Execute())
}
-2
View File
@@ -21,11 +21,9 @@ CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/
RUN apk add --update \
curl \
ethtool \
iptables \
ipset \
iproute2 \
util-linux \
conntrack-tools \
bind-tools \
ca-certificates \
+10 -37
View File
@@ -1,6 +1,7 @@
package main
import (
"context"
"fmt"
"os"
"sync/atomic"
@@ -9,9 +10,6 @@ import (
checkpoint "github.com/weaveworks/go-checkpoint"
weave "github.com/weaveworks/weave/router"
api "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
var checker *checkpoint.Checker
@@ -19,9 +17,7 @@ var newVersion atomic.Value
var success atomic.Value
const (
updateCheckPeriod = 6 * time.Hour
configMapName = "weave-net"
configMapNamespace = "kube-system"
updateCheckPeriod = 6 * time.Hour
)
func checkForUpdates(dockerVersion string, router *weave.NetworkRouter, clusterSize uint) {
@@ -60,7 +56,7 @@ func checkForUpdates(dockerVersion string, router *weave.NetworkRouter, clusterS
"kernel-version": kernelVersion,
}
checkpointKubernetes(flags, clusterSize)
checkpointKubernetes(context.Background(), flags, clusterSize)
// Start background version checking
params := checkpoint.CheckParams{
@@ -87,36 +83,13 @@ func checkpointFlags(router *weave.NetworkRouter) []checkpoint.Flag {
return flags
}
// checkpoint Kubernetes specific details
func checkpointKubernetes(flags map[string]string, clusterSize uint) {
// checks if weaver is running in Kubernetes
host := os.Getenv("KUBERNETES_SERVICE_HOST")
if len(host) == 0 {
return
// checkpoint Kubernetes specific details, passed in from launch script
func checkpointKubernetes(ctx context.Context, flags map[string]string, clusterSize uint) {
version := os.Getenv("WEAVE_KUBERNETES_VERSION")
if len(version) == 0 {
return // not running under Kubernetes
}
config, err := rest.InClusterConfig()
if err != nil {
Log.Printf("Could not get Kubernetes in-cluster config: %v", err)
return
}
c, err := kubernetes.NewForConfig(config)
if err != nil {
Log.Printf("Could not make Kubernetes client: %v", err)
return
}
k8sVersion, err := c.Discovery().ServerVersion()
if err != nil {
Log.Printf("Could not get Kubernetes version: %v", err)
return
}
flags["kubernetes-version"] = k8sVersion.String()
// use UID of `weave-net` configmap as unique ID of the Kubenerets cluster
cm, err := c.CoreV1().ConfigMaps(configMapNamespace).Get(configMapName, api.GetOptions{})
if err != nil {
Log.Printf("Unable to fetch ConfigMap %s/%s to infer unique cluster ID", configMapNamespace, configMapName)
return
}
flags["kubernetes-cluster-uid"] = string(cm.ObjectMeta.UID)
flags["kubernetes-version"] = version
flags["kubernetes-cluster-uid"] = string(os.Getenv("WEAVE_KUBERNETES_UID"))
flags["kubernetes-cluster-size"] = fmt.Sprint(clusterSize)
}
+28 -7
View File
@@ -55,10 +55,7 @@ type dnsConfig struct {
// return the address part of the DNS listen address, without ":53" on the end
func (c dnsConfig) addressOnly() string {
addr, _, err := net.SplitHostPort(c.ListenAddress)
if err != nil {
Log.Fatalf("Error when parsing DNS listen address %q: %s", c.ListenAddress, err)
}
addr, _, _ := net.SplitHostPort(c.ListenAddress)
return addr
}
@@ -307,9 +304,17 @@ func main() {
bridgeConfig.Mac = name.String()
bridgeConfig.Port = config.Port
if httpAddr != "" {
if _, port, err := net.SplitHostPort(httpAddr); err == nil {
bridgeConfig.ControlPort = port
}
}
ips := ipset.New(common.LogLogger(), 0)
err = weavenet.ResetIPTables(&bridgeConfig, ips)
checkFatal(err)
bridgeType, err := weavenet.EnsureBridge(procPath, &bridgeConfig, Log, ips)
checkFatal(err)
Log.Println("Bridge type is", bridgeType)
config.Password = determinePassword(password)
@@ -453,8 +458,11 @@ func main() {
pluginConfig.DNS = !noDNS
pluginConfig.DefaultSubnet = defaultSubnet.String()
pluginConfig.ProcPath = procPath
plugin := plugin.NewPlugin(pluginConfig)
metricsHandler := metricsHandler(router, allocator, ns, dnsserver)
// The weave script always waits for a status call to succeed,
// so there is no point in doing "weave launch --http-addr ''".
// This is here to support stand-alone use of weaver.
@@ -465,11 +473,12 @@ func main() {
}
if ns != nil {
ns.HandleHTTP(muxRouter, dockerCli)
dnsserver.HandleHTTP(muxRouter)
}
router.HandleHTTP(muxRouter)
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, proxy, plugin, &waitReady)
HandleHTTPPeer(muxRouter, allocator, discoveryEndpoint, token, name.String())
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver))
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler)
if proxy != nil {
muxRouter.Methods("GET").Path("/proxyaddrs").HandlerFunc(proxy.StatusHTTP)
}
@@ -481,7 +490,7 @@ func main() {
if statusAddr != "" {
muxRouter := mux.NewRouter()
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, proxy, plugin, &waitReady)
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver))
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler)
statusMux := http.NewServeMux()
statusMux.Handle("/", muxRouter)
Log.Println("Listening for status+metrics requests on", statusAddr)
@@ -490,7 +499,7 @@ func main() {
if metricsAddr != "" {
metricsMux := http.NewServeMux()
metricsMux.Handle("/metrics", metricsHandler(router, allocator, ns, dnsserver))
metricsMux.Handle("/metrics", metricsHandler)
Log.Println("Listening for metrics requests on", metricsAddr)
go listenAndServeHTTP(metricsAddr, metricsMux)
}
@@ -506,6 +515,18 @@ func main() {
go exposeForAWSVPC(allocator, defaultSubnet, bridgeConfig.WeaveBridgeName, waitReady.Add())
}
applyIPTables := func() {
Log.Info("Re-configuring iptables")
err := weavenet.ConfigureIPTables(&bridgeConfig, ips)
if err != nil {
Log.Errorf("Error configuring iptables: %s", err)
}
weavenet.Reexpose(&bridgeConfig, Log)
}
stopChan := make(chan struct{})
go weavenet.MonitorForIptablesFlush(Log, "WEAVE-CANARY", []string{"mangle", "nat", "filter"}, applyIPTables, 10*time.Second, stopChan)
defer close(stopChan)
signals.SignalHandlerLoop(common.Log, router)
}
+24 -10
View File
@@ -2,7 +2,6 @@ package main
import (
"net/http"
"os"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
@@ -14,10 +13,9 @@ import (
)
func metricsHandler(router *weave.NetworkRouter, allocator *ipam.Allocator, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer) http.Handler {
reg := prometheus.NewRegistry()
reg.MustRegister(prometheus.NewProcessCollector(os.Getpid(), ""))
reg := prometheus.DefaultRegisterer
reg.MustRegister(newMetrics(router, allocator, ns, dnsserver))
return promhttp.HandlerFor(reg, promhttp.HandlerOpts{})
return promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{})
}
type collector struct {
@@ -44,14 +42,30 @@ func uint64Counter(desc *prometheus.Desc, val uint64, labels ...string) promethe
}
var metrics = []metric{
{desc("weave_connections", "Number of peer-to-peer connections.", "state"),
{desc("weave_connections", "Number of peer-to-peer connections.", "state", "type", "encryption"),
func(s WeaveStatus, desc *prometheus.Desc, ch chan<- prometheus.Metric) {
counts := make(map[string]int)
for _, conn := range s.Router.Connections {
counts[conn.State]++
}
counts := make(map[ /*state*/ string]map[ /*type*/ string]struct{ encrypted, unencrypted int })
for _, state := range allConnectionStates {
ch <- intGauge(desc, counts[state], state)
counts[state] = make(map[string]struct{ encrypted, unencrypted int })
}
for _, conn := range s.Router.Connections {
typeName := "unknown"
if t, ok := conn.Attrs["name"]; ok {
typeName = t.(string)
}
c := counts[conn.State][typeName]
if e, ok := conn.Attrs["encrypted"]; ok && e.(bool) {
c.encrypted++
} else {
c.unencrypted++
}
counts[conn.State][typeName] = c
}
for state, stateCounts := range counts {
for connType, count := range stateCounts {
ch <- intGauge(desc, count.encrypted, state, connType, "yes")
ch <- intGauge(desc, count.unencrypted, state, connType, "")
}
}
}},
{desc("weave_connection_terminations_total", "Number of peer-to-peer connections terminated."),
+1 -3
View File
@@ -15,10 +15,8 @@ import (
)
var (
containerIDRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/([^/]*)/.*")
containerIDRegexp = regexp.MustCompile(`^(/v[0-9.]*)?/containers/([^/]*)/.*`)
weaveWaitEntrypoint = []string{"/w/w"}
weaveEntrypoint = "/home/weave/weaver"
weaveContainerName = "/weave"
Log = common.Log
)
+16 -6
View File
@@ -482,7 +482,7 @@ func (fastdp *FastDatapath) getVxlanVportID(udpPort int) (odp.VportID, error) {
// The netdev interface is down, so most likely bringing it up
// has failed due to the UDP port being in use.
if err := fastdp.dp.DeleteVport(vxlanVportID); err != nil {
log.Warning("Unable to remove vxlan vport %d: %s", vxlanVportID, err)
log.Warningf("Unable to remove vxlan vport %d: %s", vxlanVportID, err)
}
return 0, odp.NetlinkError(syscall.EADDRINUSE)
}
@@ -654,27 +654,26 @@ func (fwd *fastDatapathForwarder) logPrefix() string {
func (fwd *fastDatapathForwarder) Confirm() {
fwd.lock.Lock()
defer fwd.lock.Unlock()
if fwd.confirmed {
log.Fatal(fwd.logPrefix(), "already confirmed")
}
var controlMsg []byte
if fwd.fastdp.ipsec != nil && fwd.sessionKey != nil {
fwd.isEncrypted = true
log.Info("Setting up IPsec between ", fwd.fastdp.localPeer, " and ", fwd.remotePeer)
err := fwd.fastdp.ipsec.InitSALocal(
var err error
controlMsg, err = fwd.fastdp.ipsec.InitSALocal(
fwd.fastdp.localPeer.Name, fwd.remotePeer.Name, fwd.connUID,
net.IP(fwd.localIP[:]), fwd.remoteAddr.IP,
fwd.remoteAddr.Port,
fwd.sessionKey,
func(msg []byte) error {
return fwd.sendControlMsg(FastDatapathCryptoInitSARemote, msg)
},
)
if err != nil {
log.Error(fwd.logPrefix(), "ipsec init SA local failed: ", err)
fwd.handleError(err)
fwd.lock.Unlock()
return
}
}
@@ -692,6 +691,17 @@ func (fwd *fastDatapathForwarder) Confirm() {
}
fwd.heartbeatTimeout = time.NewTimer(HeartbeatTimeout)
fwd.lock.Unlock() // unlock before calling send() which may block
if len(controlMsg) > 0 {
if err := fwd.sendControlMsg(FastDatapathCryptoInitSARemote, controlMsg); err != nil {
log.Error(fwd.logPrefix(), "ipsec send InitSARemote failed: ", err)
fwd.handleError(err)
return
}
}
go fwd.doHeartbeats()
}
+3 -2
View File
@@ -334,13 +334,13 @@ func (fwd *overlaySwitchForwarder) healthCheck(index int, healthy bool) {
fwd.lock.Lock()
defer fwd.lock.Unlock()
if healthy == true && fwd.forwarders[index].onHold {
if healthy && fwd.forwarders[index].onHold {
log.Debug(fwd.logPrefix(), "Adding "+fwd.forwarders[index].overlayName+" to the list of forwarders")
fwd.forwarders[index].onHold = false
fwd.chooseBest()
}
if healthy == false && !fwd.forwarders[index].onHold {
if !healthy && !fwd.forwarders[index].onHold {
log.Debug(fwd.logPrefix(), "Removing "+fwd.forwarders[index].overlayName+" from the list of forwarders")
fwd.forwarders[index].onHold = true
fwd.chooseBest()
@@ -452,6 +452,7 @@ func (fwd *overlaySwitchForwarder) Stop() {
fwd.lock.Lock()
defer fwd.lock.Unlock()
fwd.stopFrom(0)
close(fwd.stopChan)
}
func (fwd *overlaySwitchForwarder) ControlMessage(tag byte, msg []byte) {
+6 -2
View File
@@ -4,10 +4,14 @@ import (
"fmt"
"net"
"sync"
"time"
"github.com/google/gopacket/pcap"
)
// Must be less than 2^31 usec - see https://github.com/google/gopacket/issues/708
const longTimeout = time.Duration(30 * time.Minute)
type Pcap struct {
NonDiscardingFlowOp
@@ -77,7 +81,7 @@ func newPcapHandle(ifName string, promisc bool, snaplen int, bufSz int) (handle
if err = inactive.SetSnapLen(snaplen); err != nil {
return
}
if err = inactive.SetTimeout(MaxDuration); err != nil {
if err = inactive.SetTimeout(longTimeout); err != nil {
return
}
if err = inactive.SetImmediateMode(true); err != nil {
@@ -143,7 +147,7 @@ func (p *Pcap) sniff(readHandle *pcap.Handle, consumer Consumer) {
// in order to prevent the next capture from
// overwriting the data
pktLen := len(pkt)
pktCopy := make([]byte, pktLen, pktLen)
pktCopy := make([]byte, pktLen)
copy(pktCopy, pkt)
fop.Process(pktCopy, dec, false)
+42 -21
View File
@@ -7,6 +7,8 @@ search_type: Documentation
The following topics are discussed:
* [Installation](#install)
* [Installing on GKE](#gke)
* [Installing on EKS](#eks)
* [Upgrading the Daemon Sets](#daemon-sets)
* [CPU and Memory Requirements](#resources)
* [Pod Eviction](#eviction)
@@ -71,10 +73,26 @@ Shut down Kubernetes, and _on all nodes_ perform the following:
Then relaunch Kubernetes and install the addon as described
above.
**Note:** Installing on GKE
### <a name="gke"></a> Installing on GKE
Please note that you must grant the user the ability to create roles in Kubernetes before launching Weave Net.
This is a prerequisite to use use role-based access control on GKE. Please see the GKE [instructions](https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control).
### <a name="gke"></a> Installing on EKS
EKS by default installs `amazon-vpc-cni-k8s` CNI. Please follow below steps to use Weave-net as CNI
- create EKS cluster in any of [prescribed](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html) way
- delete `amazon-vpc-cni-k8s` daemonset by running `kubectl delete ds aws-node -n kube-system` command
- delete `/etc/cni/net.d/10-aws.conflist` on each of the node
- edit instance security group to allow TCP 6783 and UDP 6783/6784 ports
- flush iptables nat, mangle, filter tables to clear any iptables configurations done by `amazon-vpc-cni-k8s`
- restart kube-proxy pods to reconfigure iptables
- apply weave-net daemoset by following above installation steps
- delete existing pods so they get recreated in Weave pod CIDR's address-space.
Please note that while pods can connect to the Kubernetes API server for your cluser, API server will not be able to connect to the pods as API server nodes are not connected to Weave Net (they run on network managed by EKS).
### <a name="daemon-sets"></a> Upgrading the Daemon Sets
The DaemonSet definition specifies [Rolling
@@ -89,23 +107,18 @@ Kubernetes manages
on each node, and only schedules pods to run on nodes that have enough
free resources.
The components of a typical Kubernetes installation (with the master
node running etcd, scheduler, api-server, etc.) take up about 95% of a
CPU, which leaves little room to run anything else. For all of Weave
Net's features to work, it must run on every node, including the
master.
In the example manifests we request 10% of a CPU, which will be enough
for small installations, but you should monitor how much it uses in
your production clusters and adjust the requests to suit.
The best way to resolve this issue is to use machines with at least
two CPU cores. However if you are installing Kubernetes and Weave Net
for the first time, you may not be aware of this requirement. For this
reason, Weave Net launches as a DaemonSet with a specification that
reserves at least 1% CPU for each container. This enables Weave Net to
start up seamlessly on a single-CPU node.
We do not recommend that you set a CPU or memory _limit_ unless you
are very experienced in such matters, because the implementation of
limits in the Linux kernel sometimes behaves in a surprising way.
Depending on the workload, Weave Net may need more than 1% of the
CPU. The percentage set in the DaemonSet is the minimum and not a
limit. This minimum setting allows Weave Net to take advantage of
available CPU and "burst" above that limit if it needs to.
On a 1-node single-CPU cluster you may find Weave Net does not install
at all, because other Kubernetes components already take 95% of the
CPU. The best way to resolve this issue is to use machines with at
least two CPU cores.
## <a name="eviction"></a>Pod Eviction
@@ -231,8 +244,7 @@ You may also set the `--log-level` flag to `warning` or `error` if you
prefer to only log exceptional conditions.
Many Kubernetes network issues occur at a higher level than Weave Net.
The [Kubernetes Service Debugging Guide]
(https://kubernetes.io/docs/tasks/debug-application-cluster/debug-service/)
The [Kubernetes Service Debugging Guide](https://kubernetes.io/docs/tasks/debug-application-cluster/debug-service/)
has a detailed step-by-step guide.
Once it is up and running, the status of Weave Net can be checked by
@@ -384,7 +396,7 @@ The list of variables you can set is:
* `CHECKPOINT_DISABLE` - if set to 1, disable checking for new Weave Net
versions (default is blank, i.e. check is enabled)
* `CONN_LIMIT` - soft limit on the number of connections between
peers. Defaults to 100.
peers. Defaults to 200.
* `HAIRPIN_MODE` - Weave Net defaults to enabling hairpin on the bridge side of
the `veth` pair for containers attached. If you need to disable hairpin, e.g. your
kernel is one of those that can panic if hairpin is enabled, then you can disable it
@@ -409,9 +421,10 @@ The list of variables you can set is:
a larger size for better performance if your network supports jumbo
frames - see [here](/site/tasks/manage/fastdp.md#mtu) for more
details.
* `NO_MASQ_LOCAL` - set to 1 to preserve the client source IP address when
* `NO_MASQ_LOCAL` - set to 0 to disable preserving the client source IP address when
accessing Service annotated with `service.spec.externalTrafficPolicy=Local`.
The feature works only with Weave IPAM (default).
This feature works only with Weave IPAM (default).
* `IPTABLES_BACKEND` - set to `nft` to use `nftables` backend for `iptables` (default is `iptables`)
Example:
```
@@ -458,3 +471,11 @@ You must pass the `password-secret` option as noted in the previous section to e
A different option is to use `trusted-subnets` and whitelist only the subnets that host your k8s nodes. Mind that depending on your circumstances that might allow a malicious container running in your cluster to access the weave dataplane, still.
Read on the [Securing Connections Across Untrusted Networks](/site/tasks/manage/security-untrusted-networks/) document to see the alternatives.
To improve security drop `CAP_NET_RAW` from pod capabilities: by default pods can forge packets from anywhere on the network, which enables attacks such as DNS spoofing.
```
securityContext:
capabilities:
drop: ["NET_RAW"]
```
+16 -1
View File
@@ -13,7 +13,22 @@ Weave Net detects when a container has exited and releases its allocated address
See the [Automatic IP Address Management](/site/tasks/ipam/ipam.md) and also an explanation of [the basics of IP addressing](/site/concepts/ip-addresses.md) for further details.
Instead of allowing Weave Net to allocate IP addresses automatically (using IPAM), there may be instances where you need to control a particular container or a cluster by setting an IP address for it.
Instead of allowing Weave Net to allocate IP addresses automatically (using IPAM), there may be instances where you need to control a particular container or a cluster by setting an IP address for it. The way to do this varies according to how containers are attached to Weave Net.
## Manually specifying an IP address when using CNI
The software making a call to CNI has to specify an allocator that allows static IPs.
For instance the [static allocator](https://github.com/containernetworking/plugins/tree/master/plugins/ipam/static)
(At the time of writing there is no straightforward way to ask Kubernetes to do this.)
## Manually specifying an IP address when using the Weave Net Docker Plugin
Docker has a flag `--ip` to specify an address, e.g.:
$ docker run --network=mynetwork --ip=172.18.0.22 ...
## Manually specifying an IP address when using the Weave Net Docker Proxy
You can specify an IP address and a network explicitly, using Classless Inter-Domain Routing or [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing).
+88 -92
View File
@@ -1,5 +1,5 @@
---
title: Monitoring with Prometheus
title: Monitoring Weave Net with Prometheus
menu_order: 90
search_type: Documentation
---
@@ -51,107 +51,103 @@ Set it to an empty string to disable.
You can also pass the parameter `--metrics-addr=X.X.X.X:PORT` to
`weave launch` to specify an address to listen for metrics only.
# Static Configuration for Weave Net
# Weave Net Monitoring Setup in Kubernetes using kube-prometheus
The following YAML fragment can be used in your Prometheus configuration to
scrape the router metrics endpoint:
Weave Net monitoring can be setup in Kubernetes using the kube-prometheus [library](https://github.com/coreos/kube-prometheus/blob/master/jsonnet/kube-prometheus/kube-prometheus-weave-net.libsonnet) for Weave Net. You can read about the example document [here](https://github.com/coreos/kube-prometheus/blob/master/docs/weave-net-support.md).
Let's setup weave monitoring using [kube-prometheus](https://github.com/coreos/kube-prometheus).
#### Install golang
Follow this [document](https://golang.org/doc/install/source)
#### Install jssonet builder
```
scrape_configs:
- job_name: 'weave'
scrape_interval: 15s
static_configs:
- targets: ['localhost:6782']
go get github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb
```
# Discovery Configuration for Kubernetes
#### Install jsonnet
Follow this [document](https://github.com/google/jsonnet#building-jsonnet)
If you're running Weave in conjunction with Kubernetes, it is possible
to discover the endpoints for all nodes automatically. The following
Kubernetes config will install and configure Prometheus 1.3 on your
cluster and configure it to discover and scrape the Weave endpoints:
#### Install gojsonyaml
```
go get github.com/brancz/gojsontoyaml
```
#### Update dependencies
```
---
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus
data:
prometheus.yml: |-
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'weave'
kubernetes_sd_configs:
- api_server:
role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_namespace,__meta_kubernetes_pod_label_name]
action: keep
regex: ^kube-system;weave-net$
- source_labels: [__meta_kubernetes_pod_container_name,__address__]
action: replace
target_label: __address__
regex: ^weave;(.+?)(?::\d+)?$
replacement: $1:6782
- source_labels: [__meta_kubernetes_pod_container_name,__address__]
action: replace
target_label: __address__
regex: ^weave-npc;(.+?)(?::\d+)?$
replacement: $1:6781
- source_labels: [__meta_kubernetes_pod_container_name]
action: replace
target_label: job
---
apiVersion: v1
kind: Service
metadata:
labels:
name: prometheus
name: prometheus
spec:
selector:
app: prometheus
type: NodePort
ports:
- name: prometheus
protocol: TCP
port: 9090
nodePort: 30900
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: prometheus
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
name: prometheus
labels:
app: prometheus
spec:
containers:
- name: prometheus
image: prom/prometheus:v1.3.0
args:
- '-config.file=/etc/prometheus/prometheus.yml'
ports:
- name: web
containerPort: 9090
volumeMounts:
- name: config-volume
mountPath: /etc/prometheus
volumes:
- name: config-volume
configMap:
name: prometheus
jb update
```
#### Create weave-net.jsonnet
**Note:** Some alert configurations are environment specific and may require modifications of alert thresholds.
```
cat << EOF > weave-net.jsonnet
local kp = (import 'kube-prometheus/kube-prometheus.libsonnet') +
(import 'kube-prometheus/kube-prometheus-weave-net.libsonnet') + {
_config+:: {
namespace: 'monitoring',
},
prometheusAlerts+:: {
groups: std.map(
function(group)
if group.name == 'weave-net' then
group {
rules: std.map(function(rule)
if rule.alert == "WeaveNetFastDPFlowsLow" then
rule {
expr: "sum(weave_flows) < 20000"
}
else if rule.alert == "WeaveNetIPAMUnreachable" then
rule {
expr: "weave_ipam_unreachable_percentage > 25"
}
else
rule
,
group.rules
)
}
else
group,
super.groups
),
},
};
{ ['00namespace-' + name]: kp.kubePrometheus[name] for name in std.objectFields(kp.kubePrometheus) } +
{ ['0prometheus-operator-' + name]: kp.prometheusOperator[name] for name in std.objectFields(kp.prometheusOperator) } +
{ ['node-exporter-' + name]: kp.nodeExporter[name] for name in std.objectFields(kp.nodeExporter) } +
{ ['kube-state-metrics-' + name]: kp.kubeStateMetrics[name] for name in std.objectFields(kp.kubeStateMetrics) } +
{ ['prometheus-' + name]: kp.prometheus[name] for name in std.objectFields(kp.prometheus) } +
{ ['prometheus-adapter-' + name]: kp.prometheusAdapter[name] for name in std.objectFields(kp.prometheusAdapter) } +
{ ['grafana-' + name]: kp.grafana[name] for name in std.objectFields(kp.grafana) }
EOF
```
#### Create manifests
```
jsonnet -J vendor -m manifests weave-net.jsonnet | xargs -I{} sh -c 'cat $1 | gojsontoyaml > $1.yaml; rm -f $1' -- {}
```
#### Apply manifests
Applying the created manifests will install the following components in your Kubernetes cluster:
- [Namespace](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) "monitoring"
- [Prometheus](https://github.com/prometheus/prometheus)
- [Kube State Metrics](https://github.com/kubernetes/kube-state-metrics)
- [Prometheus Operator](https://github.com/coreos/prometheus-operator) Operator to manage prometheus
- [Grafana](https://grafana.com) Dashboards on top of Prometheus metrics.
- [Weave Net ServiceMonitor](https://github.com/coreos/kube-prometheus/blob/7a85d7d8a6a81eda1db090846759fd6ca6532884/jsonnet/kube-prometheus/kube-prometheus-weave-net.libsonnet#L12-L43) ServiceMonitor brings the weave net metrics to prometheus.
- [Weave Net Service](https://github.com/coreos/kube-prometheus/blob/7a85d7d8a6a81eda1db090846759fd6ca6532884/jsonnet/kube-prometheus/kube-prometheus-weave-net.libsonnet#L7-L11) Weave Net Service which the ServiceMonitor scrapes.
- [Weave Net Grafana Dashboard](https://grafana.com/grafana/dashboards/11789)
- [Weave Net (Cluster) Grafana Dashboard](https://grafana.com/grafana/dashboards/11804)
```
cd manifests
ls *.yaml | grep -e ^prometheus -e ^node -e ^grafana -e ^kube | xargs -I {} kubectl create -f {} -n monitoring
kubectl create -f prometheus-serviceWeaveNet.yaml -n kube-system
kubectl create -f prometheus-serviceMonitorWeaveNet.yaml -n monitoring
```
**Note:** If you want to make changes to the created yamls, please modify the weave-net.jsonnet and recreate the manifests before applying.
# Weave Cloud Integration
Finally, you can configure your local Prometheus instance to push
+15
View File
@@ -34,11 +34,26 @@ root@ubuntu:/# ping pingme
...
```
Moreover, weaveDNS always register all network aliases (--network-alias option to docker run).
```
host1$ docker run --network weave --network-alias pingme --network-alias pingme2 -dti weaveworks/ubuntu
host1$ docker run --network weave --hostname=ubuntu.weave.local -ti weaveworks/ubuntu
root@ubuntu:/# ping pingme
...
root@ubuntu:/# ping pingme2
...
```
> **Note** If both hostname and container name are specified at
the same time, the hostname takes precedence. In this circumstance, if
the hostname is not in the weaveDNS domain, the container is *not*
registered, but it will still use weaveDNS for resolution.
By default, weaveDNS will listen on port 53 on the address of the
Docker bridge. To make it listen on a different address or port use
`weave launch --dns-listen-address <address>:<port>`
To disable an application container's use of weaveDNS, add the
`--without-dns` option to `weave launch`. To
disable weaveDNS itself, launch weave with the `--no-dns` option.
+1
View File
@@ -335,3 +335,4 @@ and the container image versions as git hashes.
* [Troubleshooting the Kubernetes Addon](/site/kubernetes/kube-addon.md#troubleshooting)
* [Troubleshooting IPAM](/site/tasks/ipam/troubleshooting-ipam.md)
* [Troubleshooting the Proxy](/site/tasks/weave-docker-api/using-proxy.md)
* [Weave Net monitoring setup in Kubernetes using kube-prometheus](https://github.com/weaveworks/weave/blob/master/site/tasks/manage/metrics.md#weave-net-monitoring-setup-in-kubernetes-using-kube-prometheus)
+1
View File
@@ -24,5 +24,6 @@ weave_on $HOST2 attach $C2/24 c2
wait_for_x network_tester_status "network tester status"
assert "echo $status" "pass"
assert "connections_metric $HOST1 encryption=\\\"\\\",state=\\\"established\\\"" "1"
end_suite
+1
View File
@@ -16,5 +16,6 @@ assert_raises "exec_on $HOST1 c1 $PING $C2"
assert_raises "weave_on $HOST1 status connections | grep -P 'encrypted *sleeve'"
assert_raises "weave_on $HOST2 status connections | grep -P 'encrypted *sleeve'"
assert "connections_metric $HOST1 encryption=\\\"yes\\\"",state=\\\"established\\\" "1"
end_suite
+1
View File
@@ -44,6 +44,7 @@ weave_on $HOST2 launch --password wfvAwt7sj $HOST1
assert_raises "weave_on $HOST1 status connections | grep -P 'encrypted *fastdp'"
assert_raises "weave_on $HOST2 status connections | grep -P 'encrypted *fastdp'"
assert "connections_metric $HOST1 encryption=\\\"yes\\\"",state=\\\"established\\\" "1"
PCAP1=$(mktemp)
PCAP2=$(mktemp)
+2
View File
@@ -17,6 +17,7 @@ weave_on $HOST1 launch --password wfvAwt7sj --trusted-subnets $HOST2_CIDR
weave_on $HOST2 launch --password wfvAwt7sj $HOST1
assert_raises "weave_on $HOST1 status connections | grep encrypted"
assert_raises "weave_on $HOST2 status connections | grep encrypted"
assert "connections_metric $HOST1 encryption=\\\"yes\\\"",state=\\\"established\\\" "1"
weave_on $HOST1 stop
weave_on $HOST2 stop
@@ -26,5 +27,6 @@ weave_on $HOST1 launch --password wfvAwt7sj --trusted-subnets $HOST2_CIDR
weave_on $HOST2 launch --password wfvAwt7sj --trusted-subnets $HOST1_CIDR $HOST1
assert_raises "weave_on $HOST1 status connections | grep unencrypted"
assert_raises "weave_on $HOST2 status connections | grep unencrypted"
assert "connections_metric $HOST1 encryption=\\\"\\\"",state=\\\"established\\\" "1"
end_suite
+47
View File
@@ -0,0 +1,47 @@
#!/bin/bash
. "$(dirname "$0")/config.sh"
run_on1() {
assert_raises "run_on $HOST1 $@"
}
weave_on1() {
assert_raises "weave_on $HOST1 $@"
}
stop_weave_on1() {
assert_raises "stop_weave_on $HOST1 $@"
}
get_weave_iptable_rules() {
get_command_output_on $HOST1 "sudo iptables-save | grep -i weave"
}
wait_for_iptable_refresh() {
# Canary is checked every 10s
sleep 12
}
start_suite "exposing weave network to host"
# Launch
weave_on1 "launch"
IPT_BEFORE=$(get_weave_iptable_rules)
run_on1 "sudo iptables -t nat -X WEAVE-CANARY"
wait_for_iptable_refresh
IPT_AFTER=$(get_weave_iptable_rules)
assert_raises "diff <(echo $IPT_BEFORE) <(echo $IPT_AFTER)" 0
stop_weave_on1
# After exposing
weave_on1 "launch"
weave_on1 "expose"
IPT_BEFORE=$(get_weave_iptable_rules)
run_on1 "sudo iptables -t nat -X WEAVE-CANARY"
wait_for_iptable_refresh
IPT_AFTER=$(get_weave_iptable_rules)
assert_raises "diff <(echo $IPT_BEFORE) <(echo $IPT_AFTER)" 0
stop_weave_on1
end_suite
+3 -3
View File
@@ -13,9 +13,9 @@ start_suite "Resolve names in custom domain with subdomains"
weave_on $HOST1 launch --log-level=debug --dns-domain $DOMAIN.
start_container_with_dns $HOST1 $C1/24 --name=c1 -h foo.$SUBDOMAIN1
start_container_with_dns $HOST1 $C2/24 --name=c2 -h foo.$SUBDOMAIN2
start_container_with_dns $HOST1 $C3/24 --name=c3 -h tre.$SUBDOMAIN1 --dns-search=$SUBDOMAIN2
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C1/24 --name=c1 -h foo.$SUBDOMAIN1
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C2/24 --name=c2 -h foo.$SUBDOMAIN2
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C3/24 --name=c3 -h tre.$SUBDOMAIN1 --dns-search=$SUBDOMAIN2
assert_dns_record $HOST1 c1 foo.$SUBDOMAIN2 $C2
assert_dns_a_record $HOST1 c3 foo $C2 foo.$SUBDOMAIN2
+3 -3
View File
@@ -13,9 +13,9 @@ start_suite "Resolve unqualified names"
weave_on $HOST1 launch
start_container $HOST1 $C1/24 --name=c1 -h $NAME
start_container_with_dns $HOST1 $C2/24 --name=c2 -h seetwo.$DOMAIN
start_container_with_dns $HOST1 $C3/24 --name=c3 --dns-search=$DOMAIN
proxy_start_container $HOST1 -e WEAVE_CIDR=$C1/24 --name=c1 -h $NAME
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C2/24 --name=c2 -h seetwo.$DOMAIN
proxy_start_container_with_dns $HOST1 -e WEAVE_CIDR=$C3/24 --name=c3 --dns-search=$DOMAIN
container=$(start_container_with_dns $HOST1 $C4/24)
assert_dns_a_record $HOST1 c2 seeone $C1 $NAME
+12 -3
View File
@@ -7,14 +7,15 @@ TARGET=seetwo.weave.local
TARGET_IP=10.2.0.78
STATIC=static.name
STATIC_IP=10.9.9.9
ATTACH_ARGS="--rewrite-hosts --add-host=$STATIC:$STATIC_IP"
check_dns() {
chk=$1
shift
container=$(docker_on $HOST1 run $(dns_args $HOST1 "$@") -dt $DNS_IMAGE /bin/sh)
weave_on $HOST1 attach $IP/24 "$@" --rewrite-hosts --add-host=$STATIC:$STATIC_IP $container
container=$(start_container_with_dns $HOST1 "$@" $IP/24)
$chk $HOST1 $container $TARGET
# --add-host adds to /etc/hosts so should work even when DNS is off.
assert_dns_record $HOST1 $container $STATIC $STATIC_IP
rm_containers $HOST1 $container
}
@@ -22,10 +23,18 @@ check_dns() {
start_suite "With or without DNS test"
# Assert behaviour without weaveDNS running
weave_on $HOST1 launch
weave_on $HOST1 launch --no-dns
start_container $HOST1 $TARGET_IP/24 --name c2 -h $TARGET
check_dns assert_no_dns_record --without-dns
check_dns assert_no_dns_record
weave_on $HOST1 stop
# Assert behaviour with weaveDNS
weave_on $HOST1 launch
check_dns assert_no_dns_record --without-dns
check_dns assert_dns_record
@@ -44,20 +44,8 @@ assert_raises "exec_on $HOST1 c1 $PING $C3"
stop_weave_on $HOST1
stop_weave_on $HOST2
delete_persistence $HOST1 $HOST2
# Now make host1 attempt to claim from host2, when host2 is stopped
# the point being to check whether host1 will hang trying to talk to host2
weave_on $HOST2 launch --ipalloc-range $UNIVERSE
weave_on $HOST2 prime
# Introduce host3 to remember the IPAM CRDT when we stop host2
weave_on $HOST3 launch --ipalloc-range $UNIVERSE $HOST2
weave_on $HOST3 prime
stop_weave_on $HOST2
weave_on $HOST1 launch --ipalloc-range $UNIVERSE $HOST3
stop_weave_on $HOST1
stop_weave_on $HOST3
# Delete persistence data on host1, so that host1 would try to establish a ring.
delete_persistence $HOST1
+1 -1
View File
@@ -3,7 +3,7 @@
. "$(dirname "$0")/config.sh"
IMAGE="weaveworks/docker-py:1.9.0-prime"
IMAGE="weaveworks/docker-py3:1.9.0-prime"
docker_py_test() {
SHARD=$1
+6 -6
View File
@@ -6,7 +6,7 @@ start_suite "Abuse of 'start' operation"
weave_on $HOST1 launch
docker_bridge_ip=$(weave_on $HOST1 docker-bridge-ip)
proxy_start_container $HOST1 --name=c1
id1=$(proxy_start_container $HOST1 --name=c1)
check_hostconfig() {
docker_on $HOST1 attach $1 >/dev/null 2>&1 || true # Wait for container to exit
@@ -16,12 +16,12 @@ check_hostconfig() {
# Start c2 with a sneaky HostConfig
proxy docker_on $HOST1 create --name=c2 $SMALL_IMAGE $CHECK_ETHWE_UP
proxy docker_api_on $HOST1 POST /containers/c2/start '{"NetworkMode": "container:c1"}'
check_hostconfig c2 container:c1
check_hostconfig c2 "container:$id1"
# Start c5 with a differently sneaky HostConfig
proxy docker_on $HOST1 create --name=c5 $SMALL_IMAGE $CHECK_ETHWE_UP
proxy docker_api_on $HOST1 POST /containers/c5/start '{"HostConfig": {"NetworkMode": "container:c1"}}'
check_hostconfig c5 container:c1
check_hostconfig c5 "container:$id1"
# Start c3 with HostConfig having empty binds and null dns/networking settings
proxy docker_on $HOST1 create --name=c3 -v /tmp:/hosttmp $SMALL_IMAGE $CHECK_ETHWE_UP
@@ -41,7 +41,7 @@ assert "docker_on $HOST1 inspect -f '{{.HostConfig.MemorySwap}}' c4b" "-1"
# Start c6 with both named and unnamed HostConfig
proxy docker_on $HOST1 create --name=c6 $SMALL_IMAGE $CHECK_ETHWE_UP
proxy docker_api_on $HOST1 POST /containers/c6/start '{"NetworkMode": "container:c2", "HostConfig": {"NetworkMode": "container:c1"}}'
check_hostconfig c6 container:c1
check_hostconfig c6 "container:$id1"
# Start c7 with an empty HostConfig and check this removes previous parameters, but still attaches to weave
proxy docker_on $HOST1 create --name=c7 --memory-swap -1 $SMALL_IMAGE $CHECK_ETHWE_UP
@@ -55,9 +55,9 @@ proxy docker_api_on $HOST1 POST /containers/c8/start '{"HostConfig": {"NetworkMo
check_hostconfig c8 host
# Start c10 in network of host container
proxy_start_container $HOST1 --name=c9 --net=host
id9=$(proxy_start_container $HOST1 --name=c9 --net=host)
proxy docker_on $HOST1 create --name=c10 $SMALL_IMAGE $CHECK_ETHWE_MISSING
proxy docker_api_on $HOST1 POST /containers/c10/start '{"HostConfig": {"NetworkMode": "container:c9"}}'
check_hostconfig c10 container:c9
check_hostconfig c10 "container:$id9"
end_suite
+18 -13
View File
@@ -37,7 +37,7 @@ k8s_version="$(run_on $HOST1 "kubelet --version" | grep -oP "(?<=Kubernetes )v[\
for host in $HOSTS; do
if [ $host = $HOST1 ] ; then
run_on $host "sudo systemctl start kubelet && sudo kubeadm init --kubernetes-version=$k8s_version --token=$TOKEN --pod-network-cidr=$WEAVE_NETWORK"
run_on $host "sudo systemctl start kubelet && sudo kubeadm init --ignore-preflight-errors=NumCPU --kubernetes-version=$k8s_version --token=$TOKEN --pod-network-cidr=$WEAVE_NETWORK"
else
run_on $host "sudo systemctl start kubelet && sudo kubeadm join --token=$TOKEN --discovery-token-unsafe-skip-ca-verification $HOST1IP:$KUBE_PORT"
fi
@@ -52,9 +52,9 @@ fi
# Ensure Kubernetes uses locally built container images and inject code coverage environment variable (or do nothing depending on $COVERAGE):
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
-e "s%env:%$WEAVE_ENV_VARS%" \
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.9.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.11.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
sleep 5
sleep 2
check_connections() {
run_on $HOST1 "curl -sS http://127.0.0.1:6784/status | grep \"$SUCCESS\""
@@ -247,6 +247,9 @@ spec:
- namespaceSelector: {}
EOF
# Allow some time for the policy change to take effect
sleep 2
# Should be able to access from the "deny" pod now
assert_raises "$SSH $HOST1 $KUBECTL exec $denyPodName -- curl -s -S -f -m 2 http://$DOMAIN:8080/status >/dev/null"
@@ -270,6 +273,7 @@ spec:
cidr: $HOST1EXPIP/32
EOF
# Allow some time for the policy change to take effect
sleep 2
assert_raises "$SSH $HOST1 curl -s -S -f -m 2 http://$VIRTUAL_IP/status >/dev/null"
@@ -289,6 +293,9 @@ spec:
- {}
EOF
# Allow some time for the policy change to take effect
sleep 2
# Virtual IP and NodePort should now work
assert_raises "$SSH $HOST1 curl -s -S -f -m 2 http://$VIRTUAL_IP/status >/dev/null"
assert_raises "$SSH $HOST1 curl -s -S -f -m 2 http://$HOST2:31138/status >/dev/null"
@@ -314,6 +321,9 @@ spec:
- 8.8.8.4/32
EOF
# Allow some time for the policy change to take effect
sleep 2
assert_raises "! $SSH $HOST1 $KUBECTL exec $denyPodName -- curl -s -S -f -m 2 http://$DOMAIN:8080/status >/dev/null"
assert_raises "! $SSH $HOST1 $KUBECTL exec $denyPodName -- dig @8.8.8.4 google.com >/dev/null"
assert_raises "$SSH $HOST1 $KUBECTL exec $denyPodName -- dig @8.8.8.8 google.com >/dev/null"
@@ -346,23 +356,18 @@ spec:
name: kube-system
EOF
# Allow some time for the policy change to take effect
sleep 2
assert_raises "$SSH $HOST1 $KUBECTL exec $denyPodName -- curl -s -S -f -m 2 http://$DOMAIN:8080/status >/dev/null"
# Passing --no-masq-local and setting externalTrafficPolicy to Local must preserve
# the client source IP addr
# Setting externalTrafficPolicy to Local must preserve the client source IP addr
CLIENT_IP_MASQ="$($SSH $HOST1 curl -sS http://$HOST2:31138/client_ip)"
WEAVE_ENV_VARS="${WEAVE_ENV_VARS}\\n - name: NO_MASQ_LOCAL\\n value: \"1\""
$SSH $HOST1 "$KUBECTL delete ds weave-net -n=kube-system"
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
-e "s%env:%$WEAVE_ENV_VARS%" \
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.9.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
sleep 5
run_on $HOST1 "$KUBECTL patch svc netvirt -p '{\"spec\":{\"externalTrafficPolicy\":\"Local\"}}'"
sleep 2
CLIENT_IP_NO_MASQ="$($SSH $HOST1 curl -sS http://$HOST2:31138/client_ip)"
assert_raises "[ $CLIENT_IP_NO_MASQ != $CLIENT_IP_MASQ ]"
+2 -2
View File
@@ -41,7 +41,7 @@ function setup_kubernetes_cluster {
for host in $HOSTS; do
if [ $host = $HOST1 ] ; then
run_on $host "sudo systemctl start kubelet && sudo kubeadm init --kubernetes-version=$k8s_version --token=$TOKEN"
run_on $host "sudo systemctl start kubelet && sudo kubeadm init --ignore-preflight-errors=NumCPU --kubernetes-version=$k8s_version --token=$TOKEN"
else
run_on $host "sudo systemctl start kubelet && sudo kubeadm join --token=$TOKEN --discovery-token-unsafe-skip-ca-verification $HOST1IP:$KUBE_PORT"
fi
@@ -50,7 +50,7 @@ function setup_kubernetes_cluster {
# Ensure Kubernetes uses locally built container images and inject code coverage environment variable (or do nothing depending on $COVERAGE):
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
-e "s%env:%$COVERAGE_ARGS%" \
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.7.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.11.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
}
function weave_connected {
@@ -41,7 +41,7 @@ function setup_kubernetes_cluster {
for host in $HOSTS; do
if [ $host = $HOST1 ] ; then
run_on $host "sudo systemctl start kubelet && sudo kubeadm init --kubernetes-version=$k8s_version --token=$TOKEN"
run_on $host "sudo systemctl start kubelet && sudo kubeadm init --ignore-preflight-errors=NumCPU --kubernetes-version=$k8s_version --token=$TOKEN"
else
run_on $host "sudo systemctl start kubelet && sudo kubeadm join --token=$TOKEN --discovery-token-unsafe-skip-ca-verification $HOST1IP:$KUBE_PORT"
fi
@@ -50,7 +50,7 @@ function setup_kubernetes_cluster {
# Ensure Kubernetes uses locally built container images and inject code coverage environment variable (or do nothing depending on $COVERAGE):
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
-e "s%env:%$COVERAGE_ARGS%" \
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.7.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.11.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
}
function force_drop_node {
+5 -1
View File
@@ -189,7 +189,7 @@ start_container_image() {
fi
is_cidr "$1" && { cidr=$1; shift; }
container=$(docker_on $host run $weave_dns_args $name_args "$@" -dt $image /bin/sh)
if ! weave_on $host attach $cidr $container >/dev/null ; then
if ! weave_on $host attach $cidr $ATTACH_ARGS $container >/dev/null ; then
docker_on $host rm -f $container
return 1
fi
@@ -267,6 +267,10 @@ wait_for_attached() {
wait_for_x "check_attached $1 $2" "$2 on $1 to be attached"
}
connections_metric() {
$SSH $1 curl -sS http://127.0.0.1:6784/metrics | awk -e "/^weave_connections.*$2/ { print \$2 }"
}
# assert_dns_record <host> <container> <name> [<ip> ...]
assert_dns_record() {
local host=$1
+1 -1
View File
@@ -91,7 +91,7 @@ func (s *State) serveClientIP(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
}
fmt.Fprintf(w, host)
fmt.Fprintln(w, host)
}
// serveRead writes our json encoded state
+14 -3
View File
@@ -66,7 +66,7 @@ function print_vars() {
}
function verify_dependencies() {
local deps=(python terraform ansible-playbook gcloud)
local deps=(python terraform gcloud)
for dep in "${deps[@]}"; do
if [ ! "$(which "$dep")" ]; then
echo >&2 "$dep is not installed or not in PATH."
@@ -141,13 +141,23 @@ function wait_for_image() {
exit 1
}
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
}
# shellcheck disable=SC2155
function create_image() {
if [[ "$CREATE_IMAGE" == 1 ]]; then
install_ansible
greenly echo "> Creating GCP image $IMAGE_NAME..."
local begin_img=$(date +%s)
local num_hosts=1
terraform apply -input=false -var "app=$APP" -var "name=$NAME" -var "num_hosts=$num_hosts" "$DIR/../tools/provisioning/gcp"
terraform init "$DIR/../tools/provisioning/gcp"
terraform apply -auto-approve -input=false -var "app=$APP" -var "name=$NAME" -var "num_hosts=$num_hosts" "$DIR/../tools/provisioning/gcp"
configure_with_ansible "$(terraform output username)" "$(terraform output public_ips)," "$(terraform output private_key_path)" $num_hosts
local zone=$(terraform output zone)
local name=$(terraform output instances_names)
@@ -206,7 +216,8 @@ function set_hosts() {
function provision_remotely() {
case "$1" in
on)
terraform apply -input=false -parallelism="$NUM_HOSTS" -var "app=$APP" -var "name=$NAME" -var "num_hosts=$NUM_HOSTS" "$DIR/../tools/provisioning/$2"
terraform init "$DIR/../tools/provisioning/gcp"
terraform apply -auto-approve -input=false -parallelism="$NUM_HOSTS" -var "app=$APP" -var "name=$NAME" -var "num_hosts=$NUM_HOSTS" "$DIR/../tools/provisioning/$2"
local status=$?
ssh_user=$(terraform output username)
ssh_id_file=$(terraform output private_key_path)
-2
View File
@@ -15,8 +15,6 @@ const (
caCertPath = "ca.pem"
clientKeyPath = "key.pem"
clientCertPath = "cert.pem"
serverKeyPath = "server-key.pem"
serverCertPath = "server.pem"
)
func main() {
-7
View File
@@ -4,7 +4,6 @@ import (
"fmt"
"os"
"reflect"
"runtime"
"testing"
"github.com/stretchr/testify/require"
@@ -29,12 +28,6 @@ func AssertErrorType(t *testing.T, expected interface{}, actual error, desc stri
}
}
func stackTrace(all bool) string {
buf := make([]byte, 1<<20)
stacklen := runtime.Stack(buf, all)
return string(buf[:stacklen])
}
// TrimTestArgs finds the first -- in os.Args and trim all args before
// that, returning true when a -- was in fact found.
func TrimTestArgs() bool {
+1 -1
Submodule tools updated: f041a74ffb...7c2f120b0e.
+8
View File
@@ -0,0 +1,8 @@
language: go
go:
- "1.x"
- master
env:
- TAGS=""
- TAGS="-tags purego"
script: go test $TAGS -v ./...
+22
View File
@@ -0,0 +1,22 @@
Copyright (c) 2016 Caleb Spare
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+67
View File
@@ -0,0 +1,67 @@
# xxhash
[![GoDoc](https://godoc.org/github.com/cespare/xxhash?status.svg)](https://godoc.org/github.com/cespare/xxhash)
[![Build Status](https://travis-ci.org/cespare/xxhash.svg?branch=master)](https://travis-ci.org/cespare/xxhash)
xxhash is a Go implementation of the 64-bit
[xxHash](http://cyan4973.github.io/xxHash/) algorithm, XXH64. This is a
high-quality hashing algorithm that is much faster than anything in the Go
standard library.
This package provides a straightforward API:
```
func Sum64(b []byte) uint64
func Sum64String(s string) uint64
type Digest struct{ ... }
func New() *Digest
```
The `Digest` type implements hash.Hash64. Its key methods are:
```
func (*Digest) Write([]byte) (int, error)
func (*Digest) WriteString(string) (int, error)
func (*Digest) Sum64() uint64
```
This implementation provides a fast pure-Go implementation and an even faster
assembly implementation for amd64.
## Compatibility
This package is in a module and the latest code is in version 2 of the module.
You need a version of Go with at least "minimal module compatibility" to use
github.com/cespare/xxhash/v2:
* 1.9.7+ for Go 1.9
* 1.10.3+ for Go 1.10
* Go 1.11 or later
I recommend using the latest release of Go.
## Benchmarks
Here are some quick benchmarks comparing the pure-Go and assembly
implementations of Sum64.
| input size | purego | asm |
| --- | --- | --- |
| 5 B | 979.66 MB/s | 1291.17 MB/s |
| 100 B | 7475.26 MB/s | 7973.40 MB/s |
| 4 KB | 17573.46 MB/s | 17602.65 MB/s |
| 10 MB | 17131.46 MB/s | 17142.16 MB/s |
These numbers were generated on Ubuntu 18.04 with an Intel i7-8700K CPU using
the following commands under Go 1.11.2:
```
$ go test -tags purego -benchtime 10s -bench '/xxhash,direct,bytes'
$ go test -benchtime 10s -bench '/xxhash,direct,bytes'
```
## Projects using this package
- [InfluxDB](https://github.com/influxdata/influxdb)
- [Prometheus](https://github.com/prometheus/prometheus)
- [FreeCache](https://github.com/coocood/freecache)
Loaded 100 of 2421 files, more files were not shown because too many files have changed in this diff. Show more