Compare commits

...
769 Commits
Author SHA1 Message Date
Bryan Boreham f670be4315 Add release v2.1.3 2017-12-04 14:38:05 +00:00
Bryan Boreham a658861fde Merge pull request #3189 from weaveworks/release-latest-plugin
Fix release script for plugin latest_release
2017-12-04 06:33:02 -08:00
Bryan Boreham 475b15e372 Merge pull request #3192 from weaveworks/issues/3190-deepcopy-configmaps
Fix ipam reclaim
2017-12-01 12:33:48 -08:00
Bryan Boreham d2ed91ccc8 Clean up log messages a bit 2017-12-01 14:20:39 +00:00
Bryan Boreham 333f4a1d3c Make sure Annotation names conform to Kubernetes requirements.
E.g. replace "26:c6:0b:ba:fd:31" with "26_c6_0b_ba_fd_31"
2017-12-01 14:20:39 +00:00
Bryan Boreham 832fe2f0b0 Update local copy of annotations even after error
e.g. if we get a clash because someone else has updated the data, it
returns the new data so we should work off that next time.

Also re-fetch the Annotations every time round the main loop for safety.
2017-12-01 14:20:39 +00:00
Martynas Pumputis ea76185873 Update k8s netpol docs
- Mention `--use-legacy-netpol` flag.
- Link to NetworkPolicy from 1.7.
2017-12-01 14:20:21 +00:00
Bryan Boreham 51c3ea184a Fix release script for plugin latest_release
We should never update the latest_release plugin on a PRERELEASE.
We should always update it on a MAINLINE or BRANCH release.
2017-11-27 15:04:39 +00:00
Bryan Boreham 59fe76f29b Add release v2.1.2 2017-11-27 14:06:33 +00:00
Bryan Boreham 2ab01b55c9 Merge branch 'master' into 2.1 2017-11-27 11:45:15 +00:00
Bryan Boreham 461f9e736b Merge pull request #3186 from weaveworks/issues/3184-update-mesh
Update vendored mesh dep
2017-11-27 11:34:15 +00:00
Bryan Boreham 8e16b03ae8 Merge pull request #3181 from weaveworks/issues/3177-ooo
npc: Track ipset entries per user and refcount default-allow ipsets
2017-11-27 11:01:59 +00:00
Martynas Pumputis 6469809b9a Update vendored mesh dep 2017-11-22 16:07:19 +02:00
Martynas Pumputis 0a0dbe115a npc: Track ipset entries per user
There was a bug in handling "default-allow" ipsets - it could not
cope with out of order receive of Pod updates. E.g:

    1) AddPod(Pod_A, PodIP_A),
    2) AddPod(Pod_B, PodIP_A),
    3) DeletePod(Pod_A),

would result with PodIP_A being removed from "default-allow" ipset,
as such ipset entries were not refcounted. Bypassing of refcounting
was due to the fact that adding a netpol which dst-selects a Pod which
IP addr is in "default-allow" ipset has to remove the IP addr from
the ipset regardless of refcount value of the IP addr entry in the
ipset. So, refcounting in such case didn't make sense and it was
bypassed.

This commit changes the way entries are refcounted in ipsets, and
it makes "default-allow" ipset the same citizen as other ipsets, so
from now "default-allow" ipset is refcounted.
2017-11-21 14:41:29 +02:00
Bryan Boreham ebbf3d4244 Add release v2.1.1 2017-11-17 14:17:31 +00:00
Bryan Boreham ceb36d1891 Typo 2017-11-17 14:15:10 +00:00
Bryan Boreham 4caa850853 Merge pull request #3176 from weaveworks/issues/3175-fix-install
Fix 2.1.0 install issues
2017-11-17 14:14:41 +00:00
Bryan Boreham 96cecf1796 Pull images before running inside weaveexec container
Now we don't bundle the docker command inside weaveexec, we need to do
an explicit 'docker pull' to ensure the images are there.

Also set the weavedb tag to :latest to remove a warning from docker
2017-11-17 13:51:10 +00:00
Bryan Boreham 51c7af8fb4 Set IMAGE before using it 2017-11-17 13:31:46 +00:00
Bryan Boreham 347466aba2 Add release v2.1.0 2017-11-17 11:10:52 +00:00
Bryan Boreham bee1c44859 Merge pull request #3173 from weaveworks/reclaim-tweaks
Rearrange peer reclaim checks in weave-kube launch script
2017-11-16 17:05:46 +00:00
Bryan Boreham f07238c8bb Move info log to after error check 2017-11-16 14:31:40 +00:00
Bryan Boreham 3b499ce27c Rearrange peer reclaim checks in weave-kube launch script
This is to make it behave better on fresh start, and in the case where
the manifest has not been updated to give it permissions.
2017-11-16 14:14:54 +00:00
Bryan Boreham 4dda216398 Merge pull request #3172 from weaveworks/issues/3170-fix-upgrade
weave-kube reclaim: check for upgrade case
2017-11-15 17:59:54 +00:00
Bryan Boreham f0e511510a Don't print a message on flag not found 2017-11-15 12:35:19 +00:00
Bryan Boreham 570ab0b10b Avoid deleting persisted data on weave-kube upgrade
Add a feature to weaveutil to get and set flags, then use this feature
to mark the DB when this version runs
2017-11-15 11:26:43 +00:00
Bryan Boreham 214cf6cb2e Flip result code when checking for new peer
This avoids mistaking an error condition for the result we should act on
2017-11-15 10:11:02 +00:00
Bryan Boreham 07459f0cec Merge pull request #3149 from weaveworks/fix-2797-loosing-ipam-ips
Fix 2797 on Kubernetes - Cluster goes down because all IPs become unreachable
2017-11-14 15:31:06 +00:00
Brice Fernandes 90f4f7b62c Add test to ensure that weave recovers unreachable IPs on launch 2017-11-14 14:18:21 +00:00
Brice Fernandes 987ac98fbf Add up command to integration tests to make launching cluster easier 2017-11-14 14:16:01 +00:00
Brice Fernandes 49ed40a301 Add test function to recover clean output from command run on remote host 2017-11-14 14:16:01 +00:00
Bryan Boreham c67bc704e1 Temporarily raise kube-peers log level to debug 2017-11-14 14:16:01 +00:00
Bryan Boreham 3501ad45e6 Cope with a Kubernetes node being deleted and coming back
Add features to weaver and kube-peers to find the peer name and check
if it is in the list, then in launch.sh delete persisted data if not.
2017-11-14 14:15:31 +00:00
Bryan Boreham 70a13c9c12 Make kube-peers logging consistent and add -log-level flag
Also tag kube-peer log messages with "[kube-peers]": in a standard
deployment they end up interspersed with weaver log messages so this
makes it easier to pick them out.
2017-11-14 14:06:34 +00:00
Brice Fernandes 3afb8d3ddf Add log messages to detect dying peer edge case 2017-11-14 14:06:34 +00:00
Brice Fernandes fd2f91e2ee Refactor: Improve naming 2017-11-14 14:06:33 +00:00
Brice Fernandes cb0c9e5fba Document: Add file-level docstrings for kube-peers 2017-11-14 14:06:33 +00:00
Brice Fernandes 6a0e39e5ee Minor refactor for clarity 2017-11-14 14:06:33 +00:00
Bryan Boreham a552f194b4 Code to reclaim IP address space from removed peers 2017-11-14 14:06:33 +00:00
Bryan Boreham 267bd8b51d Pseudo-code to clean up dead peers 2017-11-14 14:06:33 +00:00
Brice Fernandes 497dddabc1 Improve config locking by using optimistic locking strategy
Loop using jitter until the update succeeds
2017-11-14 14:06:33 +00:00
Bryan Boreham 71b39489da Maintain a list of peers in a Kubernetes annotation
This is prework for a feature which will remove 'dead' peers
2017-11-14 14:06:33 +00:00
Bryan Boreham ed8d92cfc6 RBAC to read and write ConfigMaps 2017-11-14 14:06:33 +00:00
Bryan Boreham f431ee289b Refactor: create config in main function 2017-11-14 14:06:33 +00:00
Martynas Pumputis 7ea82204e0 Merge pull request #3089 from weaveworks/improve-flags
Improve flag handling
2017-11-13 17:31:33 +02:00
Bryan Boreham 44692b997c Merge pull request #3169 from weaveworks/issues/k8s-netpol-testing
Extend NetworkPolicy smoke tests
2017-11-13 15:30:48 +00:00
Bryan Boreham 21086a0b2a Merge branch '2.0' 2017-11-13 12:51:29 +00:00
Bryan Boreham d7119169df Add length to log message for too-big DF broadcast frame 2017-11-13 11:06:34 +00:00
Martynas Pumputis e1eb0a8617 npc: Fix typo 2017-11-13 10:41:45 +02:00
Martynas Pumputis cacc190764 npc: Extend NetworkPolicy test cases in 840
- Add a test case for default allow all ingress traffic.
- Fix misleading comment.
2017-11-13 09:40:07 +02:00
Brice Fernandes 89e5d935a6 Document test runner feature to pick number of hosts
Merge pull request #3164 from weaveworks/improve-test-docs
2017-11-09 17:00:31 +00:00
Brice Fernandes 884e1d7a6b Document test runner feature to pick number of hosts 2017-11-09 15:48:21 +00:00
Bryan Boreham 5b1ca02ecc Merge pull request #3151 from weaveworks/issues/3105-k8s-17-netpolicies-whitelist
Implement Kubernetes 1.7 NetworkPolicy semantics
2017-11-07 16:31:01 +00:00
Martynas Pumputis f51347feac npc: Address PR comments
* Add comments about presence of `analysePolicyLegacy` and `analysePolicy`.
* Use non-legacy netpol in TestRegressionPolicyNamespaceOrdering3059.
2017-11-07 15:40:58 +02:00
Martynas Pumputis b605b832ed npc: Extend k8s NetworkPolicy smoke tests
- Test that pods not matching ingress rules are not able to access
  the nettest pods.
- Test upgrading of NPC (from legacy to non-legacy).
- Test new semantics of k8s netpol.
2017-11-07 14:55:03 +02:00
Bryan Boreham e148b72284 Merge branch '2.0' 2017-11-06 11:48:29 +00:00
Bryan Boreham 16db921349 Merge pull request #3128 from weaveworks/k8s-notes
Added 'things to watch out for' section in Kubernetes instructions
2017-11-03 10:59:35 +00:00
Bryan Boreham 4c235b3648 Merge pull request #3160 from weaveworks/2017-11-02-update-gopacket
Update gopacket to latest master to benefit from memory optimization
2017-11-03 10:32:35 +00:00
Damien Lespiau 1a8d479227 Update gopacket to latest master to benefit from memory optimization
Upstream has done some work saving 133k allocated objects on startup (init()),
which translates into a saving of 30-50MB RSS memory.

Details: https://github.com/google/gopacket/pull/377#issuecomment-338984309
2017-11-02 17:07:31 +00:00
Matthias Radestock 7aad364116 Merge pull request #3158 from weaveworks/2.0
merge branch 2.0
2017-10-31 08:11:17 +00:00
Matthias Radestock 4958d9e423 Merge pull request #3156 from weaveworks/3153-v2-plugin-dockerhub
document using v2 plugin from dockerhub rather than store

Fixes #3153.
2017-10-31 07:08:50 +00:00
Matthias Radestock 474f1f3673 document using v2 plugin from dockerhub rather than store
Since the latter is hard to update and hence frequently out of date.

Fixes #3153.
2017-10-30 20:43:45 +00:00
Martynas Pumputis 9aa7044f1e npc: Add unit tests for default-allow ipsets 2017-10-22 19:42:08 +02:00
Martynas Pumputis 7c39f96d08 npc: Implement networking.k8s.io/v1/NetworkPolicy semantics (k8s 1.7)
The main difference between new and legacy (pre-1.7) netpol semantics
are the following:

    * The DenyDefault ingress isolation annotation is obsoleted.
    * Traffic is allowed to a pod if there are no netpol selecting
      the pod.

See https://kubernetes.io/docs/api-reference/v1.6/#networkpolicyspec-v1beta1-extensions
vs https://kubernetes.io/docs/api-reference/v1.7/#networkpolicyspec-v1-networking
for more details.

weave-npc can operate either in the legacy or the new mode (default). To
use the legacy, pass "--use-legacy-netpol" arg when starting the npc.

In non-legacy mode we create for each Namespace a default-allow ipset
which stores IP addrs of such Pods which are not selected by any
NetworkPolicy.The ipsets are dst's in rules of the WEAVE-NPC-DEFAULT chain.
2017-10-22 19:37:18 +02:00
Martynas Pumputis 3c3e0b0352 Enable access to "networkpolicies" of "networking.k8s.io" API group
Since 1.7, k8s netpol is no longer in beta, so NPC can start subscribing
from the non-beta API group.
2017-10-22 19:32:52 +02:00
Martynas Pumputis 8467742d6d Increase smoke test timeout from 240 to 300 sec
The 840 smoke test (k8s + npc) sometimes might take longer than 240 sec.
2017-10-22 19:29:52 +02:00
Martynas Pumputis 5cfc3f8c47 Bump k8s version in smoke tests to 1.7.8 2017-10-22 19:29:21 +02:00
Bryan Boreham 62dbe03193 Don't log nil errors in CNI DEL 2017-10-17 16:13:48 +00:00
Martynas Pumputis 8755da4b5a Add smoke tests to check FORWARDing after 'expose' 2017-10-17 12:08:43 +01:00
Martynas Pumputis 25cff16bd1 Create WEAVE-EXPOSE iptables chain
Docker 1.13 has changed a default policy of FORWARD chain to DROP
(https://github.com/moby/moby/pull/28257) which makes containers
inaccessible from a remote host when the bridge is exposed.

The change breaks e.g. the AWSVPC mode. To overcome this we install
an explicit rule for accepting forwarded ingress traffic to an
exposed subnet which is appended to the WEAVE-EXPOSE chain.

The chain is a target of the rule "-t filter -A FORWARD -o weave".
2017-10-17 12:08:43 +01:00
Martynas Pumputis ade6738789 Handle "weave expose" in weaver
The change makes "weave expose" to call the "/expose" HTTP
endpoint implemented in router which exposes the bridge.

Such architectural change required as we need to know whether NPC is
enabled when exposing the bridge and weaver knows this fact the best.

Unfortunately, this change makes impossible to "weave expose"
when weaver is not running.
2017-10-17 12:08:43 +01:00
Bryan Boreham ea0e3a14e0 Merge branch '2.0' 2017-10-17 10:17:25 +00:00
Bryan Boreham 4a1a1e83c8 Update Python 'setuptools' module to resolve issue
Symptom of issue was this message:

error in cryptography setup command: Invalid environment marker: platform_python_implementation != 'PyPy'
2017-10-17 10:17:06 +00:00
Bryan Boreham ee48700b40 Merge pull request #3141 from bjhaid/upgrade_client_go
Upgrading client go and vendoring its extra dependencies.
2017-10-11 16:08:00 +01:00
Bryan Boreham 0791ce8ab0 Merge branch '2.0' 2017-10-11 10:49:13 +00:00
Ayodele Abejide 1ac543aba7 Upgrading client go and vendoring it's extra dependencies. 2017-10-10 16:48:35 +00:00
Bryan Boreham 3d5f80630d Merge pull request #3142 from weaveworks/fixnotes
Fixnotes
2017-10-10 16:10:00 +01:00
abuehrle be2da07735 fix note pins 2017-10-10 09:46:35 -05:00
Bryan Boreham 276d0b621b Add release v2.0.5 2017-10-05 11:57:23 +00:00
Martynas Pumputis 6733dac9fc Merge remote-tracking branch 'origin/issues/3136-fix-etc-hosts' into 2.0 2017-10-05 13:18:41 +02:00
Martynas Pumputis 80b286ebf7 Merge pull request #3138 from weaveworks/issues/3136-fix-etc-hosts
Add back EXEC_IMAGE so proxy can docker-run itself

Fixes #3136
2017-10-05 13:14:16 +02:00
Bryan Boreham 2c143612e2 Add back EXEC_IMAGE so proxy can exec itself 2017-10-05 11:01:57 +00:00
Bryan Boreham be412812f9 Remove unused variable assignment 2017-10-05 10:45:51 +00:00
Bryan Boreham bfed7c24f8 Merge pull request #3129 from mkumatag/ppc64le_suuport
Add ppc64le support
2017-10-04 17:29:30 +01:00
Bryan Boreham fe859952e0 Merge branch '2.0' 2017-10-04 16:05:07 +00:00
Bryan Boreham 86361c5b60 Merge pull request #3137 from weaveworks/lint-nonsense
Remove explicit error check at end of functions to placate lint
2017-10-04 16:59:01 +01:00
Bryan Boreham 35c017a787 Remove explicit error check at end of functions to placate lint
It's sad because this changes a regular pattern into an irregular one,
which will create spurious diffs if more work is added at the end of
the function.  Still, this is easier than fixing the lint runner to
ignore the report.
2017-10-04 13:40:13 +00:00
Bryan Boreham 79d65bc98b Report errors from rewriting /etc/hosts 2017-10-04 13:32:52 +00:00
Brice Fernandes 6bc69199d3 Merge pull request #3135 from weaveworks/fix-build-osx
Fix builds on OSX
2017-10-04 14:00:18 +01:00
Brice Fernandes 292cbc484a Fix other occurences of GNU-specific sed invocation 2017-10-04 12:12:28 +01:00
Brice Fernandes 1a98cbfff9 Ignore sed backup files 2017-10-04 12:03:12 +01:00
Brice Fernandes 071f077cc5 Fix broken builds on OSX due to BSD vs GNU sed 2017-10-04 11:58:14 +01:00
Bryan Boreham c16653a396 Mount iptables lock file in weave-kube (#3134)
Mount iptables lock file in weave-kube

iptables uses the file `/run/xtables.lock` so that if changes are
under way, another instance of the iptables command can wait till it
is finished.
We need to mount the lock file from the host to the container in order
for this mechanism to work at all.
Note we rely on kubelet touching the file before running any pods -
see https://github.com/kubernetes/kubernetes/pull/47212
2017-10-03 14:52:49 +01:00
Damien Lespiau b157544394 Bump license copyright year to 2017 (#3132) 2017-10-03 14:52:03 +01:00
Matthias Radestock 18f65a1914 fix typo 2017-10-01 21:12:29 +01:00
Bryan Boreham ba16135b3a Escape a minus that is being interpreted as a bullet (#3131) 2017-09-29 14:16:13 +01:00
Bryan Boreham df688cfb53 Added weave_ipam_unreachable_percentage metric 2017-09-26 15:55:38 +00:00
Bryan Boreham 88679d66fc Improve wording 2017-09-26 15:53:14 +00:00
Carlos Alexandro Becker ab1cbcbbf8 prometheus: export count of unreachable peers (#3119)
* prometheus: export count of unreachable peers
* extracted part of printIPAMRanges
2017-09-26 16:50:10 +01:00
Bryan Boreham a02fb753df Use the configured Docker host for the proxy, not the default one 2017-09-26 09:44:46 +00:00
Bryan Boreham 98b002f7c0 Remove unnecessary 'Version' in proxy 2017-09-26 09:44:46 +00:00
Bryan Boreham e251bfe807 Move use of command-line params to after we know them 2017-09-26 09:44:46 +00:00
Bryan Boreham eb88893312 Rename configureProxy to newProxyConfig 2017-09-26 09:44:46 +00:00
Bryan Boreham a362bf68bb Merge branch '2.0' 2017-09-26 09:41:29 +00:00
Bryan Boreham 3c53aa66b7 Improved wording after review 2017-09-26 09:41:11 +00:00
Bryan Boreham c97d4731dc Merge pull request #3113 from weaveworks/plugin-v2-troubleshooting
Add instructions on troubleshooting the V2 plugin
2017-09-26 10:40:29 +01:00
Bryan Boreham a69546c9ee Reworded on review feedback 2017-09-26 09:39:04 +00:00
Manjunath A Kumatagi b0f78e97f4 Add ppc64le support 2017-09-26 13:49:35 +05:30
Bryan Boreham 49f7e38133 Removed stray repetition of anchor 2017-09-25 16:38:07 +00:00
Bryan Boreham 2e7f44feee Added 'things to watch out for' 2017-09-25 16:36:57 +00:00
Matthias Radestock 48ceb49832 refactor: inline and simplify proxy_addrs() 2017-09-18 09:16:37 +01:00
Matthias Radestock dd772f04fe cosmetic: move cidr functions to better place 2017-09-18 08:57:50 +01:00
Matthias Radestock 47597c941d refactor(ish): create volumes just before weave container
It's the most logical sequencing and reduces the chances of debris
being left behind when things go wrong.
2017-09-18 08:49:02 +01:00
Matthias Radestock c0e8af56e2 refactor: inline attach() 2017-09-18 08:24:13 +01:00
Matthias Radestock 72c0172c48 refactor: inline rewrite_etc_hosts 2017-09-18 07:37:01 +01:00
Matthias Radestock 507f5345c5 refactor: inline kill_container 2017-09-18 07:24:34 +01:00
Matthias Radestock 79d4aec1ec cosmetic: move kill_container to correct section 2017-09-18 07:18:27 +01:00
Matthias Radestock 89c7e6d337 refactor weave setup for clarity 2017-09-17 16:33:37 +01:00
Bryan Boreham b8d7af3822 Don't call 'docker pull' inside weaveexec 2017-09-16 18:51:58 +00:00
Bryan Boreham 3c9c968174 Merge pull request #3110 from dtshepherd/issues/2957-rm-docker-binary-from-weaveexec
Remove docker binary from weaveexec container
2017-09-13 13:38:07 +01:00
David Shepherd 38ca0f90c7 Simplify mac generation on attach|expose|hide
`weaveexec` no longer mounting '/' so we can't access the weavedb file
to get persistent peer ID.  If `weaver` was running, we couldn't have
read the file anyway because BoltDB does not support concurrent access
from two processes.

Consequence is that if someone really does need the bridge creation on
'weave expose' the peer ID may change if created pre-1.9.0.  We'll just
live with that (per @bboreham).
2017-09-13 08:04:04 -04:00
David Shepherd 8bf08c3cf8 Remove docker binary from weaveexec container
Fixes #2957

- replace `docker stop` with `weaveuitl stop-container`
- replace `docker kill` with `weaveutil kill-container`
- replace `docker rm` with `weaveutil remove-container`
- replace `docker run` with minimal `weaveutil container-run`
- replace `docker inspect -f {{.ID}}` with `weaveutil container-id`
- replace data-only container `docker create` with `weaveutil create-volume-container`
- remove `docker inspect` dependencies from `weave` script
  `rewrite_etc_hosts` and `with_container_fqdn`
- rework `weave` script `check_running` and `check_not_running` to use `weaveutil`
- rework `weave version` to use `weaver` /report API or `weaver --version` if not running
- rework `weave setup`'s `docker pull` to run locally rather than in `weaveexec` container
2017-09-13 08:03:58 -04:00
Martynas Pumputis 14c79d2184 Merge remote-tracking branch 'origin/2.0' 2017-09-09 13:17:29 +02:00
Martynas Pumputis b0519af573 Merge pull request #3114 from weaveworks/issues/3103-rm-pluginv2-db
Remove db file for v2 plugin

Fixes #3103
2017-09-09 12:44:51 +02:00
Bryan Boreham dc7acd6c70 Remove db file for v2 plugin 2017-09-08 13:23:26 +00:00
Bryan Boreham d63a21363e Add instructions on troubleshooting the V2 plugin 2017-09-08 11:11:44 +00:00
Bryan Boreham a330dd4970 Improve "What is Weave Cloud" link 2017-09-07 19:39:50 +00:00
Bryan Boreham c0388c0136 Improve "What is Weave Cloud" link 2017-09-07 20:32:24 +01:00
Bryan Boreham aeca987a4c Merge branch '2.0' 2017-08-25 15:25:55 +00:00
Bryan Boreham 3aff5f2467 Add release v2.0.4 2017-08-25 14:57:02 +00:00
Bryan Boreham 0c63a8d0e5 Merge pull request #3100 from weaveworks/wip-3098
fix: Test for ipset comment support
2017-08-24 17:29:44 +01:00
Mike Bryant 65b45e8dd1 fix: Test for ipset comment support
During initialisation try and create an ipset with the comment extension
If this fails, disable comment support

Fixes #3098
2017-08-24 11:14:16 +01:00
Bryan Boreham 03885d4b40 Merge pull request #3070 from weaveworks/update-kube-addon-doc
Update kube addon doc
2017-08-24 09:49:58 +01:00
Bryan Boreham 40e78fea99 Add a screen shot of Weave Net status in Weave Cloud 2017-08-24 08:38:05 +00:00
Bryan Boreham ecba88e445 Clarify the wording of weave-kube troubleshooting
and note that statement about deleting old pods applies only to pre-2.0
2017-08-24 08:37:57 +00:00
Bryan Boreham 29c9b2c064 Move 'weave status' up beside the other troubleshooting
and put it in the table of contents at the top
2017-08-24 08:35:11 +00:00
Bryan Boreham ff1cd7c008 Merge branch '2.0' 2017-08-23 11:18:52 +00:00
Bryan Boreham 6a871d13a6 Add release v2.0.3 2017-08-23 11:08:24 +00:00
Bryan Boreham c2a224b436 Merge pull request #3096 from weaveworks/wip-3095
fix: Missing nil checks
2017-08-23 11:28:16 +01:00
Bryan Boreham dd8d4b1d9b Merge pull request #3097 from weaveworks/issues/3095-better-test
Extend weave-kube smoke test: add a policy with blank 'from'
2017-08-23 11:27:43 +01:00
Bryan Boreham 527bcffe3b Extend weave-kube smoke test: add a policy with blank 'from'
Per issue #3095 this crashes the commenting code.
Also added check to see if the pods are still running.
2017-08-23 09:42:51 +00:00
Mike Bryant de1d409c6a Fix review comments 2017-08-23 09:40:44 +01:00
Mike Bryant 2555e491e1 fix: Missing nil checks
Fixes #3095
2017-08-23 01:21:15 +01:00
Bryan Boreham 4b5299d124 Add release v2.0.2 2017-08-22 11:28:19 +00:00
Bryan Boreham 294c16c186 Merge pull request #3060 from weaveworks/docker-install-role-override
Make Ansible's docker_install_role overridable
2017-08-22 11:50:38 +01:00
Bryan Boreham 4b720bffdf Merge branch '2.0' 2017-08-18 14:02:58 +00:00
Bryan Boreham 7df458fcdd Merge pull request #3093 from weaveworks/issues/3092-port-number
Supply the weave port number to bridgeConfig
2017-08-18 15:02:26 +01:00
Bryan Boreham 608b8f0a06 Supply the weave port number to bridgeConfig 2017-08-18 13:13:18 +00:00
Bryan Boreham 089a993299 Merge pull request #3088 from weaveworks/issues/3054-honour-no-dns-in-proxy
If DNS server is off then disable proxy DNS registration
2017-08-18 14:10:28 +01:00
Bryan Boreham bc4c31e48b If DNS server is off then disable proxy DNS registration 2017-08-18 10:25:10 +00:00
Bryan Boreham 5c210c90b5 Merge branch '2.0' 2017-08-16 16:37:29 +00:00
Bryan Boreham a6cd456f8b Merge pull request #3080 from weaveworks/issues/plugin-v2-modprobe
net-plugin: bind mount /lib/modules
2017-08-15 12:05:33 +01:00
Bryan Boreham 2ede1066e9 Remove unused WeaveDomain
(left over from a22b88ed89)
2017-08-14 13:56:53 +00:00
Martynas Pumputis 462033dc99 net-plugin: bind mount /lib/modules
Otherwise, the plugin is not able to load kernel modules
(openvswitch, vxlan, vport_vxlan) required by fastdp which
makes weave to fallback to sleeve.

CAP_SYS_MODULE is required in order to load kernel modules.
2017-08-04 14:14:55 +02:00
Matthias Radestock 0521bdb3b9 Merge pull request #3078 from weaveworks/clarify-rmpeer-caution
clarify rmpeer caution in docs
2017-08-02 22:46:02 +01:00
Matthias Radestock 1f4165c132 clarify rmpeer caution in docs
- "You cannot call `weave rmpeer` on more than one host" - yes you
  can, but you must not call it on more than one host *for the same
  peer*
- `weave forget` has nothing to do with this
- "results in duplicate IPs" - no, it causes duplicate address range
  assignments
- "the address is reassigned" - it's the address *range* that is
  reassigned
- "claim" is a new and confusing term -> drop
- "address space" -> "address range" (that's what it's called
  elsewhere)
2017-08-02 22:28:26 +01:00
Matthias Radestock a1fb08216e correct --allow-mcast docs 2017-07-31 20:21:06 +01:00
Anita Buehrle 381996b225 Merge pull request #3058 from weaveworks/docs-reorg
[WIP] Docs Reorg to accommodate for top menu
2017-07-28 12:34:58 -05:00
Martynas Pumputis 08bca70192 Merge pull request #3071 from weaveworks/remove-kube-fallback
Remove localhost:8080 fallback for Kubernetes api-server
2017-07-24 07:37:02 +02:00
abuehrle 10d25056a0 some conflict 2017-07-20 15:40:39 -05:00
abuehrle f889dda9f3 add more urls fix others 2017-07-20 15:37:43 -05:00
abuehrle b0cd84c940 test anchor 2017-07-20 15:37:33 -05:00
abuehrle 411fd2d831 test anchor 2017-07-20 15:37:32 -05:00
abuehrle d18782afd7 fixed a conflict 2017-07-20 15:34:44 -05:00
abuehrle 43dfbdc8e3 taks toc - full urls added 2017-07-20 15:31:47 -05:00
abuehrle ea0f156b6f install toc added - full urls 2017-07-20 15:31:47 -05:00
abuehrle 98def2f5fc rearrange install and launch 2017-07-20 15:31:47 -05:00
abuehrle c089cb508c add full urls instead 2017-07-20 15:31:47 -05:00
abuehrle 1797cee84f update links in readme anchors 2017-07-20 15:31:46 -05:00
abuehrle 45c97c82e1 concepts toc 2017-07-20 15:31:46 -05:00
abuehrle bccde69a33 test anchor 2017-07-20 15:31:46 -05:00
abuehrle d9aa1a5abd test anchor 2017-07-20 15:31:46 -05:00
abuehrle 46e1153f92 remove code format from title 2017-07-20 15:31:46 -05:00
abuehrle 3dc642c007 fixed url with anchor and broken link 2017-07-20 15:31:45 -05:00
abuehrle bd9bc9093e replaced Using Weave Net with Launching Weave Net 2017-07-20 15:31:45 -05:00
abuehrle 6f0680cc7b replaced getting started guides with tutorials 2017-07-20 15:31:45 -05:00
abuehrle 911bf289bd replaced URLs systemd and installing-weave 2017-07-20 15:31:44 -05:00
abuehrle 393b98a463 misc link replaced topology still going to router-topology 2017-07-20 15:31:44 -05:00
abuehrle 2126d2314e replaced URLs for weave proxy section 2017-07-20 15:31:44 -05:00
abuehrle d4d9a8fa9a replaced URLs for weavedns section 2017-07-20 15:31:43 -05:00
abuehrle 6a21e3a2ca replaced URLs for ipam section 2017-07-20 15:31:43 -05:00
abuehrle 7119348b31 replaced URL to weave cloud 2017-07-20 15:31:43 -05:00
abuehrle bf291b1863 replaced URLs for host network int. 2017-07-20 15:31:42 -05:00
abuehrle e6a1acddcb replaced more urls for /site/tasks/manage section 2017-07-20 15:31:42 -05:00
abuehrle 8a8cd70879 replaced urls for tasks/manage section 2017-07-20 15:31:42 -05:00
abuehrle b744e41e9e replace URLs for kubernetes section 2017-07-20 15:31:41 -05:00
abuehrle c101957fb9 replaced URLs for install and docker plugins 2017-07-20 15:31:41 -05:00
abuehrle a8dc7986af replaced urls /site/installing-weave.md w /site/install/installing-weave.md 2017-07-20 15:31:41 -05:00
abuehrle d0c9763d0d replaced urls /site/how-it-works/ with /site/concepts/ 2017-07-20 15:31:41 -05:00
abuehrle 5988fede53 update how it works url 2017-07-20 15:31:40 -05:00
abuehrle 25c8b46c70 replaced url for features 2017-07-20 15:31:40 -05:00
abuehrle 60c3d97c7a better title for weave cloud and net 2017-07-20 15:31:40 -05:00
abuehrle ee0bd2d747 make launch 10 2017-07-20 15:31:39 -05:00
abuehrle c0e94cabb6 put installing first 2017-07-20 15:31:39 -05:00
abuehrle 867e3231d2 remove index from concepts title 2017-07-20 15:31:39 -05:00
abuehrle 00bfa3ae03 order topic 2017-07-20 15:31:39 -05:00
abuehrle 7ae83d6a5b index file for directory 2017-07-20 15:31:39 -05:00
abuehrle 5d6f6456d3 topic ordering 2017-07-20 15:31:38 -05:00
abuehrle 69b6077221 docker-api mv to tasks 2017-07-20 15:31:38 -05:00
abuehrle dcf82f8db7 moved screencast image to installing 2017-07-20 15:31:37 -05:00
abuehrle 69f83b352a moved .dot file need this? 2017-07-20 15:31:37 -05:00
abuehrle 2899789147 index file 2017-07-20 15:31:37 -05:00
abuehrle d33f06634f menu topic order 2017-07-20 15:31:37 -05:00
abuehrle 1d3bdd6a34 added diagram to concepts mv weavedns 2017-07-20 15:31:37 -05:00
abuehrle 5a38e04789 ipam topic order 2017-07-20 15:31:36 -05:00
abuehrle 1f1b22cee7 mv ipam tasks mv weavedns tasks mv image tasks/manage 2017-07-20 15:31:36 -05:00
abuehrle 16ce5eacbb index file for tasks section 2017-07-20 15:31:36 -05:00
abuehrle 69e311d021 menu topic order 2017-07-20 15:31:35 -05:00
abuehrle ea48915007 index files for tasks and manage directories 2017-07-20 15:31:35 -05:00
abuehrle 165c8c1d0f added manage sd and mv using-weave to it 2017-07-20 15:31:35 -05:00
abuehrle b237eaf6bf content from cni-plugin added 2017-07-20 15:31:35 -05:00
abuehrle 4de70e31c6 ordered menu 2017-07-20 15:31:34 -05:00
abuehrle dd29302d57 cni-plugin moved to kubernetes file kube-add moved 2017-07-20 15:31:34 -05:00
abuehrle 4f3cf40e30 index files and subdirectory order 2017-07-20 15:31:34 -05:00
abuehrle 9fdb40c9b8 menu items ordered 2017-07-20 15:31:34 -05:00
abuehrle 3af2a070e3 docker plugin subdirectory of install 2017-07-20 15:31:33 -05:00
abuehrle 6e5f0a8eea ordered menu 2017-07-20 15:31:33 -05:00
abuehrle d0320dd0c6 renamed installing-weave to install moved cloud and launch to install 2017-07-20 15:31:33 -05:00
abuehrle 5f25bba012 initial index file 2017-07-20 15:31:33 -05:00
abuehrle 42e650bba8 menu order 2017-07-20 15:31:32 -05:00
abuehrle c6f29d685c menu order 2017-07-20 15:31:32 -05:00
abuehrle a45c5e1170 menu order 2017-07-20 15:31:32 -05:00
abuehrle 683b4c7c18 menu reorder 2017-07-20 15:31:32 -05:00
abuehrle 1b5d6033b0 menu order 2017-07-20 15:31:31 -05:00
abuehrle c209761689 how it works renamed to concepts 2017-07-20 15:31:31 -05:00
abuehrle 59112209d0 renamed introducing moved features to overview 2017-07-20 15:31:31 -05:00
Bryan Boreham 28ea18d3a6 Remove localhost:8080 fallback for Kubernetes api-server
It was a hack for a badly-configured Kubernetes install: it shouldn't
be necessary, it will only work on an unsecured install, and it
generates confusing error messages when something is really wrong.
2017-07-19 22:59:34 +00:00
Bryan Boreham fac669156e Merge pull request #3046 from weaveworks/update-weave-kube-docs
Update weave-kube documentation
2017-07-19 15:40:52 -07:00
Bryan Boreham 102f4ad4a4 Merge pull request #3064 from weaveworks/wip-2621
Add comments to iptables rules and ipsets
2017-07-19 13:01:09 -07:00
Mike Bryant e10ce2345b Add comments to iptables rules and ipsets
Fixes #2621
2017-07-17 11:00:08 +01:00
abuehrle d06eaf14af add more urls fix others 2017-07-16 14:14:12 -05:00
abuehrle 21623118d3 Merge branch 'docs-reorg' of https://github.com/weaveworks/weave into docs-reorg 2017-07-16 13:20:38 -05:00
abuehrle 4dfcaa470a taks toc - full urls added 2017-07-16 12:48:44 -05:00
abuehrle 9cc98b0ee8 install toc added - full urls 2017-07-16 12:48:44 -05:00
abuehrle acf2b4dc7d rearrange install and launch 2017-07-16 12:48:43 -05:00
abuehrle 029c6f9caf add full urls instead 2017-07-16 12:48:43 -05:00
abuehrle 34767f4986 update links in readme anchors 2017-07-16 12:48:43 -05:00
abuehrle fe852d8519 concepts toc 2017-07-16 12:48:43 -05:00
abuehrle 0eded20bdf test anchor 2017-07-16 12:48:43 -05:00
abuehrle 9ec9e72ade test anchor 2017-07-16 12:48:42 -05:00
abuehrle c9559666ef remove code format from title 2017-07-16 12:48:42 -05:00
abuehrle 81c0d44c09 fixed url with anchor and broken link 2017-07-16 12:48:42 -05:00
abuehrle 2651fe2ed4 replaced Using Weave Net with Launching Weave Net 2017-07-16 12:48:42 -05:00
abuehrle e1e40fc68c replaced getting started guides with tutorials 2017-07-16 12:48:40 -05:00
abuehrle dff0f08cb5 replaced URLs systemd and installing-weave 2017-07-16 12:48:40 -05:00
abuehrle 5483e81d75 misc link replaced topology still going to router-topology 2017-07-16 12:48:40 -05:00
abuehrle 905d923880 replaced URLs for weave proxy section 2017-07-16 12:48:40 -05:00
abuehrle c3d96ca448 replaced URLs for weavedns section 2017-07-16 12:48:39 -05:00
abuehrle 7ea8761685 replaced URLs for ipam section 2017-07-16 12:48:39 -05:00
abuehrle 0e6e5e3a4d replaced URL to weave cloud 2017-07-16 12:48:39 -05:00
abuehrle afbc7aaa14 replaced URLs for host network int. 2017-07-16 12:48:38 -05:00
abuehrle 8cc3179a36 replaced more urls for /site/tasks/manage section 2017-07-16 12:48:38 -05:00
abuehrle 324d013f88 replaced urls for tasks/manage section 2017-07-16 12:48:38 -05:00
abuehrle 70924f6f3a replace URLs for kubernetes section 2017-07-16 12:48:37 -05:00
abuehrle a2602bb712 replaced URLs for install and docker plugins 2017-07-16 12:48:37 -05:00
abuehrle 5fc94ca01d replaced urls /site/installing-weave.md w /site/install/installing-weave.md 2017-07-16 12:48:37 -05:00
abuehrle ddf2c99240 replaced urls /site/how-it-works/ with /site/concepts/ 2017-07-16 12:48:36 -05:00
abuehrle f3e83dcdb9 update how it works url 2017-07-16 12:48:36 -05:00
abuehrle 773aeda980 replaced url for features 2017-07-16 12:48:36 -05:00
abuehrle bea58ef6dc better title for weave cloud and net 2017-07-16 12:48:36 -05:00
abuehrle 35b4fca59f make launch 10 2017-07-16 12:48:35 -05:00
abuehrle afc2f13841 put installing first 2017-07-16 12:48:35 -05:00
abuehrle 4e71e4db86 remove index from concepts title 2017-07-16 12:48:35 -05:00
abuehrle dd1fc02f9f order topic 2017-07-16 12:48:35 -05:00
abuehrle 760a76cbd0 index file for directory 2017-07-16 12:48:34 -05:00
abuehrle a81720d64c topic ordering 2017-07-16 12:48:34 -05:00
abuehrle d0ad4ad022 docker-api mv to tasks 2017-07-16 12:48:34 -05:00
abuehrle 2f9f500ecb moved screencast image to installing 2017-07-16 12:48:34 -05:00
abuehrle 1d09a35bcd moved .dot file need this? 2017-07-16 12:48:33 -05:00
abuehrle e8310ab1b7 index file 2017-07-16 12:48:33 -05:00
abuehrle 3b029896c9 menu topic order 2017-07-16 12:48:33 -05:00
abuehrle 61f83cd463 added diagram to concepts mv weavedns 2017-07-16 12:48:33 -05:00
abuehrle 0c36b87bcc ipam topic order 2017-07-16 12:48:32 -05:00
abuehrle 14e97185b3 mv ipam tasks mv weavedns tasks mv image tasks/manage 2017-07-16 12:48:32 -05:00
abuehrle fa512ee22a index file for tasks section 2017-07-16 12:48:32 -05:00
abuehrle 58dc68d112 menu topic order 2017-07-16 12:48:31 -05:00
abuehrle 7e265100c3 index files for tasks and manage directories 2017-07-16 12:48:30 -05:00
abuehrle 9d0a0253c9 added manage sd and mv using-weave to it 2017-07-16 12:48:30 -05:00
abuehrle e41b5d9a1c content from cni-plugin added 2017-07-16 12:48:30 -05:00
abuehrle 7af82945d9 ordered menu 2017-07-16 12:48:30 -05:00
abuehrle 6e90c56d03 cni-plugin moved to kubernetes file kube-add moved 2017-07-16 12:48:29 -05:00
abuehrle 887d72e45f index files and subdirectory order 2017-07-16 12:48:29 -05:00
abuehrle 3086a6821b menu items ordered 2017-07-16 12:48:29 -05:00
abuehrle 599d5e4863 docker plugin subdirectory of install 2017-07-16 12:48:28 -05:00
abuehrle d59aab3f71 ordered menu 2017-07-16 12:48:28 -05:00
abuehrle d356afd6cf renamed installing-weave to install moved cloud and launch to install 2017-07-16 12:48:28 -05:00
abuehrle 474ff5815b initial index file 2017-07-16 12:48:27 -05:00
abuehrle 5379826662 menu order 2017-07-16 12:48:27 -05:00
abuehrle b551c15f5c menu order 2017-07-16 12:48:27 -05:00
abuehrle 8554f0f896 menu order 2017-07-16 12:48:27 -05:00
abuehrle b8a5d49100 menu reorder 2017-07-16 12:48:26 -05:00
abuehrle 05ed63aaf4 menu order 2017-07-16 12:48:26 -05:00
abuehrle f37f8308c8 how it works renamed to concepts 2017-07-16 12:48:26 -05:00
abuehrle 136c4521d4 renamed introducing moved features to overview 2017-07-16 12:48:26 -05:00
abuehrle 7a34d997aa taks toc - full urls added 2017-07-16 12:41:56 -05:00
abuehrle 6ca9b2c006 install toc added - full urls 2017-07-16 12:40:47 -05:00
abuehrle fdc01a41de rearrange install and launch 2017-07-14 16:57:40 -05:00
abuehrle fb138b54fa add full urls instead 2017-07-14 16:56:43 -05:00
Bryan Boreham efde637e1c Merge pull request #3056 from dlespiau/20170711-weave-instant-help
Make help instantaneous in the weave script
2017-07-14 11:54:32 -07:00
Bryan Boreham 448518d500 Merge pull request #3057 from weaveworks/wip-npc-race-test
Fix weave-npc race condition
2017-07-14 11:11:06 -07:00
Bryan Boreham b562cc9b98 Merge pull request #3055 from weaveworks/issues/2603-document-weave-kube-commands
Add operations section to weave-kube's docs.
2017-07-14 10:05:34 -07:00
Bryan Boreham 7b6a21f612 Merge pull request #3066 from weaveworks/label-weavedb
label weavedb image
2017-07-14 10:01:54 -07:00
Matthias Radestock cf1a1116f4 label weavedb image
Fixes weaveworks/scope#2610
2017-07-14 15:00:46 +01:00
Mike Bryant cbc3d5b04c Don't bypass selector provisioning when not default deny
If we have namespaces Source and Destination, and Destination
contains a NetworkPolicy allowing access from Source, we need
to provision the ipsets for Source and add them to relevant
selectors, even though Source is DefaultAllow.

This also fixes an issue where if the Namespace labels are updated,
that would be ignored.

Fixes #3059
2017-07-14 14:45:41 +01:00
Mike Bryant 219b03cb6b Add regression test for weave-npc race condition 2017-07-14 14:45:41 +01:00
Mike Bryant c33cd2657c Refactor iptables usage in weave-npc to make it testable 2017-07-14 14:45:41 +01:00
abuehrle e26b0663e3 update links in readme anchors 2017-07-13 19:53:14 -05:00
abuehrle 7f93c403e9 concepts toc 2017-07-13 18:25:47 -05:00
abuehrle 4a1c2c5d09 test anchor 2017-07-13 17:39:33 -05:00
abuehrle 8e445f349b test anchor 2017-07-13 17:28:26 -05:00
abuehrle 09984001fc remove code format from title 2017-07-13 17:04:04 -05:00
abuehrle f598338a5f fixed url with anchor and broken link 2017-07-13 16:29:36 -05:00
abuehrle 650adb47fd replaced Using Weave Net with Launching Weave Net 2017-07-13 16:09:04 -05:00
abuehrle ad8a943eb2 replaced getting started guides with tutorials 2017-07-13 15:59:40 -05:00
abuehrle 1b7efab40a replaced URLs systemd and installing-weave 2017-07-13 15:55:10 -05:00
abuehrle 43c608e25c misc link replaced topology still going to router-topology 2017-07-13 15:43:55 -05:00
abuehrle 6aba9411a6 replaced URLs for weave proxy section 2017-07-13 15:41:04 -05:00
abuehrle 1e70992835 replaced URLs for weavedns section 2017-07-13 15:32:15 -05:00
abuehrle 38a84e95ad replaced URLs for ipam section 2017-07-13 15:27:23 -05:00
abuehrle 5492d046d1 replaced URL to weave cloud 2017-07-13 15:18:56 -05:00
abuehrle 16dbd5eea0 replaced URLs for host network int. 2017-07-13 15:16:58 -05:00
abuehrle 098a3c59c7 replaced more urls for /site/tasks/manage section 2017-07-13 15:14:47 -05:00
abuehrle 16272f0d75 replaced urls for tasks/manage section 2017-07-13 15:05:23 -05:00
abuehrle 4e41e422c5 replace URLs for kubernetes section 2017-07-13 14:53:18 -05:00
abuehrle 227d45a40c replaced URLs for install and docker plugins 2017-07-13 14:46:56 -05:00
abuehrle 6bd529ef66 replaced urls /site/installing-weave.md w /site/install/installing-weave.md 2017-07-13 14:35:45 -05:00
abuehrle 61e798d400 replaced urls /site/how-it-works/ with /site/concepts/ 2017-07-13 14:31:48 -05:00
abuehrle d84154326f update how it works url 2017-07-13 14:12:02 -05:00
abuehrle cba793524e replaced url for features 2017-07-13 14:06:34 -05:00
abuehrle 9ec8cb9bf4 better title for weave cloud and net 2017-07-13 12:45:13 -05:00
abuehrle be52e08f2d make launch 10 2017-07-13 12:41:38 -05:00
abuehrle 4edff2f17f put installing first 2017-07-13 12:37:33 -05:00
Marc CARRE ed70e6e344 Remove URLs section.
As discussed internally, this could just create more confusion for the end-user, than bringing benefits for previous users who would potentially wonder why the URLs have changed.
2017-07-13 16:48:33 +01:00
Marc CARRE 920bba2ffd Fix doc regarding git.io short URLs.
GitHub only allows git.io to point to content hosted under github.com, therefore it was not possible to have the short URLs point to Weave Cloud's Launch Generator.
2017-07-13 16:48:33 +01:00
Marc CARRE 2113498348 Replace git.io/weave-kube with cloud.weave.works for manual rollout under Kubernetes <=1.5. 2017-07-13 16:48:33 +01:00
Marc CARRE 8e7e1a3b26 Remove -n kube-system from kubectl apply commands. 2017-07-13 16:48:33 +01:00
Marc CARRE f638fac152 Add operations section to weave-kube's docs. 2017-07-13 16:48:15 +01:00
Marc CARRE d2ebaf3ab7 Make Ansible's docker_install_role overridable.
Currently:
- there is no easy way to change the way we install Docker from Net
- if build-tools' default was to change, Net could break.

This change addresses this situation.
2017-07-13 16:47:22 +01:00
Marc Carré 90575278b0 Merge pull request #3061 from weaveworks/docker-17.6
Fix various CI failures
2017-07-13 16:38:05 +01:00
Bryan Boreham fdbffce93a Use modified docker-py to mask change in Docker error message
Before this change, when using Docker 17.06 we get:
tests/integration/container_test.py:121: in test_create_with_restart_policy
    'You cannot remove a running container', err
    E   AssertionError: 'You cannot remove a running container' not found in u'You cannot remove a restarting container

The modified image simply checks for "You cannot remove a".
2017-07-13 14:00:23 +00:00
Bryan Boreham afac7c4d09 Change test 610 to use a Weaveworks container
Previously we used 'alpine' which had no 'CMD' line, but that changed
upstream, so generate our own trivial image for this purpose.
2017-07-13 13:41:53 +00:00
Bryan Boreham 3fdca717c1 Upgrade to Docker 17.06, including newer tools submodule 2017-07-12 16:00:26 +00:00
abuehrle 3959149077 remove index from concepts title 2017-07-11 23:40:16 -05:00
abuehrle f17053fcee order topic 2017-07-11 20:17:00 -05:00
abuehrle fcbbf89083 index file for directory 2017-07-11 19:35:57 -05:00
abuehrle 3138602661 topic ordering 2017-07-11 19:35:28 -05:00
abuehrle 562f49b3ad docker-api mv to tasks 2017-07-11 19:34:58 -05:00
abuehrle 02328ae43f moved screencast image to installing 2017-07-11 19:14:00 -05:00
abuehrle e132f6c385 moved .dot file need this? 2017-07-11 19:10:01 -05:00
abuehrle 2b8fb49be2 index file 2017-07-11 19:08:10 -05:00
abuehrle 51601a3258 menu topic order 2017-07-11 19:07:51 -05:00
abuehrle 31267f36ed added diagram to concepts mv weavedns 2017-07-11 19:07:23 -05:00
abuehrle 540d1cbf06 ipam topic order 2017-07-11 18:51:37 -05:00
abuehrle 050f671c65 mv ipam tasks mv weavedns tasks mv image tasks/manage 2017-07-11 18:50:52 -05:00
abuehrle 35e2179271 index file for tasks section 2017-07-11 18:28:09 -05:00
abuehrle 52d06513bb menu topic order 2017-07-11 18:27:44 -05:00
abuehrle 124ef94500 index files for tasks and manage directories 2017-07-11 18:27:22 -05:00
abuehrle 166d5bfc5b added manage sd and mv using-weave to it 2017-07-11 18:26:15 -05:00
abuehrle efd290a3be content from cni-plugin added 2017-07-11 17:49:31 -05:00
abuehrle 742ef03495 ordered menu 2017-07-11 17:48:58 -05:00
abuehrle 92a6694ac8 cni-plugin moved to kubernetes file kube-add moved 2017-07-11 17:48:36 -05:00
abuehrle 1354ad1884 index files and subdirectory order 2017-07-11 17:30:26 -05:00
abuehrle 15a4b189f4 menu items ordered 2017-07-11 17:29:24 -05:00
abuehrle 53cf6c2f8c docker plugin subdirectory of install 2017-07-11 17:28:43 -05:00
abuehrle 64518c3bd4 ordered menu 2017-07-11 17:07:17 -05:00
abuehrle 20711cb8bc renamed installing-weave to install moved cloud and launch to install 2017-07-11 17:06:47 -05:00
abuehrle 2914b9d220 initial index file 2017-07-11 16:26:41 -05:00
abuehrle 677c872d5a menu order 2017-07-11 16:25:59 -05:00
abuehrle 015809c83a menu order 2017-07-11 16:25:42 -05:00
abuehrle 092ec8d83d menu order 2017-07-11 16:25:14 -05:00
abuehrle 9d2237cfd4 menu reorder 2017-07-11 16:24:49 -05:00
abuehrle 8b615e58e8 menu order 2017-07-11 16:24:16 -05:00
abuehrle e351d0c3c0 how it works renamed to concepts 2017-07-11 16:23:35 -05:00
abuehrle a943f66afd renamed introducing moved features to overview 2017-07-11 15:49:46 -05:00
Damien Lespiau 3df1a0943c Make help instantaneous in the weave script
There are 3 ways to get help:

  • weave --help
  • weave help
  • weave <command> --help

At the moment, only the first one prints the usage instantaneously, the
others go much further in the script and take quite some time, which is
not idea of impatient users.

Note that "help" only works because it's not a recognized command and
ends up in the default case of "case $COMMAND" (and indeed, "Unknown
weave command 'help'" is displayed). This is because handle_help_arg()
always returns true and so the second part of:

  handle_help_arg "$1" || handle_help_arg "--$1"

is never evaluated.

This commit changes things a bit so all 3 ways to get help are
recognized early, print the usage and exit.
2017-07-11 16:46:42 +01:00
Marc Carré b5759c5b6d Merge pull request #3051 from weaveworks/issues/3049-kube-hostnames
Add back HOSTNAME env var for weave-npc container
2017-07-04 14:28:32 +01:00
Bryan Boreham 6b4c6c84b4 Add back HOSTNAME env var for weave-npc container 2017-07-03 16:41:07 +00:00
Marc CARRE d8222d76d9 Add release v2.0.1 2017-06-29 10:58:27 +01:00
Marc Carré 88a3b41135 Merge pull request #3045 from weaveworks/fix-v2-plugin-release
net-plugin release: swap publish and plugin_publish
2017-06-28 17:32:27 +01:00
Marc Carré fb7aa9298d Merge pull request #3044 from weaveworks/check-disco-blank-token
Don't contact peer discovery back-end unless we have a token
2017-06-28 17:30:03 +01:00
Marc Carré b79cc948b3 Merge pull request #3043 from weaveworks/issues/fastdp-enosupport-fallback
Fix fallback to pcap based bridge when odp is not supported
2017-06-28 17:25:45 +01:00
Marc CARRE e7092612a9 Swap publish and plugin_publish.
Currently our `Makefile` and `bin/release` scripts are such that we effectively do the following when releasing:
```
publish:
  for arch in [amd64 arm arm64]:
    sub-publish:
      clean_bin
      publish
plugin_publish
```
which leads the Docker v2 plugin to contain `arm64` binaries even though we target `amd64`.
Swaping `publish` and `plugin_publish` is a simple way to avoid this.
2017-06-28 17:16:53 +01:00
Bryan Boreham 15c512388d Don't contact peer discovery back-end unless we have a token 2017-06-28 13:34:49 +00:00
Martynas Pumputis f37377264b Fix fallback to pcap based bridge when odp is not supported
The fix ensures that if odp is not supported (usually due to
missing openvswitch, vxlan or vport-vxlan kernel modules),
weaver will create the pcap based bridge instead of crashing.
2017-06-27 18:38:21 +02:00
Bryan Boreham bd44b20b4a Merge pull request #3039 from weaveworks/do-not-merge-args
No longer merge proxy and remaining args
2017-06-27 15:17:39 +01:00
Bryan Boreham e25da3c619 Merge pull request #3042 from weaveworks/latest-yaml-from-launch-generator
Update YAMLs to be what the Launch Generator serves.
2017-06-27 14:58:41 +01:00
Bryan Boreham 3499dbfe09 Merge branch '2.0' 2017-06-27 10:48:05 +00:00
Marc CARRE 81c4a0ffce Temporarily increase tests' timeout. 2017-06-27 10:23:36 +01:00
Marc CARRE a0064f7535 Update YAMLs to be what the Launch Generator serves.
See also:
- https://github.com/weaveworks/launch-generator/issues/133
- https://github.com/weaveworks/launch-generator/pull/134

Command used:
```
$ curl -fsSo prog/weave-kube/weave-daemonset-k8s-1.6.yaml "http://localhost:8080/k8s/v1.6/net?v=latest"
$ curl -fsSo prog/weave-kube/weave-daemonset.yaml "http://localhost:8080/k8s/v1.5/net?v=latest"
```
Annotations then removed.
2017-06-26 17:54:17 +01:00
Marc Carré 79c9eff2b9 Merge pull request #3033 from weaveworks/put-namespace-back-in-yaml
Put kube-system namespace back in the weave-kube yaml
2017-06-26 15:09:18 +01:00
Marc CARRE b8bcf0c87d No longer merge proxy and remaining args.
`proxy_parse_args` is currently called:

- once, all the time
- again, if Docker is configured with TLS.

If a second call to `proxy_parse_args` happens, given the way we append to `PROXY_ARGS` and merge proxy and remaining args, genuine arguments like peers can be mixed with flags/options/etc. hence forming an invalid peers list and crashing Weave Net.
2017-06-26 14:54:04 +01:00
Matthias Radestock 179a560e1d Merge branch '2.0' 2017-06-25 21:17:41 +01:00
Matthias Radestock 2245bd25e9 Merge pull request #3036 from weaveworks/3035-remove-proxyplugin-remnants
remove weave{proxy,plugin} remnants

Fixes #3035.
2017-06-25 21:09:27 +01:00
Matthias Radestock c256daceb0 don't panic when TestMain is invoked as a regular test
Just no-op instead.

This change is necessary because previously a recent build-tools
change no longer excludes prog/* from unit testing since other
projects actually do have genuine tests under there.
2017-06-25 20:49:19 +01:00
Matthias Radestock 73b29050b9 update tools to weaveplugin-free version 2017-06-25 20:49:19 +01:00
Matthias Radestock 162da63522 remove remnants of the weaveproxy and weaveplugin containers 2017-06-25 18:42:48 +01:00
Bryan Boreham 01194ee267 Use weaveworks nettest image instead of nginx in plugin test
so we can ensure it has 'ping' in it
2017-06-25 14:52:27 +00:00
Bryan Boreham d958cff58e Put kube-system namespace back in the weave-kube yaml
Save people getting in to trouble when they don't know to add `-n kube-system`
2017-06-23 16:07:55 +00:00
Bryan Boreham d0662b519f late-breaking additions to 2.0 release 2017-06-23 10:19:33 +00:00
Bryan Boreham d75a96e9ba Mention Rolling Update in instructions 2017-06-23 10:19:10 +00:00
Bryan Boreham bd7ed1b41a Make formatting more consistent with previous versions 2017-06-23 10:18:39 +00:00
Bryan Boreham b5e6d235ba Merge pull request #3019 from unitymind/plugin-v2-ipalloc-range
Ability to set IPALLOC_RANGE via plugin-v2 configuration parameters
2017-06-23 10:40:04 +01:00
Bryan Boreham 3cc537b978 Merge pull request #3028 from weaveworks/issues/3025-track-local-pods-separately
weave-npc: stop ignoring local pods
2017-06-23 10:39:01 +01:00
Bryan Boreham ac0c0db942 Merge branch '1.9' 2017-06-23 09:38:46 +00:00
Bryan Boreham 0affbad976 Anchor names must be quoted 2017-06-23 09:08:22 +00:00
Bryan Boreham ced84955d3 Stop ignoring local pods
This behaviour was breaking the use of pod selectors for the 'from'
part of a rule.

Move checking of local pods into namespace.go so we can maintain
LocalIpSet correctly
2017-06-22 14:16:53 +00:00
Bryan Boreham b86fc67adf Extend test to include a network policy 2017-06-22 14:16:53 +00:00
Bryan Boreham 59de4c3435 Add curl to test image 2017-06-22 14:16:53 +00:00
Bryan Boreham 8e418b8743 More logging for namespace changes 2017-06-22 13:51:05 +00:00
Bryan Boreham f2b003379d Merge pull request #3024 from weaveworks/update-k8s-yaml
Update YAMLs to be what the Launch Generator serves.
2017-06-21 15:43:03 +01:00
Marc CARRE 0d083077ab Update YAMLs to be what the Launch Generator serves.
See also:
- weaveworks/launch-generator/pull/130
- weaveworks/launch-generator/pull/125

Command used:
```
$ curl -fsSo prog/weave-kube/weave-daemonset-k8s-1.6.yaml "https://localhost:8080/k8s/v1.6/net?v=latest"
$ curl -fsSo prog/weave-kube/weave-daemonset.yaml "https://localhost:8080/k8s/v1.5/net?v=latest"
```
Annotations then removed.
2017-06-21 14:41:59 +01:00
Marc CARRE db1a94a02c Add release v2.0.0 2017-06-20 16:42:04 +01:00
Bryan Boreham fdbc7dfe04 Merge pull request #3017 from weaveworks/add_weave_cloud_msg
Update references to Weave Cloud
2017-06-20 12:18:05 +01:00
Bryan Boreham 70f004cc62 Merge pull request #3018 from Shimi/patch-2
modify tolerations to match any taint
2017-06-20 12:02:56 +01:00
Vitaliy V. Shopov c02cb45c6c Ability to set IPALLOC_RANGE via plugin-v2 configuration parameters 2017-06-17 10:36:02 +10:00
Bryan Boreham 8dccc88613 Merge pull request #3000 from weaveworks/issues/2990-empty-selinuxoptions-by-default
Kubernetes' seLinuxOptions are empty by default
2017-06-16 15:44:44 +01:00
Bryan Boreham bb5914dbce Merge branch '1.9' 2017-06-16 14:50:13 +00:00
Bryan Boreham 4698ec1a37 Put the Ruby version back to 2.3.0 until we update Netlify 2017-06-16 14:38:54 +00:00
Bryan Boreham e29c98faad Merge pull request #2992 from weaveworks/attach-with-safe-netns
Remove unsafe netns change in proxy
2017-06-16 14:36:15 +01:00
Bryan Boreham 444d6be6c9 Document the requirement for 'nsenter' 2017-06-16 13:21:07 +00:00
Bryan Boreham 28aa181480 Move setting up addresses for a container, into weaveutil-invoked function
This means we only change netns by execing nsenter: changing netns in
Go is unsafe for long-running processes like the proxy.
2017-06-16 13:19:08 +00:00
Bryan Boreham 97e0fcb765 Refactor: move SetupIface code from weaveutil to net package 2017-06-16 13:19:08 +00:00
Bryan Boreham 052fdb30c0 Merge pull request #3001 from weaveworks/issues/2614-password-via-k8s-secret
Document Launch Generator's password-secret query parameter
2017-06-16 10:07:10 +01:00
Marc CARRE 2e2b667864 Document Launch Generator's seLinuxOptions.NAME=VALUE. 2017-06-16 09:06:26 +00:00
Marc CARRE 666631134c Update YAMLs to be what the Launch Generator serves.
See also: weaveworks/launch-generator/pull/117

Command used:
```
$ curl -fsSo prog/weave-kube/weave-daemonset-k8s-1.6.yaml "https://cloud.weave.works/k8s/v1.6/net?v=latest"
$ curl -fsSo prog/weave-kube/weave-daemonset.yaml "https://cloud.weave.works/k8s/v1.5/net?v=latest"
```
Annotations then removed.
2017-06-16 09:06:26 +00:00
Bryan Boreham de4cfe2b8b Merge branch '1.9' 2017-06-15 17:28:43 +00:00
Bryan Boreham a7ebe53cfa Add release v1.9.8 2017-06-15 17:05:11 +00:00
Shimi Kiviti 66a569fc40 modify tolerations to match any node
Currently weave doesn't run on nodes with tolerations except the master
The suggested code change it to run on all nodes
2017-06-15 15:32:50 +03:00
pidster 3a646ffdba change cloud URL in weave script, again, because typo 2017-06-14 15:45:52 +01:00
pidster 7cfd71c0bd change cloud URL in weave script 2017-06-14 15:44:53 +01:00
pidster 3265d60d52 Update references to weave cloud 2017-06-14 15:21:25 +01:00
Bryan Boreham 640b417b39 Merge branch '1.9' 2017-06-14 13:57:08 +00:00
Marc Carré b655a3aede Merge pull request #3014 from weaveworks/issues/3011-allow-non-pod-source
Allow any non-local traffic onto the weave bridge
2017-06-14 14:52:11 +01:00
Bryan Boreham 819b395ae4 Temporarily raise the test timeout
Docker 1.11 seems much slower at the pull tests than Docker 1.13
while we investigate that, raise the timeout to allow tests to pass
2017-06-14 13:14:06 +00:00
Bryan Boreham 2584335b11 Allow any non-local traffic onto the weave bridge
If it's destined for a pod on another node it will be checked again
when it reaches that other node.  The previous version was rejecting
traffic coming in from outside the cluster.
2017-06-12 17:00:57 +00:00
Marc Carré 4e5a8f348a Merge pull request #3013 from weaveworks/fix-claim
Pass check-alive flag on claim for container
2017-06-12 15:31:51 +01:00
Bryan Boreham f91a9c2562 Fix test: committed image embeds WEAVE_CIDR
so we cannot run two of those containers at the same time.
Fixed by stopping the first one before we start the second.
2017-06-12 14:03:53 +00:00
Bryan Boreham ea098ac53e Only retain IP addresses for running containers 2017-06-12 14:03:53 +00:00
Bryan Boreham a0d0b00938 Pass check-alive flag on claim for container 2017-06-12 14:03:53 +00:00
Bryan Boreham 31a4657467 Update COVERAGE sed to latest daemonset which has nonempty env 2017-06-12 13:55:21 +00:00
Bryan Boreham 2ddb8fcec3 Merge branch '1.9' 2017-06-12 09:09:32 +00:00
Bryan Boreham 21d4fff450 Update broken link to Docker docs 2017-06-12 09:42:22 +01:00
Marc CARRE 00036ec277 Merge remote-tracking branch 'origin/1.9' 2017-06-09 08:30:34 +01:00
Marc Carré a5d7fb66f0 Merge pull request #3010 from weaveworks/issues/3003-anonymous-claim
Fix use of '_' as container ID in claim outside range
2017-06-09 08:30:13 +01:00
Bryan Boreham b01a204c1f Check who previously owned an address claimed outside the range 2017-06-08 16:25:09 +00:00
Bryan Boreham e9310eba98 Don't use '_' as container ID in claim outside range
And added unit test for various claim-without-ID situations
2017-06-07 16:38:19 +00:00
Bryan Boreham 69285270e5 Bump Ruby version
2.3.4 is pre-installed by CircleCI, whereas 2.3.0 isn't
2017-06-07 13:01:15 +00:00
Marc CARRE 6f96d6d63e Document Launch Generator's password-secret query parameter.
See also: weaveworks/launch-generator#118
2017-06-06 10:52:06 +01:00
Marc Carré 91f476d2c6 Merge pull request #2981 from deitch/document-entrypoints
First revision of how weave utils get launches
2017-06-05 13:09:56 +01:00
Bryan Boreham 7871a0b7a4 Merge branch 1.9 2017-06-01 15:03:59 +00:00
Bryan Boreham 6bd11a426e typo 2017-06-01 14:28:10 +00:00
Bryan Boreham 1abdc3afcf Add release v1.9.7 2017-06-01 13:51:06 +00:00
Bryan Boreham b8f98a5387 Merge pull request #2996 from Bregor/issues/2995-npc-and-hostname_override
Weave-NPC should get hostname from K8s Downward API.
2017-06-01 14:33:22 +01:00
Maxim Filatov cb3b858df6 Weave-NPC should get hostname from K8s Downward API.
It is necessary in case when kubelet's args includes `--hostname_override=`.
Without this change, pods on hostname overriding kubelets will never be local,
and all pod's traffic will be blocked.
2017-05-31 18:06:17 +03:00
Marc Carré d7025e7dfa Merge pull request #2873 from weaveworks/gh-issue-template
Template for GitHub issues
2017-05-31 15:54:08 +01:00
Bryan Boreham b2b9c47a50 Simplified 2017-05-31 14:34:41 +00:00
Bryan Boreham 211003f542 Merge branch '1.9' 2017-05-30 16:43:32 +00:00
Avi Deitcher f8227c3f47 First revision of how weave utils get launches 2017-05-30 19:19:38 +03:00
Bryan Boreham 258d764af8 Merge branch '1.9' 2017-05-30 14:31:51 +00:00
Bryan Boreham 37526728e0 Merge branch '1.9' 2017-05-30 13:55:49 +00:00
Bryan Boreham 7f4ad03a5c Remove mention of enable-encryption mode - it's too insecure 2017-05-26 16:23:55 +00:00
Marc Carré d60ad1f40a Merge pull request #2991 from weaveworks/remove-init-peer-count
Remove deprecated --init-peer-count option
2017-05-26 16:39:19 +01:00
Bryan Boreham 5106317e5d Remove deprecated --init-peer-count option
Since this was the last deprecated option, remove all code to generate
deprecation warnings in the weave script.
2017-05-26 15:19:27 +00:00
Bryan Boreham a5e4a19f06 Merge pull request #2903 from weaveworks/issues/2754-launch-generator-for-net
Update weave-kube docs and YAML files to leverage Launch Generator
2017-05-26 15:48:14 +01:00
Marc CARRE 067ce6de9f Update Weave-Kube daemonset YAML files using Launch Generator.
Note that given the YAML's structure is different from previous version, indentation of `COVERAGE_ARGS` had to change (+4 whitespaces to each line).
Commands used:
```
$ curl -fsS https://frontend.dev.weave.works/k8s/v1.5/net?v=latest > prog/weave-kube/weave-daemonset.yaml
$ curl -fsS https://frontend.dev.weave.works/k8s/v1.6/net?v=latest > prog/weave-kube/weave-daemonset-k8s-1.6.yaml
```
Annotations removed from Launch Generator's files:
```
      annotations:
        cloud.weave.works/launcher-info: |-
          {
            "server-version": "master-050965d",
            "original-request": {
              "url": "/k8s/v1.6/net?v=latest",
              "date": "Thu May 25 2017 13:16:43 GMT+0000 (UTC)"
            },
            "email-address": "support@weave.works"
          }
```
and
```
      annotations:
        cloud.weave.works/launcher-info: |-
          {
            "server-version": "master-050965d",
            "original-request": {
              "url": "/k8s/v1.5/net?v=latest",
              "date": "Thu May 25 2017 13:16:43 GMT+0000 (UTC)"
            },
            "email-address": "support@weave.works"
          }
```
2017-05-26 14:19:26 +01:00
Marc CARRE 9facab53b7 Add Launch Generator to weave-kube docs.
Details:
- Update weave-kube docs to avoid explicit versioning by leveraging the Launch Generator.
- Update weave-kube docs to mention YAML customisation via the Launch Generator.
- Warn about potential backward incompatibility of the generated YAML, and how to ensure YAML and Net versions are compatible.
2017-05-26 14:17:41 +01:00
Marc Carré 4f20f545dc Merge pull request #2989 from weaveworks/remove-deprecated-options
Remove deprecated flag versions
2017-05-23 18:27:12 +01:00
Bryan Boreham 4bbf84f551 Merge branch '1.9' 2017-05-23 17:00:22 +00:00
Bryan Boreham c617612794 Remove deprecated flag versions 2017-05-23 16:49:13 +00:00
Marc Carré 0c89bbb8df Merge pull request #2967 from weaveworks/issues/2610-host-volume
Change weavedb from an emptyDir to a hostPath volume
2017-05-23 17:19:04 +01:00
Bryan Boreham a7206bee95 Merge branch '1.9' 2017-05-23 15:19:18 +00:00
Marc CARRE 0e3a749f69 Merge remote-tracking branch 'origin/remove-wordepress' 2017-05-23 12:04:34 +01:00
Marc CARRE 535bf9b066 Merge remote-tracking branch 'origin/use-fixed-version-of-shfmt' 2017-05-23 11:31:55 +01:00
Bryan Boreham ceb7206117 Merge pull request #2988 from mattjtodd/patch-2
Fix Network Commands in plugin-v2 doc
2017-05-23 09:23:47 +01:00
Matt Todd 1273157ace Update plugin-v2.md
Fixed network create command statement ordering.
2017-05-22 20:01:52 +01:00
Marc Carré 5a92200dc6 Merge pull request #2964 from weaveworks/issues/plugin-v2-docs
Add plugin-v2 (net-plugin) docs
2017-05-22 16:10:48 +01:00
Bryan Boreham d021e61dfa Update troubleshooting page to match code 2017-05-22 14:52:29 +01:00
Bryan Boreham 3ae505d6c6 More accessible reference for v2 plugins 2017-05-22 14:52:29 +01:00
Bryan Boreham a1ddb336c1 Make it clear that only one of the two plugins works without a cluster store 2017-05-22 14:52:29 +01:00
Martynas Pumputis 646ac3c74d Add plugin-v2 (net-plugin) docs 2017-05-22 14:52:29 +01:00
Bryan Boreham d383a29e00 Merge pull request #2945 from weaveworks/issues/1642-proxy-merge-docs
Update docs following merge of proxy & router
2017-05-22 13:24:48 +01:00
Marc Carré b44e295562 Merge pull request #2979 from weaveworks/issues/2622-npc-local-node-only
weave-npc to check local addresses only
2017-05-19 16:48:30 +01:00
Bryan Boreham 8a1f8d549e Let through connections from local pods to non-local pods
This means we only filter connections at the destination end,
which is a better match for the ingress-only rules.
2017-05-19 15:17:20 +00:00
Bryan Boreham a2b674e094 Ignore updates for pods on other nodes 2017-05-19 15:17:20 +00:00
Bryan Boreham c4796dcdf5 Refactor: move logging of ipset entries down to ipset package 2017-05-19 15:17:20 +00:00
Bryan Boreham 992b4a65df Refactor creation of base iptables rules 2017-05-19 15:17:20 +00:00
Bryan Boreham 6928929bc9 Install rules allowing outward traffic in npc mode 2017-05-19 15:16:02 +00:00
Bryan Boreham 508b424234 Add test for outward traffic from weave-kube 2017-05-19 15:16:02 +00:00
Marc Carré 7f68a96f75 Merge pull request #2918 from weaveworks/network-tester
Add a network test that isn't ping
2017-05-19 16:15:17 +01:00
Bryan Boreham 535e22e5f8 Wait for nodes to be ready before starting pods
Otherwise we can schedule all pods on the same node, which isn't such a good test
2017-05-19 11:47:57 +00:00
Bryan Boreham 348a926af4 Use network-tester image in Kubernetes test 2017-05-19 11:47:57 +00:00
Bryan Boreham aa84c4788a Add a network test that isn't ping 2017-05-19 11:47:57 +00:00
Bryan Boreham 66293e8caa Factor out 'wait_for_x' loop to reduce duplication 2017-05-19 11:47:57 +00:00
Marc Carré 1e60cff2ef Merge pull request #2977 from weaveworks/issues/2975-chain-race
Don't clear WEAVE-NPC chain in weaver
2017-05-18 11:22:10 +01:00
Bryan Boreham 701519a15c Merge branch '1.9' 2017-05-18 10:18:39 +00:00
Bryan Boreham 3cb6569d55 Don't clear WEAVE-NPC chain here; it is controlled by weave-npc.
We don't get a very useful error object back from go-iptables and I
didn't feel like parsing the message, so just ignore all errors.
It would be racy to try to check if WEAVE-NPC existed before calling
NewChain.
2017-05-18 09:29:33 +00:00
Bryan Boreham bebaa48520 Change weavedb from an emptyDir to a hostPath volume
EmptyDir has the same lifetime as the pod, whereas we want our
persistence to extend past that, e.g. when Weave Net is upgraded.

`weave reset` cleans out the file.

We assume that /var/lib is writable.
2017-05-17 12:38:24 +00:00
Bryan Boreham af246225a9 Merge pull request #2974 from weaveworks/issues/net-plugin-makefile
Do not remove sigproxy and docker from net-plugin build image
2017-05-17 11:28:07 +01:00
Martynas Pumputis 582a792c71 Merge pull request #2966 from weaveworks/issues/2956-simplify-running
Simplify checks for plugin running

Fixes #2956 #2709
2017-05-17 12:56:31 +03:00
Martynas Pumputis 98c4bd9ee5 Do not remove sigproxy and docker from net-plugin build img
The #2954 PR has changed the base image of weaveworks/weave which no
longer includes sigproxy and docker client.
2017-05-17 12:45:20 +03:00
Bryan Boreham 933b395de4 Report plugin version status via the Config object 2017-05-17 09:28:34 +00:00
Bryan Boreham 4f485f856b Factor out Plugin variables into Plugin and plugin.Config structs 2017-05-17 09:27:40 +00:00
Bryan Boreham 280651da9c Create constant for 'weave' network name and move inside if-statement for weavemesh 2017-05-17 09:27:40 +00:00
Bryan Boreham 77201e949d Don't check if weave is running in protect_against_docker_hang
Since it is only called in contexts where we have already checked that.
We don't need the detail of whether plugin is enabled; if it's not
running then it's ok to remove those socket files.
2017-05-17 09:27:40 +00:00
Bryan Boreham 292a50a891 Don't check if the plugin is enabled before trying to remove the default 'weave network'
If the plugin wasn't enabled then that network shouldn't exist.
If the network 'weave' doesn't exist then util_op remove-plugin-network will do nothing.
If it does exist for some reason then docker will pause for a while and remove it anyway.
2017-05-17 09:27:40 +00:00
Bryan Boreham a36fc867d1 Formatting of status message 2017-05-17 09:27:39 +00:00
Bryan Boreham def9f2d407 Check if weave is running for any reason before launching 2017-05-17 09:27:39 +00:00
Bryan Boreham b0da4f6b91 Move proxy and plugin status from shell to Go
In the process we stop printing out the `PLUGIN_FULL_NAME`, but that
is assumed to be something the user can figure out from `docker plugin ls`
2017-05-17 09:27:22 +00:00
Marc CARRE cbf1230f6d Update docs following merge of proxy & router.
Notes:
- Deleted trailing whitespaces on modified files.
- Added documentation for launch --proxy=false.
2017-05-16 08:57:17 +01:00
Marc Carré 71d6e881f2 Merge pull request #2954 from weaveworks/issues/2953-reorg-images
Issues/2953 reorg images
2017-05-15 16:25:58 +01:00
Marc Carré da40771739 Merge pull request #2963 from weaveworks/issues/net-plugin-latest-release-tag
Use :latest_release tag for net-plugin
2017-05-15 16:06:12 +01:00
Martynas Pumputis 694314cc00 Use :latest_release tag for net-plugin
As for some reasons Docker Store does not allow us to use :latest.
2017-05-15 15:38:21 +01:00
Bryan Boreham 3025738377 Extract pluginNameFromAddress() function 2017-05-15 13:33:17 +00:00
Bryan Boreham cbe0f4e6e5 Merge branch '1.9' 2017-05-15 12:44:08 +00:00
Marc Carré e0088e0252 Merge pull request #2960 from weaveworks/remove-proxy-status-sock
Remove proxy status.sock
2017-05-15 13:26:25 +01:00
Bryan Boreham e0bb49aa23 Don't crash on nil proxy in StatusHTTP 2017-05-15 11:32:20 +00:00
Bryan Boreham 81d79a64e6 Blank proxy_addrs should be a failure 2017-05-15 11:31:14 +00:00
Bryan Boreham 4f08879321 Multiple proxy addresses need to be all on one line
For some reason the previous version was de-newlined by the shell and
the new version isn't. Since I can't figure out the exact reason the
shell is now behaving differently (man page says it depends on the
quoting that is in effect) I brute-force it with 'tr'.
2017-05-15 10:17:35 +00:00
Bryan Boreham 6d6394c408 Don't say 'stop-router' in error message 2017-05-15 09:55:46 +00:00
Bryan Boreham bf3ecaf48a Remove proxy status.sock 2017-05-13 16:31:16 +01:00
Bryan Boreham 6ba2bf80b8 Remove some duplication between stop and reset 2017-05-13 16:14:02 +01:00
Bryan Boreham 9f4030cdb6 Move AWSVPC/IPAM check to Go code
The weave script check was broken in an earlier commit.
The Go error message is less specific because it checks more cases.
2017-05-13 14:34:29 +01:00
Bryan Boreham cce818995a Remove unused variable 2017-05-13 14:34:18 +01:00
Bryan Boreham 1e2dc43df6 Don't check docker version when run --local
The standard case for --local is when the weave script in the weaveexec container
is run by the weave script, which has just checked the version.

--local is also used from weave-kube where we don't mount the docker socket and
therefore cannot check.

Since --local is undocumented we will not worry about any other cases; the worst
that can happen is a confusing error message.
2017-05-13 13:52:42 +01:00
Bryan Boreham 06caf03d70 Need the workdir for weave container too 2017-05-12 16:51:39 +00:00
Bryan Boreham 7226b26e8e Reorganise Docker image layers to slim weave-kube 2017-05-12 15:50:57 +00:00
Marc Carré 7c72d69e2f Merge pull request #2951 from weaveworks/cleanup-args
Clean up some argument parsing in weave script
2017-05-12 14:49:43 +01:00
Marc Carré bc1d6c47ba Merge pull request #2947 from weaveworks/issues/1940-remove-proxy-attach-dep
Attach containers from Proxy using Go code
2017-05-12 14:49:20 +01:00
Bryan Boreham 8ec0e025d3 Don't need to parse --no-restart twice 2017-05-12 13:25:50 +00:00
Bryan Boreham 9f40d913c9 No special parsing needed for plugin argument 2017-05-12 13:24:59 +00:00
Bryan Boreham 3595c71d8b No special parsing needed for DNS arguments 2017-05-12 13:24:39 +00:00
Bryan Boreham 9740478151 Merge pull request #2950 from weaveworks/issues/better-plugin-v2-detection
Better plugin-v2 detection
2017-05-12 13:31:01 +01:00
Bryan Boreham 442a55d539 Update comment to reflect ubuntu->debian change 2017-05-12 12:12:21 +00:00
Bryan Boreham 01fce0c6b1 Merge branch '1.9' 2017-05-12 12:10:12 +00:00
Martynas Pumputis 0e3ac00ff5 Fix DriverName for plugin-v2
Print the full plugin-v2 name which might include a registry name.

Also, do not print error from "proxy_addrs".
2017-05-12 14:22:39 +03:00
Martynas Pumputis 2285942384 Add better detection for plugin-v2 (net-plugin)
The problem is that the plugin name is prefixed with a registry name.
So, if the plugin is fetched from Docker Store, its name will be
"store/weaveworks/net-plugin".

The detection function does an exact match on "weaveworks/net-plugin",
so in the Docker Store case, the presence of the plugin cannot be
detected.
2017-05-12 13:56:56 +03:00
Bryan Boreham 0273491e6e Pass check-alive flag to IPAM API 2017-05-12 06:56:52 +00:00
Bryan Boreham b1917d909a Move proxy attach from shell to Go
Note we don't need to propagate shell-script env vars now
2017-05-12 06:56:52 +00:00
Bryan Boreham edbf85655a Move rewrite /etc/hosts from shell to Go 2017-05-12 06:56:52 +00:00
Bryan Boreham be917eb86b Refactor: introduce runTransientContainer function
also specify that it needs no container network
2017-05-12 06:56:52 +00:00
Bryan Boreham 0a2521e7a4 Introduce StubProxy() so weaveutil can call functions on it
implies change type of docker client to weavedocker

so we can call things like Info() on it
2017-05-12 06:56:52 +00:00
Bryan Boreham 1b8d115b63 Refactor: make weave API a part of the proxy struct 2017-05-12 06:56:52 +00:00
Marc Carré 70929cec57 Merge pull request #2946 from weaveworks/ready-aim-fire
Wait until ready; make test 810 more reliable
2017-05-11 19:14:00 +01:00
Bryan Boreham 7611cd963c Don't return OK from status until all parts are ready 2017-05-11 14:02:45 +00:00
Bryan Boreham 3e0eb4ac1e Move creation of default network from weaver to plugin
This way it is more likely that we create it after the plugin is up
and running.
2017-05-11 13:59:29 +00:00
Bryan Boreham f8d501ae50 Specify fields when creating WeaveStatus object 2017-05-11 13:29:28 +00:00
Bryan Boreham cb614f01c3 Fix message when IPAM has pending allocations
It could be because we are waiting for a peer, or it could be because
a subnet is exhausted and we need some local containers to die.
2017-05-10 15:47:49 +00:00
Marc Carré 9be11d9cf0 Merge pull request #2942 from weaveworks/remove-weave-create-bridge
Remote deprecated create-bridge command
2017-05-10 12:28:53 +01:00
Bryan Boreham 8ca83de332 Merge pull request #2936 from weaveworks/issues/1642-merge-proxy
Merge proxy and router into one single process.
2017-05-10 11:57:21 +01:00
Bryan Boreham 89d3fedcd4 Qualify some options as applying to the proxy 2017-05-10 10:25:36 +00:00
Bryan Boreham 71ca91db09 Handle --awsvpc implies --no-multicast-route in Go code 2017-05-10 10:25:36 +00:00
Marc CARRE 5cf973f03a Add --proxy option to enable/disable proxy.
Weave Net initially had the ability to start a single component at a time with `launch-proxy` and `launch-router`.
This change enables this again via `--proxy=false` despite the merge of the proxy and the router.
Note that by default:
- `launch` passes `--proxy` which enables the proxy and keeps behaviour consistent with `launch` pre-merge,
- `weaver` defaults `--proxy` to `false` which disables the proxy and keeps behaviour consistent with `weaver` pre-merge (as it was `weaveproxy`'s responsibility).
2017-05-10 10:25:36 +00:00
Marc CARRE 2c7693b2c5 Fix tests following proxy merge.
Remove tests of situations that don't exist any more and fix the following tests:

- Fix test 660: pass arguments in correct order.
- Fix test 620: no double launch, weave stop instead of kill -9.

  - Now that router and proxy have been merged, we should only call `weave launch` once.
  - `sudo kill -9` was introduced because we previously had `docker kill` (see: http://github.com/weaveworks/weave/commit/cb73b738621d57727072ae998cdeaec337f23a1a), because we had no `weave stop-proxy` yet (see: http://github.com/weaveworks/weave/commit/e31f21a6d224d61de1d8a940ea4b0b45cebc9723). Pre-proxy-merge, this should just have been `weave stop-proxy`, and now that router and proxy have been merged, we should just call `weave stop`.

- Fix test 650: no double launch.
- Fix test 630: remove redundant case & assertions.
- Fix test 090: remove irrelevant assertions.

PING
2017-05-10 10:25:36 +00:00
Marc CARRE 43249a8d39 Change all launch-*/stop-* commands to launch/stop.
Given `proxy` & `router` processes have been merged, `launch-proxy`,
`launch-router`, `stop-proxy`, `stop-router` do not make sense any more, and
should just be `launch` and `stop` with the appropriate flags.
2017-05-10 10:25:36 +00:00
Marc CARRE b654ac178c Merge proxy and router/weaver processes.
Note: we no longer need to detect awsvpc when launching.
The "AWS VPC" mode is now set via the `--awsvpc` flag.
Before we had to "detect" it when the proxy was potentially started
later, after the router had started.

We drop WEAVEPROXY_DOCKER_ARGS as obsolete.
2017-05-10 10:25:23 +00:00
Marc CARRE ccac18b21c Proxy pre-merge refactoring. 2017-05-10 10:24:19 +00:00
Bryan Boreham 8a5fef98ab Remote deprecated create-bridge command 2017-05-09 15:10:42 +00:00
Bryan Boreham c85fff8f23 Fix outdated comment 2017-05-09 14:27:24 +00:00
Bryan Boreham fc57e72853 Merge pull request #2941 from weaveworks/remove-with-dns-flag
Remove deprecated flag --with-dns.
2017-05-09 14:25:05 +01:00
Marc CARRE ce94e69fd5 Clean-up: remove deprecated flag --with-dns. 2017-05-09 13:56:23 +01:00
Marc CARRE b46ccc0937 Remove brackets from condition in protect_against_docker_hang. 2017-05-09 11:11:21 +01:00
Bryan Boreham e89fc8f66a Merge pull request #2929 from weaveworks/issues/2906-plugin-v2-docker-sock
Work around missing docker.sock in plugin-v2
2017-05-09 10:14:47 +01:00
Bryan Boreham ad4fe86285 Merge branch '1.9' 2017-05-09 09:05:38 +00:00
Martynas Pumputis 34ec7bd1c9 Do not populate network info map in plugin-v2
Avoids unnecessary locking.
2017-05-08 23:47:40 +03:00
Bryan Boreham 9a90898c7d Merge branch 1.9 2017-05-05 20:54:46 +01:00
Bryan Boreham 8e80cd1441 Patch wordepress on all kinds of build 2017-05-05 20:53:18 +01:00
Martynas Pumputis d5d45de5a4 Get rid of ipam modes in plugin-v2
plugin-v2 is not going to be used with Docker IPAM in most cases,
so there is no need to complicate the code with ipam mode selection.
2017-05-05 17:25:17 +00:00
Martynas Pumputis 2ebd358aeb Workaround missing docker.sock in plugin-v2
"docker.sock" is used to access Docker API which is required to:

1. subscribe to Docker events to configure-arp,
2. query Docker network info to detect whether multicast should be
   enabled.
3. get list of Swarm peers before starting the plugin.

(1) is currently not implemented.

(2) is replaced by WEAVE_MULTICAST env var which
can enable multicast for all Weave networks created by
the plugin (not ideal, but better than nothing).

(3) is fixed by not removing "restart.sentinel".
2017-05-05 17:25:17 +00:00
Bryan Boreham bb66b6161a Merge branch '1.9' 2017-05-05 17:23:01 +00:00
Bryan Boreham f7130b8c21 Merge pull request #2932 from weaveworks/issues/fix-protect-against-docker-hang
Fix protect_against_docker_hang
2017-05-05 17:31:20 +01:00
Martynas Pumputis a497e1ab8a Fix protect_against_docker_hang
Check not only for plugin-v2 but also for plugin-v1, as both
create the same plugin sockets (weave.sock and weavemesh.sock).
2017-05-05 17:14:50 +01:00
Marc CARRE e1ff2197c0 Fix conflict accidentally missed when merging 1.9. 2017-05-04 12:20:26 +01:00
Bryan Boreham f684ea563d Merge branch '1.9' 2017-05-04 11:13:46 +00:00
Bryan Boreham 88cb871654 Merge pull request #2922 from weaveworks/coc
Add code-of-conduct.md pointing to CNCF CoC
2017-05-04 09:38:56 +01:00
Marc CARRE 507e734d1a Merge remote-tracking branch 'origin/1.9'
- PR #2926 - Branch issues/2808-improve-hairpin-messages - Fixes #2808.
- PR #2907 - Branch issues/2771-checkpoint-net-modes - Fixes #2771.
2017-05-03 20:28:31 +01:00
Bryan Boreham cb8599ebd5 One more doc to update 2017-05-03 16:36:43 +00:00
Bryan Boreham 7714952574 Merge branch '1.9' 2017-05-03 16:35:42 +00:00
Ilya Dmitrichenko aaa974353a Use absolute path for links to other pages 2017-05-03 16:47:37 +01:00
Ilya Dmitrichenko 1cca9d6d79 Fix broken link in docs 2017-05-03 16:41:26 +01:00
Marc CARRE d28b1dcd9f Add template for GitHub issues. 2017-05-02 18:21:20 +01:00
Marc Carré e4cab53a11 Merge pull request #2920 from weaveworks/issues/2919-move-plugin-network-create
Move plugin network creation from shell script to Go
2017-05-02 17:26:50 +01:00
Marc Carré c342bc4188 Merge pull request #2923 from weaveworks/kubernetes-1.6.2
Bump Kubernetes to 1.6.2 for smoke-tests
2017-05-02 15:54:30 +01:00
Bryan Boreham 73a0df56b2 Bump Kubernetes to 1.6.2 2017-05-02 12:49:21 +01:00
Marc CARRE e0303a0dda Merge remote-tracking branch 'origin/1.9' 2017-05-02 11:53:53 +01:00
Bryan Boreham 280a0fed69 Add code-of-conduct.md pointing to CNCF CoC 2017-05-02 08:55:32 +00:00
Bryan Boreham 264a2cd2ad Remove plugin socket from mounted host directory 2017-04-27 22:17:37 +00:00
Bryan Boreham 907ba8f53b Quote arg in test function 2017-04-27 21:56:04 +00:00
Bryan Boreham d2cbb2749e Move plugin network creation from shell script to Go
In the process, use the default subnet instead of the whole IP
allocation range.
2017-04-27 17:07:59 +00:00
Bryan Boreham eab5ec206a Merge branch '1.9' 2017-04-27 14:29:29 +00:00
Ilya Dmitrichenko fa8753cab3 Merge pull request #2899 from weaveworks/netlify
Add website preview via Netlify
2017-04-27 12:52:51 +01:00
Ilya Dmitrichenko 9459d4b739 Add website preview 2017-04-27 12:14:50 +01:00
Bryan Boreham f517a09f0f Create WEAVE-NPC chain in the correct table 2017-04-26 17:04:36 +00:00
Bryan Boreham 34642a04a4 Merge pull request #2914 from weaveworks/upgrade-go-1.8.1
Upgrade Go version to 1.8.1.
2017-04-26 15:51:18 +01:00
Marc CARRE 4bb4d943ba Please ./tools/lint -nocomment -notestpackage.
Fixes:
- `test/run-integration-tests.sh:160:75: arithmetic expressions must consist of names and numbers`
- `test/run-integration-tests.sh:265:56: arithmetic expressions must consist of names and numbers`
- `test/run-integration-tests.sh:295:61: arithmetic expressions must consist of names and numbers`
- `test/run-integration-tests.sh:309:49: arithmetic expressions must consist of names and numbers`
- `test/run-integration-tests.sh:316:41: arithmetic expressions must consist of names and numbers`
- `test/run-integration-tests.sh: run shfmt -i 4 -w test/run-integration-tests.sh`

See also: https://circleci.com/gh/weaveworks/weave/8685
2017-04-26 14:51:53 +01:00
Marc CARRE db855715ab Upgrade Ansible's default Go version to 1.8.1. 2017-04-26 14:51:49 +01:00
Marc CARRE c27e4d020d Upgrade Go version to 1.8.1. 2017-04-26 12:21:50 +01:00
Bryan Boreham a16ad4d6e6 Merge pull request #2913 from weaveworks/remove-old-logic
Remove obsolete validation and warning
2017-04-25 14:22:26 +01:00
Marc CARRE 33ce8c5060 Remove obsolete validation and warning.
This logic was added for backward compatibility and to warn users about changes made ~2 years ago.
Given we are planning a 2.0 release for Weave Net, such logic is now irrelevant and can be removed.
2017-04-25 13:59:05 +01:00
Marc Carré f2568627af Merge pull request #2910 from weaveworks/rename-router-bridge
Rename router.Bridge to router.InjectorConsumer
2017-04-25 13:48:15 +01:00
Bryan Boreham 334974472d Rename router.Bridge to router.InjectorConsumer
since what it does it injects and consumes packets, and something else
entirely does bridging.
2017-04-25 11:03:32 +01:00
Marc Carré 8227a3f67c Merge pull request #1958 from weaveworks/issues/1940-remove-proxy-attachrouter-dep
Use netlink instead of shelling out to `weave attach-router`
2017-04-25 10:37:52 +01:00
Bryan Boreham 4f7d476907 Only do set-up on bridge/datapath devices once at creation time
This is a change to the previous behaviour, but makes the code easier
to read and seems more sensible.
2017-04-24 16:48:19 +00:00
Bryan Boreham a731d47d97 Rename bridge detection/creation functions 2017-04-24 16:42:05 +00:00
Bryan Boreham 44beed4027 Refactor decision logic for initial bridge type 2017-04-24 16:26:16 +00:00
Bryan Boreham 9fd1a43769 Put back some weave bridge options
ability to set MTU was lost in an earlier change
2017-04-24 14:55:53 +00:00
Bryan Boreham 1c6abbbe41 Merge pull request #2909 from weaveworks/remove-deprecated-dns-cmds
Remove deprecation warnings for `launch-dns` and `stop-dns` commands
2017-04-24 11:34:23 +01:00
Marc CARRE c4a715747a Remove deprecation warnings for DNS commands removed 2 years ago. 2017-04-24 11:01:43 +01:00
Bryan Boreham 3bdea732fc Remove documentation of separate args to plugin
since it has been merged into the `weaver` process
2017-04-24 10:00:32 +00:00
Marc Carré bfe8e79653 Merge pull request #2905 from weaveworks/remove-docker-from-plugin
Remove some things we don't want in the v2 plugin image
2017-04-21 11:12:28 +01:00
Marc Carré 7d812e3087 Merge pull request #2901 from weaveworks/remove-deprecated-options
Remove deprecation warnings for things removed a long time ago
2017-04-21 11:12:07 +01:00
Bryan Boreham 05d9cf8235 Remove some things we don't want in the v2 plugin image 2017-04-20 16:43:42 +00:00
Bryan Boreham 108f4784a6 Add back check for datapath supported 2017-04-20 16:12:42 +00:00
Bryan Boreham a7feb41e62 Replace switch statements with Bridge polymorphism 2017-04-20 15:57:49 +00:00
Bryan Boreham fddb3ee06e Review feedback 2017-04-20 15:57:49 +00:00
Bryan Boreham c59c86c660 Only publish "latest" tag on v2 plugin if explicitly told to
For V2 plugin, "latest" means "latest stable release", to make
instructions simple for end-users.  So we don't want to overwrite
"latest" with a random build by accident.
2017-04-20 10:43:16 +00:00
Bryan Boreham 8f02c81f16 Update docs for change where proxy no longer calls attach-router 2017-04-18 10:45:05 +00:00
Bryan Boreham b3fac8ed6a Remove deprecation warnings for things removed a long time ago 2017-04-17 19:48:21 +00:00
Bryan Boreham 3574da267b Remove -enforce_docker_bridge_addr_assign_type no longer used 2017-04-17 19:41:47 +00:00
Bryan Boreham c929b2d5f9 ip netns and nsenter no longer called by weave script 2017-04-17 19:41:47 +00:00
Bryan Boreham f479e57870 Remove attach-router since it no longer does anything 2017-04-17 19:41:47 +00:00
Bryan Boreham ae625a18c8 Move awsvpc bridge expose from weave script to Go code 2017-04-17 19:41:47 +00:00
Bryan Boreham 41a261bdcd Add conversion from CIDR to IPNet 2017-04-17 19:41:47 +00:00
Bryan Boreham 4ad1c22ef6 Move initial DNS population into Go code 2017-04-17 19:41:47 +00:00
Bryan Boreham ef9f95f653 Let weaver create the bridge in weave-kube 2017-04-17 19:41:47 +00:00
Bryan Boreham 3b54372eab Let weaver create the bridge in net-plugin launch 2017-04-17 19:41:47 +00:00
Bryan Boreham f05bb6c4e0 Don't assume we always run in in host pid space
Pass the path to the proc filesystem down
2017-04-17 19:41:47 +00:00
Bryan Boreham c8e0c12d34 Move AWSVPC sysctls into Go code 2017-04-17 19:41:47 +00:00
Bryan Boreham ab380ed2c1 Set weave bridge address and mtu
including the dance with the dummy interface to get MTU set high
2017-04-17 19:41:47 +00:00
Bryan Boreham 9494f0655d More meaningful errors 2017-04-17 19:41:47 +00:00
Bryan Boreham c3a41286fd Use the bridge name passed in on the command-line more 2017-04-17 19:41:47 +00:00
Bryan Boreham 8297652204 Read our peerName from persistence file if necessary
Mount directories for machine ID files into weave container
2017-04-17 19:41:47 +00:00
Bryan Boreham a26fc67ded New way of initializing; remove --iface option 2017-04-17 19:41:47 +00:00
Bryan Boreham abadbf883a AWSVPC mode now part of BridgeConfig 2017-04-17 19:41:47 +00:00
Bryan Boreham 833eb6166f Add AWSVPC bridge type 2017-04-17 19:41:47 +00:00
Bryan Boreham e7e3608642 Move creation of bridge inside router 2017-04-17 19:41:47 +00:00
Bryan Boreham dd232775e6 Move expect-npc setup from weave script to Go code 2017-04-17 19:41:47 +00:00
Bryan Boreham a8eb7966b6 Wire up enforce_docker_bridge_addr_assign_type 2017-04-17 19:41:47 +00:00
Bryan Boreham 8051f51d46 Move bridge-creation code from weave script into Go code
via weaveutil create-bridge function
2017-04-17 19:41:47 +00:00
Bryan Boreham 6fd9f471ff Bridge setup iptables rules 2017-04-17 19:41:47 +00:00
Bryan Boreham 2d037d874c MTU selection closer to weave script
Note that if initFastdp sets the MTU for the datapath then the same
value is used for the bridge also.
2017-04-17 19:41:47 +00:00
Bryan Boreham 8e5384ee01 Create pcap veth for no-fastdp operation 2017-04-17 19:41:47 +00:00
Adam Harrison 7dd37d2a13 Add functions to create bridge 2017-04-17 19:41:47 +00:00
Adam Harrison 36521b04a2 Utility function to enforce docker bridge addr_assign_type 2017-04-17 19:41:47 +00:00
Bryan Boreham f5d0a277fb Move canonicalisation and checking of DNS entries into nameserver 2017-04-17 19:41:47 +00:00
Bryan Boreham 986a3f8079 Pass bridge name into awsvpc 2017-04-17 19:41:47 +00:00
Bryan Boreham de4ec23809 Remove unused check_docker_server_api_version()
The last code that called it was removed in 1f42a9d2f9
2017-04-17 19:29:28 +00:00
Marc Carré 1cc0794e75 Merge pull request #2897 from weaveworks/stop-old-plugin
More help for upgraders who use plugin commands
2017-04-13 17:47:22 +01:00
Marc Carré 3cca0887c7 Merge pull request #2898 from weaveworks/weaveutil-allids-without-all
Only list active containers in weaveutil/addrs.go#containerAddrs
2017-04-13 13:12:41 +01:00
Marc Carré 0e1d39120e Merge pull request #2895 from bjhaid/patch-1
Highlight the forward rules
2017-04-13 13:05:28 +01:00
Bryan Boreham a072cf2e0a Merge pull request #2894 from weaveworks/fix-typo-plugin
Fix typo: 'JSON encode payload' -> 'JSON encoded'.
2017-04-13 12:28:07 +01:00
Marc CARRE 0f0f3649a4 Fix typo: 'JSON encode payload' -> 'JSON encoded'. 2017-04-13 12:26:50 +01:00
Bryan Boreham 54c95c04af Stop trying to publish the old plugin container 2017-04-13 11:13:24 +00:00
Marc CARRE 7c5dda353d Only list active containers.
Previously was using `docker.ListContainersOptions{All: true}`, which is the equivalent of `docker ps -a`, and is not what we want here.
2017-04-13 12:12:49 +01:00
Bryan Boreham c42400de4f Remove warning about create-bridge not working with fastdp
This hasn't been true for a long time.
2017-04-13 10:15:08 +00:00
Bryan Boreham 9b5cef9167 Stop and reset old weaveplugin container
in case user has upgraded from <v2.0 and left it running
2017-04-13 09:14:04 +00:00
Bryan Boreham 6081c400fb Print special 'removed' message on launch-plugin and stop-plugin 2017-04-13 09:13:50 +00:00
Bryan Boreham cb339523de Remove mentions of deleted commands 2017-04-13 09:03:26 +00:00
Àbéjídé Àyodélé 538902b207 Highlight the forward rules 2017-04-12 10:37:25 -05:00
Marc Carré 8961041469 Merge pull request #2727 from weaveworks/issues/2397-v2-plugin
Create a V2 Docker plugin
2017-04-12 14:27:34 +01:00
Martynas Pumputis cfe26ae346 Add an ugly way to match whether network is ours to plugin
Docker Plugin V2 does not expose a plugin name to the plugin, so we
check for "net-plugin" within driver name of a network to detect
whether network is ours.
2017-04-12 13:05:40 +00:00
Martynas Pumputis bdfa06dbe9 Use $(SUDO) for each docker cmd when building net-plugin 2017-04-12 13:05:40 +00:00
Martynas Pumputis 1a3537a8f4 Replace noDNS by dns in plugin
Just to avoid double negation.
2017-04-12 13:05:40 +00:00
Martynas Pumputis 09606db9c3 Exit when launching plugin-v2 if node is not active in Swarm
We retrieve the list of swarm masters for peer discovery when launching
plugin-v2, thus the node should belong to any Swarm when enabling the
plugin.
2017-04-12 13:05:40 +00:00
Martynas Pumputis 4a708c2a82 Rename prog/plugin-v2 to prog/net-plugin
Consensus was to call the plugin-v2 as weaveworks/net-plugin.
2017-04-12 13:05:40 +00:00
Martynas Pumputis 735a7f9154 Use correct path to netns of container in plugin-v2
Used when configuring ARP settings of a container upon ContainerStarted
event.
2017-04-12 13:05:40 +00:00
Martynas Pumputis 7478e78ab7 Add NSPathByPidWithRoot
The function is used in a case when /proc is bind mounted to
other than /proc dir.
2017-04-12 13:05:40 +00:00
Martynas Pumputis 01bfa602ad Pass noDNS and isPluginV2 flags to plugin
- "noDNS" controls whether upon ContainerStarted event a container
  should be registered within the Weave DNS.
- "isPluginV2" will be used to determine a path to host's /proc.
2017-04-12 13:05:40 +00:00
Martynas Pumputis 332762201a Reuse docker client instance in plugin
Instead of creating a new one, reuse one created in weaver.

The change removes the pinning of client API versions (1.21 in our
case).
2017-04-12 13:05:40 +00:00
Martynas Pumputis 568290afb7 Do not start local scope plugin (mesh) in plugin-v2
Currently, plugin-v2 works only in "swarm" scope, as it depends
on swarm for peer discovery.
2017-04-12 13:05:40 +00:00
Martynas Pumputis 3c11c8aa38 Add comment about failures to is-docker-plugin-enabled cmd 2017-04-12 13:05:40 +00:00
Martynas Pumputis 2ba360f33a Better plugin detection functions in weave script
Renamed to "is_plugin_v1_enabled" and "is_plugin_v2_enabled".
Improve weave status and weave launch* err message when plugin-v2 is running

```
$ weave launch
Docker plugin "weaveworks/net-plugin" is running; Aborting.
$ weave status
   <..>
   Service: plugin (v2)
DriverName: weaveworks/net-plugin
```
2017-04-12 13:05:40 +00:00
Martynas Pumputis 7fc56e54b3 Add plugin_publish target to Makefile
"docker plugin" does not support tagging plugin images, therefore
we need to build plugin images two times - one for :latest and
for :$(WEAVE_VERSION).

Pushing of :latest happens only if $UPDATE_LATEST is not false.
2017-04-12 13:05:40 +00:00
Martynas Pumputis 16062ea62d Rename weaveworks/pluginv2 to weaveworks/net-plugin 2017-04-12 13:05:40 +00:00
Martynas Pumputis e852ae99ca Report correct plugin driver name in "weave status" 2017-04-12 13:05:40 +00:00
Martynas Pumputis 0ff37d3492 Do "docker plugin inspect" inside weaveutil
We cannot do it from weaveexec, because the latter is distributed
with an old version of Docker client which does not support
Plugins API.
2017-04-12 13:05:40 +00:00
Martynas Pumputis b3866ebd94 Update vendor/github.com/docker/docker to v1.13.1 2017-04-12 13:05:40 +00:00
Marc CARRE 3031372442 weave --local launch* with V2 plugin on exits with error.
For example:
```
$ docker ps
CONTAINER ID  IMAGE  COMMAND  CREATED  STATUS  PORTS  NAMES
$ docker plugin ls
ID            NAME                        DESCRIPTION                  ENABLED
e80beb4367a6  weaveworks/pluginv2:latest  Weave Net plugin for Docker  true
$ weave --local launch
weaveworks/pluginv2 is already running.
$ weave --local launch-proxy
weaveworks/pluginv2 is already running.
$ weave --local launch-router
weaveworks/pluginv2 is already running.
$ weave --local launch-plugin
```
2017-04-12 13:05:40 +00:00
Martynas Pumputis d3d2de5f1f Make NetworkAllocate to return original options
NetworkAllocate is called on Swarm master node which creates a network.
The return option map is used to describe the network, and is passed
to CreateNetwork  which is called on all nodes when a service is
created.

Returning nil instead the actual options made Docker to omit
the "works.weave.multicast" flag, thus no multicast could be used
in Swarm.
2017-04-12 13:05:40 +00:00
Martynas Pumputis d7306c66f7 Get rid of deprecated --no-multicast-route 2017-04-12 13:05:40 +00:00
Martynas Pumputis 1f42a9d2f9 Merge plugin into weaver
This simplifies the following:

- plugin-v2 does not need to start "plugin" as a separate process, thus
  Docker is able to properly restart plugin-v2 in a case of any child
  process failing.
- No need for weaveplugin container.

plugin is enabled by default when running "weave launch". when starting
only the router, you should pass "--plugin" parameter to enable it.

The env var WEAVE_NO_PLUGIN is no more.
2017-04-12 13:05:40 +00:00
Marc CARRE 8c917eeb17 weave --local status now reports plugin.
Prints the following when running:
```
        Service: plugin
     DriverName: weave
```
See also:
- https://weaveworks.slack.com/archives/net/p1488563299009870
- https://weaveworks.slack.com/archives/net/p1488539841009756
2017-04-12 13:05:39 +00:00
Marc CARRE a81a873703 Upgrade docker-py to 1.9.0-rc2 to fix test #602.
Since 1.12.0, `docker inspect -f "{{ .NetworkSettings.Networks.<network>.Aliases }}"` also returns the container's short ID.
See also: https://github.com/docker/docker/blob/master/CHANGELOG.md
> 1.12.0 (2016-07-28)
> Networking
> Add container's short-id as default network alias #21901

Upgrading `docker/docker-py` to 1.9.0-rc2 effectively relaxes test assertions for:

- `tests/integration/network_test.py#test_connect_with_aliases`
- `tests/integration/network_test.py#test_create_with_aliases`

which do something equivalent to:

```
$ docker network create net1
$ docker run --name c1 -d busybox top
$ docker network connect --alias foo --alias bar net1 c1
$ docker inspect -f "{{ .NetworkSettings.Networks.net1.Aliases }}" c1
[foo bar e52bf50e5ee7]
```

allowing us to be consistent with the above change.

In 1.8.1, the below fails as the container's short ID would be present:

```
        self.assertEqual(
            container_data['NetworkSettings']['Networks'][net_name]['Aliases'],
            ['foo', 'bar'])
```

In 1.9.0-rc2, the below passes as the container's short ID is ignored:

```
        aliases = (
            container_data['NetworkSettings']['Networks'][net_name]['Aliases']
        )
        assert 'foo' in aliases
        assert 'bar' in aliases
```
2017-04-12 13:05:39 +00:00
Martynas Pumputis da04d97fb5 Add smoke test for plugin-v2 2017-04-12 13:05:39 +00:00
Martynas Pumputis 4f42029228 Enable WEAVE_{MTU,PASSWORD} env vars, persistence and ARP settings in plugin-v2
The vars can be customized before enabling the plugin with e.g.:

    docker plugin set $PLUGIN_NAME set WEAVE_MTU=8160

The ARP settings apply to "weave" bridge. In order to manipulate them,
we bind mount the host's /proc to /host/proc.
(The mount type of /proc changed to bind, Otherwise (when type =
"proc"), the kernel does not propagate pids of host processes as the
plugin runs in a separate PID ns.)

Persistence relies on weave.db which is stored under
/var/lib/weave/weave.db on the host.

NOTE: we do not persist peer list for plugin-v2, as it gets
restored from existing alive master nodes during the peer discovery.
2017-04-12 13:05:39 +00:00
Martynas Pumputis 4916badcc4 Move prog/v2-plugin to prog/plugin-v2 2017-04-12 13:05:39 +00:00
Martynas Pumputis 82b56848a9 Add peer discovery for Docker Swarm
The peer discovery relies on "GET /info" API call which returns
list of master nodes. The peer list is passed to weaver when
launching it.

If node is a master, then we pass "--ipalloc-alloc
consensus=$(MASTER_NODES_COUNT)" to weaver. Otherwise, we pass
"--ipalloc-alloc observer".
2017-04-12 13:05:39 +00:00
Martynas Pumputis 889dc856af Update fsouza/go-dockerclient
The updated dep requires adding the following new deps:

- vendor/github.com/fsouza/go-dockerclient
- vendor/golang.org/x/net
2017-04-12 13:05:39 +00:00
Martynas Pumputis 2ba8764615 Do not run "docker kill" inside smoke tests, because Docker 1.13.1
Otherwise test suites hang if run with Docker 1.13.1.

See: https://github.com/docker/docker/issues/31447
2017-04-12 13:05:39 +00:00
Martynas Pumputis eb5435d275 Bump Docker CI version to 1.13.1 2017-04-12 13:05:39 +00:00
Marc CARRE b048b6deb0 Bind-mount /proc in V2 plugin container.
This allows to pass ARP settings from the host, e.g.:
```
$ sudo docker-runc exec 512af90f342f16dddebc7b7245985d5eb67557e76798b4033eed2ff7adaa4eb5 cat /proc/sys/net/ipv4/neigh/weave/ucast_solicit
3
$ cat /proc/sys/net/ipv4/neigh/weave/ucast_solicit
3
$ cat /proc/sys/net/ipv4/neigh/weave/ucast_solicit
1
$ sudo docker-runc exec 512af90f342f16dddebc7b7245985d5eb67557e76798b4033eed2ff7adaa4eb5 cat /proc/sys/net/ipv4/neigh/weave/ucast_solicit
1
```
2017-04-12 13:05:39 +00:00
Bryan Boreham 0c23e47124 Allow docker API location to be specified or blanked 2017-04-12 13:05:39 +00:00
Bryan Boreham 0af2111535 Mention swarm mode in docs 2017-04-12 13:05:39 +00:00
Bryan Boreham 5bbd886e6f Build a 'v2' Docker plugin
Redirect output to specific log files, because there doesn't seem to
be a 'docker logs' for plugins
2017-04-12 13:05:39 +00:00
Marc CARRE b753bcd982 Merge remote-tracking branch 'origin/ipam-ops-reentrant' 2017-04-12 13:19:52 +01:00
Marc Carré d6a5eaec3f Merge pull request #2885 from weaveworks/issues/2353-remove-weave-run
Remove 'weave run', 'start' and 'restart'
2017-04-12 12:40:29 +01:00
Bryan Boreham 771f57029e Document flags to 'weave attach' 2017-04-12 12:15:42 +01:00
Bryan Boreham c223ff1c7d Support --without-dns in 'weave attach' 2017-04-12 12:15:42 +01:00
Bryan Boreham 481214776b Update docs for removal of 'weave run' 2017-04-12 12:15:42 +01:00
Bryan Boreham 98e6571059 Remove 'weave run', 'start' and 'restart'
Replace with informative message.
Also fix up tests which were calling these commands.
2017-04-12 12:15:37 +01:00
Marc Carré 19a31a5b82 Merge pull request #2814 from weaveworks/weaveutil-allids
Fetch list of container IDs inside weaveutil
2017-04-12 11:35:37 +01:00
Bryan Boreham 090878c157 Implement GetCapabilities on IPAM interface to eliminate warning message 2017-04-12 10:19:06 +00:00
Martynas Pumputis 53cc270f47 Make compatible with Docker Swarmkit
Implement (empty) endpoints for new NetworkAllocate and NetworkFree calls
Also update libnetwork and docker dependencies
2017-04-12 10:19:06 +00:00
Martynas Pumputis ceb0186f46 Better error reporing for weaveutil
If a weaveutil subcmd is not found, report the fact to stderr.
2017-04-12 09:48:03 +00:00
Bryan Boreham 46762a40b0 Use 'allids' feature to populate DNS names 2017-04-12 09:36:21 +00:00
Bryan Boreham c291324d14 Refactor: don't have three global variables called COMMAND 2017-04-12 09:36:21 +00:00
Bryan Boreham b307b9872a Fetch list of container IDs inside weaveutil, for 'weave ps' 2017-04-12 09:36:21 +00:00
Bryan Boreham 5e290aa11f Don't halt kubernetes test script if 'weave expose' fails
it's better to carry on so k8s gets cleaned down
2017-04-11 16:31:52 +00:00
Bryan Boreham 5f6c5f6692 Ensure boltDB pathname is constructed uniformly
Keep the concatenation of the prefix and filename inside the boltdb
package, so we can't get it wrong outside.
2017-04-11 15:45:04 +00:00
Marc Carré bc47866880 Merge pull request #2827 from weaveworks/issues/2799-peer-disco
Peer Discovery via cloud service
2017-04-11 14:59:28 +01:00
Bryan Boreham e6a692424b Add screen grab for Weave Cloud token 2017-04-11 12:22:59 +00:00
Bryan Boreham f293063538 Fix print of error 2017-04-10 16:44:10 +00:00
Bryan Boreham 6321512ddb Use peer count sent back by service 2017-04-10 16:42:47 +00:00
Bryan Boreham 0ca125ff2c Extract 'HasMode' as method on ipamConfig 2017-04-10 16:42:28 +00:00
Bryan Boreham 57efe0145b Remove TODO comment - if it's a transient error then enough restarts will get past it 2017-04-10 15:53:23 +00:00
Bryan Boreham bd53462ab2 Rename 'weavenet' to 'net' in URLs, for simplicity 2017-04-10 15:45:49 +00:00
Bryan Boreham c44d98b798 Add basic docs for peer discovery 2017-04-10 14:36:26 +00:00
Bryan Boreham c8adcb2e79 Wire peer discovery delete into reset and rmpeer 2017-04-10 14:09:06 +00:00
Bryan Boreham 768f89c3de Move peer http handlers from ipam to weaver 2017-04-10 14:09:06 +00:00
Bryan Boreham e2d644b86b Peer Discovery via a web service 2017-04-10 14:09:06 +00:00
Bryan Boreham 09977a2e04 Updated weaveworks/common, plus dependencies
Needed for peer discovery client calls
2017-04-10 14:01:59 +00:00
Bryan Boreham 63a0b964ab Merge branch '1.9' 2017-04-10 12:45:03 +00:00
Marc Carré 1b7c386351 Merge pull request #2889 from weaveworks/consistent-spacing-in-markdown-headings
Consisten spacing in Markdown headings
2017-04-10 13:35:37 +01:00
Ilya Dmitrichenko 293f1990bc Consisten spacing in Markdown headings
Jekyll doesn't tolerate this, and it's generally cosidered a cleaner
style, we've had a bit of mixed style and this makes it consistent.
2017-04-10 12:19:29 +01:00
Bryan Boreham 0bb62ae75a Merge branch '1.9' 2017-04-10 10:47:42 +00:00
Marc Carré 77b193791a Merge pull request #2853 from weaveworks/kube-smoketest-1.6
Update smoke tests for kubernetes 1.6
2017-04-10 11:21:23 +01:00
Bryan Boreham 74a7bef472 Use 'kubeadm reset' instead of replicating it 2017-04-10 09:02:45 +00:00
Bryan Boreham fc78bf4d11 Update test script to work with kubeadm 1.6 2017-04-10 09:02:45 +00:00
Bryan Boreham 84cdf54079 Build VMs with Kubernetes 1.6.1 and CNI 0.5.1 2017-04-10 09:02:45 +00:00
Marc CARRE fa08bb9df6 Merge remote-tracking branch 'origin/1.9' 2017-04-07 15:11:38 +01:00
Marc CARRE 3e030f7971 Merge branch '1.9' 2017-04-06 14:50:21 +01:00
Bryan Boreham d0e0df9bd4 Merge pull request #1350 from weaveworks/ipam-json
Add GET /ip handler to return all IPAM mappings.
2017-04-06 10:09:01 +01:00
Bryan Boreham f5bdf916f5 Merge branch '1.9' 2017-04-05 16:31:47 +00:00
Martynas Pumputis ea36d232ac Merge branch '1.9' 2017-04-04 15:46:09 +01:00
Bryan Boreham 916ff7aa39 Merge branch '1.9' 2017-03-31 17:53:04 +00:00
Martynas Pumputis e74783b987 Revert disabling of 840 smoke test 2017-03-30 17:40:25 +01:00
Martynas Pumputis 0b4c19a369 Add 840_weave_kube_3_disabled.sh to .lintignore 2017-03-30 16:07:36 +01:00
Martynas Pumputis def9d8d004 Disable temporarily 840 smoke test to publish docs
840 is broken because of kubeadm failing with 1.6 k8s.
2017-03-30 15:36:38 +01:00
Martynas Pumputis 2301e8dbf7 Merge remote-tracking branch 'origin/1.9' 2017-03-29 10:33:07 +01:00
Bryan Boreham ac430e4c42 Merge branch '1.9' 2017-03-21 15:53:29 +00:00
Bryan Boreham c6457981ab Merge branch '1.9' 2017-03-21 14:14:01 +00:00
Bryan Boreham 8862d4f76e Merge pull request #2860 from mgalgs/patch-2
README: Drop Slack Status badge
2017-03-21 09:58:45 +00:00
Ilya Dmitrichenko d313ec935c Merge pull request #2859 from mgalgs/patch-1
README: Fix formatting of "Further Information" header
2017-03-21 08:55:13 +00:00
Mitchel Humpherys 40e759733d README: Drop Slack Status badge
The Slack Status badge doesn't work, at least for
non-signed-in users.  This gives a bad impression
as to the quality of the project.
2017-03-20 17:37:44 -07:00
Mitchel Humpherys dee57aca37 README: Fix formatting of "Further Information" header 2017-03-20 17:35:32 -07:00
Bryan Boreham 7ac2301247 Merge branch '1.9' 2017-03-20 12:13:35 +00:00
Bryan Boreham 1d55ee19e4 Merge branch '1.9' 2017-03-17 11:46:32 +00:00
Bryan Boreham 9810a84475 Merge branch '1.9' 2017-03-16 19:43:50 +00:00
Martynas Pumputis b128562b41 Merge pull request #2838 from weaveworks/tweak-privileged
Remove some unnecessary --privileged flags
2017-03-15 10:30:35 +00:00
Bryan Boreham 8f44dc0986 Remove hard-coded number of hosts 2017-03-14 18:10:24 +00:00
Bryan Boreham ca523fa335 Don't need --privileged when writing /etc/hosts 2017-03-10 11:55:22 +00:00
Bryan Boreham 5860332e49 Don't repeat '--privileged --net=host' docker options 2017-03-10 11:55:22 +00:00
Tom Wilkie c06d4d1b00 Add GET /ip handler to return all IPAM mappings. 2017-03-10 11:39:47 +00:00
Bryan Boreham bec2470ddf Merge branch '1.9' 2017-03-09 16:02:07 +00:00
Bryan Boreham 9516b1a91b Merge pull request #2833 from weaveworks/you-say-tomato
Change what we print in place of the password
2017-03-09 10:45:06 +00:00
Bryan Boreham 8468183738 'redacted' is a better word than 'elided' 2017-03-09 10:44:48 +00:00
Bryan Boreham 39563fc142 Merge pull request #2829 from dlmiddlecote/issues/2815-check-live-containers
Only check running containers for existing addresses
2017-03-09 09:53:03 +00:00
Daniel Middlecote 104d2240ec Move container lists to scope they are used in 2017-03-08 21:43:21 +00:00
Marc CARRE 9bec84da5b Merge branch '1.9' 2017-03-07 16:40:46 +00:00
Marc Carré e3a37c8d71 Document required GitHub OAuth scope. 2017-03-07 13:47:11 +00:00
Daniel Middlecote fd28740108 Only check running containers for existing addresses 2017-03-06 22:10:45 +00:00
Bryan Boreham fa74d1b9bb Merge two ADD commands to remove a layer 2017-03-06 11:29:09 +00:00
Bryan Boreham 11d120bb5b Debug log any error returned by exec-ing weave 2017-03-06 11:29:09 +00:00
Bryan Boreham e2c96cfa85 Remove/move down WORKDIR lines in Dockerfiles
They seem to stop Docker using its build cache.
Removing the line entirely stops weaveproxy from working, as it
assumes it can exec `./weave` from the current directory.
2017-03-06 11:29:09 +00:00
Bryan Boreham eee3e8d331 touch exes after running build command
The executables have dependencies that are not apparent to `go build`;
notably the build container. If Go doesn't see anything is out of date
then it will do nothing, hence touch the file so next time we run
`make` it is up to date.
2017-03-06 11:29:09 +00:00
Bryan Boreham 0c68ad4acb Merge branch '1.9' 2017-03-06 11:26:00 +00:00
Mike Bryant 26b566b541 Use a keyserver port that's better for firewalls 2017-03-02 15:49:22 +00:00
Martynas Pumputis 16bbee2831 Merge branch '1.9' 2017-03-01 15:08:52 +00:00
Bryan Boreham 96f7c6ebab Merge branch '1.9' 2017-03-01 11:33:25 +00:00
Martynas Pumputis 5b06063442 Add fastdp-crypto benchmarking instructions 2017-03-01 09:57:00 +00:00
256 changed files with 7652 additions and 3234 deletions

No files matched your search

+65
View File
@@ -0,0 +1,65 @@
<!--
Hi, thank you for opening an issue!
Before hitting the button...
** Is this a REQUEST FOR HELP? **
If so, please have a look at:
- our FAQ: https://www.weave.works/docs/net/latest/faq/
- our troubleshooting page: https://www.weave.works/docs/net/latest/troubleshooting/
- our help page, to choose the best channel (Slack, etc.) to reach out: https://www.weave.works/help/
** Is this a FEATURE REQUEST? **
If so, please search existing feature requests, and if you find a similar one, up-vote it and/or add your comments to it instead.
If you did not find a similar one, please describe in details:
- why: your use-case, specific constraints you may have, etc.
- what: the feature/behaviour/change you would like to see in Weave Net
Do not hesitate, when appropriate, to share the exact commands or API you would like, and/or to share a diagram (e.g.: asciiflow.com): "a picture is worth a thousand words".
** Is this a BUG REPORT? **
Please fill in as much of the template below as you can.
Thank you!
-->
## What you expected to happen?
## What happened?
<!-- Error message, actual behaviour, etc. -->
## How to reproduce it?
<!-- Specific steps, as minimally and precisely as possible. -->
## Anything else we need to know?
<!-- Cloud provider? Hardware? How did you configure your cluster? Kubernetes YAML, KOPS, etc. -->
## Versions:
<!-- Please paste in the output of these commands; 'kubectl' only if using Kubernetes -->
```
$ weave version
$ docker version
$ uname -a
$ kubectl version
```
## Logs:
```
$ docker logs weave
```
or, if using Kubernetes:
```
$ kubectl logs -n kube-system <weave-net-pod> weave
```
<!-- (If output is long, please consider a Gist.) -->
<!-- Anything interesting or unusual output by the below, potentially relevant, commands?
$ journalctl -u docker.service --no-pager
$ journalctl -u kubelet --no-pager
$ kubectl get events
-->
## Network:
<!-- If your problem has anything to do with one network endpoint not being able to contact another, please run the following commands -->
```
$ ip route
$ ip -4 -o addr
$ sudo iptables-save
```
+6 -4
View File
@@ -33,11 +33,13 @@ coverage.html
# Vim backup files
*.swp
# Sed backup files
*.bak
# Project specific
prog/weaver/weaver
prog/weavedns/weavedns
prog/weavehosts/weavehosts
prog/weaveproxy/weaveproxy
prog/sigproxy/sigproxy
prog/weavewait/weavewait
prog/weavewait/weavewait_noop
@@ -53,14 +55,13 @@ testing/runner/runner
releases
.*.uptodate
weave*.tar.gz
prog/weaveexec/weave
prog/weaver/weave
prog/weaveexec/weavehosts
prog/weaveexec/weaveproxy
prog/weaveexec/weavewait
prog/weaveexec/weavewait_noop
prog/weaveexec/weavewait_nomcast
prog/weaveexec/sigproxy
prog/weaveexec/weaveutil
prog/weaver/weaveutil
prog/weaveexec/docker*
Vagrantfile.local
test/tls/tls
@@ -70,6 +71,7 @@ test/coverage.*
*qemu-*-static
terraform.tfstate
terraform.tfstate.backup
prog/net-plugin/rootfs/
# Website
site-build
+54
View File
@@ -124,3 +124,57 @@
[submodule "vendor/github.com/containernetworking/cni"]
path = vendor/github.com/containernetworking/cni
url = https://github.com/containernetworking/cni
[submodule "vendor/google.golang.org/grpc"]
path = vendor/google.golang.org/grpc
url = https://github.com/grpc/grpc-go
[submodule "vendor/github.com/docker/go-units"]
path = vendor/github.com/docker/go-units
url = https://github.com/docker/go-units
[submodule "vendor/golang.org/x/net"]
path = vendor/golang.org/x/net
url = https://github.com/golang/net
[submodule "vendor/k8s.io/api"]
path = vendor/k8s.io/api
url = https://github.com/kubernetes/api
[submodule "vendor/k8s.io/apimachinery"]
path = vendor/k8s.io/apimachinery
url = https://github.com/kubernetes/apimachinery
[submodule "vendor/github.com/PuerkitoBio/purell"]
path = vendor/github.com/PuerkitoBio/purell
url = https://github.com/PuerkitoBio/purell
[submodule "vendor/github.com/PuerkitoBio/urlesc"]
path = vendor/github.com/PuerkitoBio/urlesc
url = https://github.com/PuerkitoBio/urlesc
[submodule "vendor/github.com/emicklei/go-restful"]
path = vendor/github.com/emicklei/go-restful
url = https://github.com/emicklei/go-restful
[submodule "vendor/github.com/go-openapi/jsonpointer"]
path = vendor/github.com/go-openapi/jsonpointer
url = https://github.com/go-openapi/jsonpointer
[submodule "vendor/github.com/go-openapi/jsonreference"]
path = vendor/github.com/go-openapi/jsonreference
url = https://github.com/go-openapi/jsonreference
[submodule "vendor/github.com/go-openapi/spec"]
path = vendor/github.com/go-openapi/spec
url = https://github.com/go-openapi/spec
[submodule "vendor/github.com/go-openapi/swag"]
path = vendor/github.com/go-openapi/swag
url = https://github.com/go-openapi/swag
[submodule "vendor/github.com/golang/glog"]
path = vendor/github.com/golang/glog
url = https://github.com/golang/glog
[submodule "vendor/github.com/google/gofuzz"]
path = vendor/github.com/google/gofuzz
url = https://github.com/google/gofuzz
[submodule "vendor/github.com/mailru/easyjson"]
path = vendor/github.com/mailru/easyjson
url = https://github.com/mailru/easyjson
[submodule "vendor/k8s.io/kube-openapi"]
path = vendor/k8s.io/kube-openapi
url = https://github.com/kubernetes/kube-openapi
[submodule "vendor/golang.org/x/text"]
path = vendor/golang.org/x/text
url = https://go.googlesource.com/text
[submodule "vendor/gopkg.in/yaml.v2"]
path = vendor/gopkg.in/yaml.v2
url = https://gopkg.in/yaml.v2
+279
View File
@@ -1,3 +1,282 @@
## Release 2.1.3
This release fixes a race-condition in the IP reclaim code for weave-kube
where two nodes could end up fighting over the same space and break
connectivity #3190, #3192
## Release 2.1.2
This release fixes a couple of bugs discovered since the release of Weave Net 2.1.0
##Bug fixes
* Fix crash seen when starting 10-15 nodes simultaneously #3184,#3186
* Fix NetworkPolicy blocking traffic if updates come out of order from Kubernetes #3177,#3181
Thanks to the following contributors:
@zignig
[Full list of changes](https://github.com/weaveworks/weave/milestone/66?closed=1)
## Release 2.1.1
As 2.1.0, but fixing a couple of installation glitches. #3175,#3176
## Release 2.1.0
##New Features
Improved Kubernetes Network Policy - Weave Net now supports the
'v1' policies introduced in Kubernetes 1.7 as well as the 'beta'
policies supported previously. See [Kubernetes 1.7 changelog](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.7.md#network)
for differences. To use old policies, `--use-legacy-netpol` argument
should be passed to `weave-npc`. #3105,#3141,#3151,#3169
Weave Net now reclaims IP addresses owned by Kubernetes nodes which
have been deleted from the cluster - this avoids running out of IP
addresses when many nodes are added and deleted over a long period.
#2797,#3149,#3170,#3172
##Other improvements
* Export a Prometheus-style metric giving count of unreachable peers #3119
* Update 'gopacket' library to reduce memory use by approx 15MB #3160
* Replace bundling the 'docker' binary with our own code to avoid
security vulnerability alerts and save space #2957,#3110
##Bug fixes
* When `weave expose` is used, allow traffic into the Weave network -
up till version 1.12 Docker would do this for us, but in 1.13 they
stopped so now we do it. This change makes `weave expose` require
Weave Net to be running. #2758,#3122
* Arm64 build now works on non-kubernetes installs #2832,#3110
* TX offload was being disabled in 'awsvpc' mode, which slows down packet sending #3089
* Removed spurious 'nil' in logs from CNI DEL operation #3143
##Build and test
* Images are now also built for the ppc64le platform #3129
* Tweak build scripts to run on OSX as well as Linux #3135
##External Contributors
Thanks to the following contributors:
@caarlos0
@dtshepherd
[Full list of changes](https://github.com/weaveworks/weave/milestone/59?closed=1)
## Release 2.0.5
Bug fixes
* Fix /etc/hosts inside containers so the container's name resolves to
its Weave Net address #3136,#3138
* New weave-kube config for Kubernetes 1.7 and 1.8 which resolves an
intermittent conflict with kube-proxy that could break Weave Net
until reboot #2998,#3134
* Remove persistence file in `weave reset` when using Docker plugin V2 #3103,#3114
Build and test
* Some trivial changes to placate go-lint #3137
[Full list of changes](https://github.com/weaveworks/weave/milestone/63?closed=1).
## Release 2.0.4
Bug fixes
* weave-npc failed on Centos 7, due to older 'ipset' version in kernel #3099,#3100
[Full list of changes](https://github.com/weaveworks/weave/milestone/62?closed=1).
## Release 2.0.3
Bug fixes
* Weave-npc would crash on a policy with no 'from' part - regression introduced in 2.0.2 #3095,#3096,#3097
[Full list of changes](https://github.com/weaveworks/weave/milestone/61?closed=1).
## Release 2.0.2
Bug fixes and minor improvements
* Fix race condition in weave-npc which would intermittently block all traffic for a namespace #3057,#3059
* Ensure Fast Datapath works on machines that need to mount the kernel module dynamically #3080
* Regression: weave-npc would block everything if `kubelet --hostname-override` was used #3049,#3051
* Fix netfilter rules to block containers from accessing the Weave Net control endpoint #3093
* If DNS server is off then disable proxy DNS registration, to avoid spurious errors #3054,#3088
* Add comments to each iptables rule and ipset, to help when troubleshooting #3064
* Remove code that checked for an outdated fallback address for Kubernetes api-server #3071
* Add a label to the weavedb image so it can be filtered out by tools #3066
* Fix various build and continuous-integration failures #3061
* Print 'help' text faster in the weave script #3056
* Add an option to create continuous integration hosts in different ways #3060
* Remove remnants of the pre-2.0 proxy and plugin from build and test #3035,#3036
[Full list of changes](https://github.com/weaveworks/weave/milestone/60?closed=1).
## Release 2.0.1
Bug fixes and minor improvements
* Fall back to slower data path (`sleeve`), rather than crashing, when the machine lacks VXLAN support (required for “fast data path”, `fastdp`) #3043
* Fix bug in processing of arguments when Docker has TLS enabled, rather than crashing with invalid peers list, e.g. `lookup --tlsverify: no such host` #3039
* Add `kube-system` namespace back to `weave-kube`'s YAMLs, preventing omissions leading to errors like `error contacting APIServer: the server does not allow access to the requested resource` #3033,#3042
* Fix release script to prevent ARM64 binaries to end up in AMD64 `net-plugin`, leading to `Error response from daemon: dial unix /run/docker/plugins/<id>/weave.sock: connect: no such file or directory` when installing `net-plugin` #3045
* `weave reset` and `weave rmpeer` now only contact Weave Cloud when Weave Net is configured with a Weave Cloud token, preventing unnecessary requests and potentially confusing `401 Unauthorized` errors in Weave Net’s logs #3044
[Full list of changes](https://github.com/weaveworks/weave/milestone/58?closed=1).
## Release 2.0.0
New Features
Peer Discovery via Weave Cloud
You can now get all your Weave Net peers to find each other via the
Weave Cloud service, instead of maintaining a list of peers at
startup. #2799,#2827
See the [docs
page](https://github.com/weaveworks/weave/blob/master/site/using-weave/weave-cloud.md)
for more details
New Docker Plugin
Docker has a [new plugin
system](https://docs.docker.com/engine/extend/) which improves the
installation UX and solves some issues around startup. This means
Weave Net 2.0 can now run with Docker in "swarm mode" and supports the
`docker service` command. #2396,#2397,#2651,#2727,#2805,#2816,#2905,
#2906,#2929,#2932,#2945,#2950,#2956,#2963,#2964,#2966,#3019
The previous Docker Plugin is still available and can be installed as before.
All of Weave Net now runs in one container
Previously we had three separate containers for routing, Docker API
proxy and Docker plugin. Running everything in one simplifies start-up
and removes the need to detect various error
conditions. #1642,#2897,#2936,#2945,#2946,#2951,#2960
The individual commands ‘weave launch-router’, ‘weave launch-plugin’,
etc., have been removed. You can turn off the plugin and proxy with
new command-line options. In keeping with Semantic Versioning, we have
changed the major version number for this release.
Other new features
* Kubernetes configuration now comes from our “Launch Generator” that
allows different options to be selected via
URL. #2754,#2903,#3000,#3001
* `weave-kube` now stores data about IP allocation in `/var/lib/weave`
on the host instead of in a Kubernetes volume. This means that the
data will persist across pod deletion and re-creation, e.g. during
an upgrade of Weave Net, which makes restarts more
reliable. #2610,#2967
* `weave-kube` turned on rolling updates, so careful manual handling
of updates is no longer required. #3024
Bug fixes
* Kubernetes Network Policies which allowed a specific set of pods to
connect would block all pods on other hosts. Revert the change in
v1.9.6 which ignored pods on other hosts #3025,#3028
Features removed
* `weave run` has been removed. This was the original method provided
to start containers with Weave Net, but it always required care over
timing of start-up, and we now provide three alternative, better,
ways. You can replicate the effect by calling `docker run` then
`weave attach`. Similarly `weave start` and `weave restart` were
removed. #2353,#2885
* Everything deprecated more than one release ago has been removed, so
if you use it now you get an error rather than a warning. This
includes the ‘create-bridge’ command and older command-line
arguments, e.g. `--iprange` was replaced by `--ipalloc-range`
#2901,#2909,#2913,#2942,#2989,#2991
Functions moved from shell-script to Go code.
This enables more precise error-checking and runs a bit faster. It has
also enabled us to shrink the size of images downloaded: `weave-kube`
is 101MB compared to 163MB previously #2953,#2954,#2974
Specific items that moved from shell-script to Go:
* Setting up the `weave` bridge #1958,#2975,#2977,#2978
* Container attachment #2947
* Creation of the ’weave’ default plugin network #2920
Minor improvements
* You can now restart the Weave Net router without requiring the proxy to be enabled #2112
* Plugin (legacy version) now respects `--ipalloc-default-subnet` option #2919
* The `weave` script now detects and issues an error message if
`weave-kube` is running and you attempt to launch again from the script. #2709/#2966
* It is now possible to choose the the MAC address of the `weave`
bridge using `--name`, in case your hosts have identical unique
IDs. #2900
* Relaxed Kubernetes tolerations for Weave Net's daemonset in order to
match any node (previously, only taints directed at master). #3018
* Kubernetes' `seLinuxOptions` configuration is now empty by default,
to reduce spurious failures on hosts not using seLinux. #3001
* Improved reliability of namespace changes via `nsenter`. #2992
* `weave ps` now fetches the list container IDs internally, rather
than calling out to `docker ps` #2814,#2898
* at startup, actively remove dead containers’ Weave Net IP addresses from IPAM #3013
* at startup, only check live containers to see if they have an
existing Weave Net IP address #2815,#2829
* Weave Net CNI plugin now logs but does not raise an error if
anything goes wrong during network interface delete, to be more
compatible with Kubernetes 1.6. #2928
* Stop running a shell in “privileged” mode when it’s only writing a file #2838
* New internal REST endpoint to return all IP address mappings. #1350
* Changed the wording where we do not log the password #2833
* Fixed typo in plugin error messages #2894
Build and test
* Weave Net is now built with Go version 1.8, which has better code
generation and garbage collection #2914
* During smoke-tests, use a webserver instead of just `ping` so we get
a more realistic test that the Weave network is working #2918
* When installing dependencies for the build container, use a
keyserver port that's better for firewalls #2812
* Kubernetes test script now scales up to more hosts, and works with
Kubernetes 1.6 #2837,#2853,#2923
* Other minor build improvements and refactoring #2760,#2910
[Full list of changes](https://github.com/weaveworks/weave/milestone/49?closed=1).
## Release 1.9.8
Bug fixes and minor improvements
* Fix weave-npc blocking NodePort and any other non-local access #3011,#3014
* Fix bug where IPAM would duplicate a fixed IP address assigned via Docker plugin #3003,#3010
[Full list of changes](https://github.com/weaveworks/weave/milestone/56?closed=1).
## Release 1.9.7
This is identical to 1.9.6 with one additional bug-fix:
* weave-npc would block everything if `kubelet --hostname-override` was used #2995,#2996
## Release 1.9.6
Bug fixes and minor improvements
+3 -3
View File
@@ -1,3 +1,3 @@
DOCKER_VERSION=1.11.2
KUBERNETES_VERSION=1.5.2
KUBERNETES_CNI_VERSION=0.3.0.1
DOCKER_VERSION=17.06
KUBERNETES_VERSION=1.7.8
KUBERNETES_CNI_VERSION=0.5.1
+1 -1
View File
@@ -176,7 +176,7 @@
END OF TERMS AND CONDITIONS
Copyright 2014-2016 Weaveworks Ltd.
Copyright 2014-2017 Weaveworks Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+88 -42
View File
@@ -1,5 +1,5 @@
.DEFAULT: all
.PHONY: all exes testrunner update tests lint publish-one-arch $(PUBLISH) clean clean-bin prerequisites build run-smoketests
.PHONY: all exes testrunner update tests lint publish-one-arch $(PUBLISH) clean clean-bin clean-work-dir prerequisites build run-smoketests
# If you can use docker without being root, you can do "make SUDO="
SUDO=$(shell docker info >/dev/null 2>&1 || echo "sudo -E")
@@ -17,15 +17,15 @@ QEMU_VERSION=v2.7.0
# A list of all supported architectures here. Should be named as Go is naming platforms
# All supported architectures must have an "ifeq" block below that customizes the parameters
ALL_ARCHITECTURES=amd64 arm arm64
ML_PLATFORMS=linux/amd64,linux/arm,linux/arm64
ALL_ARCHITECTURES=amd64 arm arm64 ppc64le
ML_PLATFORMS=linux/amd64,linux/arm,linux/arm64,linux/ppc64le
ifeq ($(ARCH),amd64)
# The architecture to use when downloading the docker binary
WEAVEEXEC_DOCKER_ARCH?=x86_64
# The name of the alpine baseimage to use as the base for weave images
ALPINE_BASEIMAGE?=alpine:3.4
ALPINE_BASEIMAGE?=alpine:3.6
# The extension for the made images
# Specifying none means for example weaveworks/weave:latest
@@ -42,7 +42,7 @@ ifeq ($(ARCH),arm)
WEAVEEXEC_DOCKER_ARCH?=armel
# Using the (semi-)official alpine image
ALPINE_BASEIMAGE?=armhf/alpine:3.4
ALPINE_BASEIMAGE?=arm32v6/alpine:3.6
# arm images have the -arm suffix, for instance weaveworks/weave-arm:latest
ARCH_EXT?=-arm
@@ -62,7 +62,7 @@ ifeq ($(ARCH),arm64)
WEAVEEXEC_DOCKER_ARCH?=armel
# Using the (semi-)official alpine image
ALPINE_BASEIMAGE?=aarch64/alpine:3.5
ALPINE_BASEIMAGE?=arm64v8/alpine:3.6
# arm64 images have the -arm64 suffix, for instance weaveworks/weave-arm64:latest
ARCH_EXT?=-arm64
@@ -77,15 +77,36 @@ ifeq ($(ARCH),arm64)
# Tell the gcc linker to search for libpcap here
CGO_LDFLAGS="-L/usr/local/lib/$(CC)"
endif
ifeq ($(ARCH),ppc64le)
# The architecture to use when downloading the docker binary
WEAVEEXEC_DOCKER_ARCH?=ppc64le
# Using the (semi-)official alpine image
ALPINE_BASEIMAGE?=ppc64le/alpine:3.6
# ppc64le images have the -ppc64le suffix, for instance weaveworks/weave-ppc64le:latest
ARCH_EXT?=-ppc64le
# The name of the gcc binary
CC=powerpc64le-linux-gnu-gcc
# The architecture name to use when downloading a prebuilt QEMU binary
QEMUARCH=ppc64le
# In the weaveworks/build image; libpcap libraries for ppc64le are placed here
# Tell the gcc linker to search for libpcap here
CGO_LDFLAGS="-L/usr/local/lib/$(CC)"
endif
# The name of the user that this Makefile should produce image artifacts for. Can/should be overridden
DOCKERHUB_USER?=weaveworks
# The default version that's chosen when pushing the images. Can/should be overridden
WEAVE_VERSION?=git-$(shell git rev-parse --short=12 HEAD)
# Docker Store does not allow the "latest" tag.
NET_PLUGIN_LATEST=latest_release
# Paths to all relevant binaries that should be compiled
WEAVER_EXE=prog/weaver/weaver
WEAVEPROXY_EXE=prog/weaveproxy/weaveproxy
SIGPROXY_EXE=prog/sigproxy/sigproxy
KUBEPEERS_EXE=prog/kube-peers/kube-peers
WEAVENPC_EXE=prog/weave-npc/weave-npc
@@ -93,45 +114,47 @@ WEAVEWAIT_EXE=prog/weavewait/weavewait
WEAVEWAIT_NOOP_EXE=prog/weavewait/weavewait_noop
WEAVEWAIT_NOMCAST_EXE=prog/weavewait/weavewait_nomcast
WEAVEUTIL_EXE=prog/weaveutil/weaveutil
PLUGIN_EXE=prog/plugin/plugin
RUNNER_EXE=tools/runner/runner
MANIFEST_TOOL_DIR=vendor/github.com/estesp/manifest-tool
MANIFEST_TOOL_EXE=$(MANIFEST_TOOL_DIR)/manifest-tool
TEST_TLS_EXE=test/tls/tls
NETWORKTESTER_EXE=test/images/network-tester/webserver
# All binaries together in a list
EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVEUTIL_EXE) $(PLUGIN_EXE) $(RUNNER_EXE) $(TEST_TLS_EXE) $(MANIFEST_TOOL_EXE)
EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVEUTIL_EXE) $(RUNNER_EXE) $(TEST_TLS_EXE) $(MANIFEST_TOOL_EXE) $(NETWORKTESTER_EXE)
# These stamp files are used to mark the current state of the build; whether an image has been built or not
BUILD_UPTODATE=.build.uptodate
WEAVER_UPTODATE=.weaver$(ARCH_EXT).uptodate
WEAVEEXEC_UPTODATE=.weaveexec$(ARCH_EXT).uptodate
PLUGIN_UPTODATE=.plugin$(ARCH_EXT).uptodate
PLUGIN_UPTODATE=.net-plugin$(ARCH_EXT).uptodate
WEAVEKUBE_UPTODATE=.weavekube$(ARCH_EXT).uptodate
WEAVENPC_UPTODATE=.weavenpc$(ARCH_EXT).uptodate
WEAVEDB_UPTODATE=.weavedb.uptodate
NETWORKTESTER_UPTODATE=.networktester$(ARCH_EXT).uptodate
IMAGES_UPTODATE=$(WEAVER_UPTODATE) $(WEAVEEXEC_UPTODATE) $(PLUGIN_UPTODATE) $(WEAVEKUBE_UPTODATE) $(WEAVENPC_UPTODATE)
IMAGES_UPTODATE=$(WEAVER_UPTODATE) $(WEAVEEXEC_UPTODATE) $(WEAVEKUBE_UPTODATE) $(WEAVENPC_UPTODATE) $(NETWORKTESTER_UPTODATE)
# The names of the images. Note that the images for other architectures than amd64 have a suffix in the image name.
WEAVER_IMAGE=$(DOCKERHUB_USER)/weave$(ARCH_EXT)
WEAVEEXEC_IMAGE=$(DOCKERHUB_USER)/weaveexec$(ARCH_EXT)
PLUGIN_IMAGE=$(DOCKERHUB_USER)/plugin$(ARCH_EXT)
WEAVEKUBE_IMAGE=$(DOCKERHUB_USER)/weave-kube$(ARCH_EXT)
WEAVENPC_IMAGE=$(DOCKERHUB_USER)/weave-npc$(ARCH_EXT)
BUILD_IMAGE=weaveworks/weavebuild
WEAVEDB_IMAGE=$(DOCKERHUB_USER)/weavedb
PLUGIN_IMAGE=$(DOCKERHUB_USER)/net-plugin
NETWORKTESTER_IMAGE=$(DOCKERHUB_USER)/network-tester
IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(PLUGIN_IMAGE) $(WEAVEKUBE_IMAGE) $(WEAVENPC_IMAGE) $(WEAVEDB_IMAGE)
IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(WEAVEKUBE_IMAGE) $(WEAVENPC_IMAGE) $(WEAVEDB_IMAGE) $(NETWORKTESTER_IMAGE)
PUBLISH=publish_weave publish_weaveexec publish_plugin publish_weave-kube publish_weave-npc
PUSH_ML=push_ml_weave push_ml_weaveexec push_ml_plugin push_ml_weave-kube push_ml_weave-npc
PLUGIN_WORK_DIR="prog/net-plugin/rootfs"
PLUGIN_BUILD_IMG="plugin-builder"
PUBLISH=publish_weave publish_weaveexec publish_weave-kube publish_weave-npc
PUSH_ML=push_ml_weave push_ml_weaveexec push_ml_weave-kube push_ml_weave-npc
WEAVE_EXPORT=weave$(ARCH_EXT).tar.gz
DOCKER_VERSION=1.10.3
DOCKER_DISTRIB=prog/weaveexec/docker-$(DOCKER_VERSION).tgz
DOCKER_DISTRIB_URL=https://get.docker.com/builds/Linux/$(WEAVEEXEC_DOCKER_ARCH)/docker-$(DOCKER_VERSION).tgz
NETGO_CHECK=@strings $@ | grep cgo_stub\\\.go >/dev/null || { \
rm $@; \
echo "\nYour go standard library was built without the 'netgo' build tag."; \
@@ -150,20 +173,21 @@ PACKAGE_BASE=$(shell go list -e ./)
all: $(WEAVE_EXPORT)
testrunner: $(RUNNER_EXE) $(TEST_TLS_EXE)
$(WEAVER_EXE) $(WEAVEPROXY_EXE) $(WEAVEUTIL_EXE): common/*.go common/*/*.go net/*.go net/*/*.go
$(WEAVER_EXE) $(WEAVEUTIL_EXE): common/*.go common/*/*.go net/*.go net/*/*.go
$(WEAVER_EXE): router/*.go ipam/*.go ipam/*/*.go db/*.go nameserver/*.go prog/weaver/*.go
$(WEAVEPROXY_EXE): proxy/*.go prog/weaveproxy/*.go
$(WEAVER_EXE): api/*.go plugin/*.go plugin/*/*
$(WEAVER_EXE): proxy/*.go
$(WEAVEUTIL_EXE): prog/weaveutil/*.go net/*.go plugin/net/*.go plugin/ipam/*.go db/*.go
$(SIGPROXY_EXE): prog/sigproxy/*.go
$(KUBEPEERS_EXE): prog/kube-peers/*.go
$(WEAVENPC_EXE): prog/weave-npc/*.go npc/*.go npc/*/*.go
$(PLUGIN_EXE): prog/plugin/*.go plugin/*/*.go api/*.go common/*.go common/docker/*.go net/*.go
$(TEST_TLS_EXE): test/tls/*.go
$(RUNNER_EXE): tools/runner/*.go
$(MANIFEST_TOOL_EXE): $(MANIFEST_TOOL_DIR)/*.go
$(WEAVEWAIT_NOOP_EXE): prog/weavewait/*.go
$(WEAVEWAIT_EXE): prog/weavewait/*.go net/*.go
$(WEAVEWAIT_NOMCAST_EXE): prog/weavewait/*.go net/*.go
$(NETWORKTESTER_EXE): test/images/network-tester/*.go
tests: tools/.git
lint: tools/.git
@@ -181,12 +205,13 @@ exes $(EXES) tests lint: $(BUILD_UPTODATE)
-v $(shell pwd)/.pkg:/go/pkg \
-e GOARCH=$(ARCH) -e CGO_ENABLED=1 -e GOOS=linux -e CIRCLECI -e CIRCLE_BUILD_NUM -e CIRCLE_NODE_TOTAL -e CIRCLE_NODE_INDEX -e COVERDIR -e SLOW -e DEBUG \
$(BUILD_IMAGE) COVERAGE=$(COVERAGE) WEAVE_VERSION=$(WEAVE_VERSION) CC=$(CC) QEMUARCH=$(QEMUARCH) CGO_LDFLAGS=$(CGO_LDFLAGS) $@
touch $@
else
exes: $(EXES)
$(WEAVER_EXE) $(WEAVEPROXY_EXE) $(PLUGIN_EXE):
$(WEAVER_EXE):
ifeq ($(COVERAGE),true)
$(eval COVERAGE_MODULES := $(shell (go list ./$(@D); go list -f '{{join .Deps "\n"}}' ./$(@D) | grep "^$(PACKAGE_BASE)/") | grep -v "^$(PACKAGE_BASE)/vendor/" | paste -s -d,))
go test -c -o ./$@ $(BUILD_FLAGS) -v -covermode=atomic -coverpkg $(COVERAGE_MODULES) ./$(@D)/
@@ -195,7 +220,7 @@ else
endif
$(NETGO_CHECK)
$(WEAVEUTIL_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE):
$(WEAVEUTIL_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE) $(NETWORKTESTER_EXE):
go build $(BUILD_FLAGS) -o $@ ./$(@D)
$(NETGO_CHECK)
@@ -236,35 +261,45 @@ $(BUILD_UPTODATE): build/*
sed -e "s|DOCKERHUB_USER|$(DOCKERHUB_USER)|g;s|ARCH_EXT|$(ARCH_EXT)|g;s|ALPINE_BASEIMAGE|$(ALPINE_BASEIMAGE)|g;s|QEMUARCH|$(QEMUARCH)|g" $^ > $@
ifeq ($(ARCH),amd64)
# When building "normally" for amd64, remove the whole line, it has no part in the amd64 image
sed -i "/CROSS_BUILD_/d" $@
sed -i.bak "/CROSS_BUILD_/d" $@
else
# When cross-building, only the placeholder "CROSS_BUILD_" should be removed
# Register /usr/bin/qemu-ARCH-static as the handler for ARM binaries in the kernel
# Register /usr/bin/qemu-ARCH-static as the handler for ARM and ppc64le binaries in the kernel
curl -sSL https://github.com/multiarch/qemu-user-static/releases/download/$(QEMU_VERSION)/x86_64_qemu-$(QEMUARCH)-static.tar.gz | tar -xz -C $(shell dirname $@)
cd $(shell dirname $@) && sha256sum -c $(shell pwd)/build/shasums/qemu-$(QEMUARCH)-static.sha256sum
sed -i "s/CROSS_BUILD_//g" $@
sed -i.bak "s/CROSS_BUILD_//g" $@
endif
# The targets below builds the weave images
$(WEAVER_UPTODATE): prog/weaver/Dockerfile.$(DOCKERHUB_USER) $(WEAVER_EXE) $(WEAVEEXEC_UPTODATE)
$(WEAVER_UPTODATE): prog/weaver/Dockerfile.$(DOCKERHUB_USER) $(WEAVER_EXE) weave $(WEAVEUTIL_EXE)
cp $(WEAVEUTIL_EXE) prog/weaver/weaveutil
cp weave prog/weaver/weave
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -f prog/weaver/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVER_IMAGE) prog/weaver
touch $@
$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) prog/weaveexec/symlink $(DOCKER_DISTRIB) weave $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVEUTIL_EXE)
cp weave prog/weaveexec/weave
$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) prog/weaveexec/symlink $(SIGPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVER_UPTODATE)
cp $(SIGPROXY_EXE) prog/weaveexec/sigproxy
cp $(WEAVEPROXY_EXE) prog/weaveexec/weaveproxy
cp $(WEAVEWAIT_EXE) prog/weaveexec/weavewait
cp $(WEAVEWAIT_NOOP_EXE) prog/weaveexec/weavewait_noop
cp $(WEAVEWAIT_NOMCAST_EXE) prog/weaveexec/weavewait_nomcast
cp $(WEAVEUTIL_EXE) prog/weaveexec/weaveutil
tar -xf $(DOCKER_DISTRIB) usr/local/bin/docker -O > prog/weaveexec/docker
chmod +x prog/weaveexec/docker
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -f prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVEEXEC_IMAGE) prog/weaveexec
touch $@
$(PLUGIN_UPTODATE): prog/plugin/Dockerfile.$(DOCKERHUB_USER) $(PLUGIN_EXE) $(WEAVER_UPTODATE)
$(SUDO) docker build -f prog/plugin/Dockerfile.$(DOCKERHUB_USER) -t $(PLUGIN_IMAGE) prog/plugin
# Builds Docker plugin.
$(PLUGIN_UPTODATE): prog/net-plugin/launch.sh prog/net-plugin/config.json $(WEAVER_UPTODATE)
-$(SUDO) docker rm -f $(PLUGIN_BUILD_IMG) 2>/dev/null
$(SUDO) docker create --name=$(PLUGIN_BUILD_IMG) $(WEAVER_IMAGE) true
rm -rf $(PLUGIN_WORK_DIR)
mkdir $(PLUGIN_WORK_DIR)
$(SUDO) docker export $(PLUGIN_BUILD_IMG) | tar -x -C $(PLUGIN_WORK_DIR)
$(SUDO) docker rm -f $(PLUGIN_BUILD_IMG)
cp prog/net-plugin/launch.sh $(PLUGIN_WORK_DIR)/home/weave/launch.sh
-$(SUDO) docker plugin disable $(PLUGIN_IMAGE):$(WEAVE_VERSION) 2>/dev/null
-$(SUDO) docker plugin rm $(PLUGIN_IMAGE):$(WEAVE_VERSION) 2>/dev/null
$(SUDO) docker plugin create $(PLUGIN_IMAGE):$(WEAVE_VERSION) prog/net-plugin
-$(SUDO) docker plugin disable $(PLUGIN_IMAGE):$(NET_PLUGIN_LATEST) 2>/dev/null
-$(SUDO) docker plugin rm $(PLUGIN_IMAGE):$(NET_PLUGIN_LATEST) 2>/dev/null
$(SUDO) docker plugin create $(PLUGIN_IMAGE):$(NET_PLUGIN_LATEST) prog/net-plugin
touch $@
$(WEAVEKUBE_UPTODATE): prog/weave-kube/Dockerfile.$(DOCKERHUB_USER) prog/weave-kube/launch.sh $(KUBEPEERS_EXE) $(WEAVER_UPTODATE)
@@ -280,18 +315,26 @@ $(WEAVEDB_UPTODATE): prog/weavedb/Dockerfile
$(SUDO) docker build -t $(WEAVEDB_IMAGE) prog/weavedb
touch $@
$(NETWORKTESTER_UPTODATE): test/images/network-tester/Dockerfile $(NETWORKTESTER_EXE)
$(SUDO) docker build -t $(NETWORKTESTER_IMAGE) test/images/network-tester
touch $@
$(WEAVE_EXPORT): $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker save $(addsuffix :latest,$(IMAGES)) | gzip > $@
$(DOCKER_DISTRIB):
curl -o $(DOCKER_DISTRIB) $(DOCKER_DISTRIB_URL)
cd $(shell dirname $@) && sha256sum -c $(shell pwd)/build/shasums/docker-tgz-$(WEAVEEXEC_DOCKER_ARCH).sha256sum
tools/.git $(MANIFEST_TOOL_DIR)/.git:
git submodule update --init
# CODE FOR PUBLISHING THE IMAGES
# Push plugin
plugin_publish: $(PLUGIN_UPTODATE)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker plugin push $(PLUGIN_IMAGE):$(WEAVE_VERSION)
# "$(NET_PLUGIN_LATEST)" means "stable release" here, so only push that if explicitly told to
ifeq ($(UPDATE_LATEST),true)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker plugin push $(PLUGIN_IMAGE):$(NET_PLUGIN_LATEST)
endif
# This target first runs "make publish" for each architecture
# Then it pushes the manifest lists
publish: $(addprefix sub-publish-,$(ALL_ARCHITECTURES)) $(WEAVEDB_UPTODATE)
@@ -311,7 +354,7 @@ publish-one-arch: $(PUBLISH)
$(PUBLISH): publish_%: $(IMAGES_UPTODATE)
# Tag :latest with the real version
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker tag $(DOCKERHUB_USER)/$*$(ARCH_EXT) $(DOCKERHUB_USER)/$*$(ARCH_EXT):$(WEAVE_VERSION)
# Push the image with the arch suffix for arm and arm64, and without suffix for amd64
# Push the image with the arch suffix for arm, arm64 and ppc64le, and without suffix for amd64
$(MAKE) DOCKER_HOST=$(DOCKER_HOST) DOCKERHUB_USER=$(DOCKERHUB_USER) WEAVE_VERSION=$(WEAVE_VERSION) UPDATE_LATEST=$(UPDATE_LATEST) push_$*$(ARCH_EXT)
ifeq ($(ARCH),amd64)
@@ -344,13 +387,16 @@ ifneq ($(UPDATE_LATEST),false)
$(MANIFEST_TOOL_EXE) push from-args --platforms $(ML_PLATFORMS) --template $(DOCKERHUB_USER)/$*-ARCH:latest --target $(DOCKERHUB_USER)/$*:latest
endif
clean-work-dir:
rm -rf $(PLUGIN_WORK_DIR)
clean-bin:
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(IMAGES)
find prog -type f -name "Dockerfile.*" -not -name "Dockerfile.template" -print | xargs rm -f
find prog -type f -name "*qemu-*" -print | xargs rm -f
rm -rf $(EXES) $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE) weave*.tar.gz $(DOCKER_DISTRIB) prog/weaveexec/docker .pkg
rm -rf $(EXES) $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE) weave*.tar.gz .pkg
clean: clean-bin
clean: clean-bin clean-work-dir
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(BUILD_IMAGE)
rm -rf test/tls/*.pem test/coverage.* test/coverage $(BUILD_UPTODATE) $(MANIFEST_TOOL_EXE)
+9 -8
View File
@@ -3,7 +3,6 @@
[![Integration Tests](https://circleci.com/gh/weaveworks/weave/tree/master.svg?style=shield)](https://circleci.com/gh/weaveworks/weave)
[![Coverage Status](https://coveralls.io/repos/weaveworks/weave/badge.svg)](https://coveralls.io/r/weaveworks/weave)
[![Go Report Card](https://goreportcard.com/badge/github.com/weaveworks/weave)](https://goreportcard.com/report/github.com/weaveworks/weave)
[![Slack Status](https://slack.weave.works/badge.svg)](https://slack.weave.works)
[![Docker Pulls](https://img.shields.io/docker/pulls/weaveworks/weave.svg?maxAge=604800)](https://hub.docker.com/r/weaveworks/weave/)
# About Weaveworks
@@ -11,11 +10,13 @@
[Weaveworks](https://www.weave.works) is the company that delivers the most productive way for developers to connect, observe and control
Docker containers.
This repository contains [Weave Net](https://www.weave.works/products/weave-net/), the first product developed by Weaveworks, and with over 8 million downloads to date, it enables you to get started with Docker clusters and portable apps in a fraction of the time compared with other solutions.
This repository contains [Weave Net](https://www.weave.works/products/weave-net/), the first product developed by Weaveworks, and with over 8 million downloads to date, enables you to get started with Docker clusters and portable apps in a fraction of the time compared with other solutions.
Weaveworks' product [Weave Cloud](https://www.weave.works/solution/cloud/) takes the heavy lifting out of building, integrating and operating open source components, so you don’t have to manage databases, storage and availability.
## Weave Cloud:
Weave Cloud is built using these Open Source projects: [Weave Scope](https://www.weave.works/products/weave-scope/), a powerful container monitoring tool that automatically maps Docker containers and their interactions, [Weave Cortex](https://github.com/weaveworks/cortex), a horizontally-scalable version of Prometheus, and [Weave Flux](https://www.weave.works/products/weave-flux/), a continuous deployment tool that works with Kubernetes.
[Weave Cloud](https://www.weave.works/product/cloud/) is software-as-a-service that simplifies deployment, monitoring and management for containers and microservices. It extends and complements popular orchestrators, and enables developers and DevOps to realize faster deployments, insightful monitoring, visualization and networking.
Weave Cloud is built using these Open Source projects: [Weave Scope](https://www.weave.works/products/weave-scope/), a powerful container visualization tool that automatically maps Docker containers and their interactions, [Weave Cortex](https://github.com/weaveworks/cortex), a horizontally-scalable version of Prometheus, and [Weave Flux](https://www.weave.works/products/weave-flux/), a continuous deployment tool that works with Kubernetes.
# Weave Net
@@ -27,7 +28,7 @@ Services provided by application containers on the Weave network can be exposed
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/introducing-weave/).
- Read [the Weave Net docs](https://www.weave.works/docs/net/latest/overview).
- Invite yourself to the <a href="https://weaveworks.github.io/community-slack/" target="_blank"> #weave-community </a> slack channel.
- Ask a question on the <a href="https://weave-community.slack.com/messages/general/"> #weave-community</a> slack channel.
- Join the <a href="https://www.meetup.com/pro/Weave/"> Weave User Group </a> and get invited to online talks, hands-on training and meetups in your area.
@@ -36,7 +37,7 @@ If you have any questions about, feedback for or a problem with Weave Net:
Your feedback is always welcome!
##Further Information
## Further Information
* [Installing Weave Net](https://www.weave.works/docs/net/latest/installing-weave/)
* [Weave Net Product Overview](https://www.weave.works/products/weave-net/)
* [Installing Weave Net](https://www.weave.works/docs/net/latest/install/installing-weave)
* [Weave Net Product Overview](https://www.weave.works/products/weave-net)
+25 -10
View File
@@ -3,6 +3,7 @@ package api
import (
"fmt"
"net"
"net/url"
)
// Special token used in place of a container identifier when:
@@ -14,21 +15,29 @@ import (
// which should be kept in mind if the entry needs to be removed at any point.
const NoContainerID string = "_"
func (client *Client) ipamOp(ID string, op string) (*net.IPNet, error) {
ip, err := client.httpVerb(op, fmt.Sprintf("/ip/%s", ID), nil)
func (client *Client) ipamOp(ID string, op string, values url.Values) (*net.IPNet, error) {
ip, err := client.httpVerb(op, fmt.Sprintf("/ip/%s", ID), values)
if err != nil {
return nil, err
}
return parseIP(ip)
}
// returns an IP for the ID given, allocating a fresh one if necessary
func (client *Client) AllocateIP(ID string) (*net.IPNet, error) {
return client.ipamOp(ID, "POST")
func ipamValues(checkAlive bool) url.Values {
values := make(url.Values)
if checkAlive {
values.Set("check-alive", "true")
}
return values
}
func (client *Client) AllocateIPInSubnet(ID string, subnet *net.IPNet) (*net.IPNet, error) {
ip, err := client.httpVerb("POST", fmt.Sprintf("/ip/%s/%s", ID, subnet), nil)
// returns an IP for the ID given, allocating a fresh one if necessary
func (client *Client) AllocateIP(ID string, checkAlive bool) (*net.IPNet, error) {
return client.ipamOp(ID, "POST", ipamValues(checkAlive))
}
func (client *Client) AllocateIPInSubnet(ID string, subnet *net.IPNet, checkAlive bool) (*net.IPNet, error) {
ip, err := client.httpVerb("POST", fmt.Sprintf("/ip/%s/%s", ID, subnet), ipamValues(checkAlive))
if err != nil {
return nil, err
}
@@ -38,12 +47,12 @@ func (client *Client) AllocateIPInSubnet(ID string, subnet *net.IPNet) (*net.IPN
// returns an IP for the ID given, or nil if one has not been
// allocated
func (client *Client) LookupIP(ID string) (*net.IPNet, error) {
return client.ipamOp(ID, "GET")
return client.ipamOp(ID, "GET", nil)
}
// Claim a specific IP on behalf of the ID
func (client *Client) ClaimIP(ID string, cidr *net.IPNet) error {
_, err := client.httpVerb("PUT", fmt.Sprintf("/ip/%s/%s", ID, cidr), nil)
func (client *Client) ClaimIP(ID string, cidr *net.IPNet, checkAlive bool) error {
_, err := client.httpVerb("PUT", fmt.Sprintf("/ip/%s/%s", ID, cidr), ipamValues(checkAlive))
return err
}
@@ -53,6 +62,12 @@ func (client *Client) ReleaseIPsFor(ID string) error {
return err
}
// release all IP space owned by a peer
func (client *Client) RmPeer(peerName string) (string, error) {
result, err := client.httpVerb("DELETE", fmt.Sprintf("/peer/%s", peerName), nil)
return result, err
}
func (client *Client) DefaultSubnet() (*net.IPNet, error) {
cidr, err := client.httpVerb("GET", fmt.Sprintf("/ipinfo/defaultsubnet"), nil)
if err != nil {
+12
View File
@@ -0,0 +1,12 @@
package api
import (
"fmt"
"net"
)
// Expose calls the router to assign the given IP addr to the weave bridge.
func (client *Client) Expose(ipAddr *net.IPNet) error {
_, err := client.httpVerb("POST", fmt.Sprintf("/expose/%s", ipAddr), nil)
return err
}
+17
View File
@@ -8,6 +8,7 @@ import (
"net/http"
"net/url"
"strings"
"time"
)
const (
@@ -76,6 +77,22 @@ func (client *Client) Connect(remote string) error {
return err
}
// IsReady returns true if the API server is up and running
// (note it returns StatusServiceUnavailable until all parts are ready,
// but callers of this function are expected to be ok with a partial service)
func (client *Client) IsReady() bool {
resp, err := http.Get(client.baseURL + "/status")
return err == nil &&
(resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusServiceUnavailable)
}
// WaitAPIServer waits until the API server is ready to serve.
func (client *Client) WaitAPIServer(n int) {
for i := 0; i < n && !client.IsReady(); i++ {
time.Sleep(2 * time.Second)
}
}
type Logger interface {
Infof(string, ...interface{})
Debugf(string, ...interface{})
+2 -2
View File
@@ -41,7 +41,7 @@ case "$1" in
for i in $(seq $START $FINISH); do
IP=$SUBNET.$i
sudo ip addr add $IP/24 dev multiweave
weave $i launch-router --datapath '' --iface '' --no-dns --host $IP \
weave $i launch --datapath '' --iface '' --no-dns --host $IP \
--name $(random_mac) --nickname weave$i "$@"
done
echo $(date -R) connecting
@@ -57,7 +57,7 @@ case "$1" in
for i in $(seq $FINISH -1 $START); do
IP=$SUBNET.$i
echo Stopping weave$i
weave $i stop-router
weave $i stop
sudo ip addr del $IP/24 dev multiweave || true
done
[ -z "$(ip -4 -o addr show multiweave)" ] && sudo ip link del multiweave
+3 -1
View File
@@ -17,7 +17,9 @@ function install_terraform() {
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 cffi && pip install --user ansible
sudo apt-get install -qq -y python-pip python-dev libffi-dev libssl-dev \
&& pip install --user -U setuptools cffi \
&& pip install --user ansible
export PATH="$PATH:$HOME/.local/bin"
}
+26 -3
View File
@@ -88,9 +88,10 @@ build() {
## Inject the version numbers and build the distributables
## (library versions?)
sed -i "/SCRIPT_VERSION=/ c\SCRIPT_VERSION=\"$VERSION\"" ./weave
sed -i -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset.yaml
sed -i -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.6.yaml
sed -i.bak "/SCRIPT_VERSION=/ c\SCRIPT_VERSION=\"$VERSION\"" ./weave
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset.yaml
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.6.yaml
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.7.yaml
make SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER
if make tests; then
@@ -173,6 +174,13 @@ draft() {
--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"
echo "** Draft $TYPE $RELEASE_NAME $VERSION created at"
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
}
@@ -187,6 +195,10 @@ publish() {
fi
if [ "$RELEASE_TYPE" = 'PRERELEASE' ] ; then
echo "== Building and pushing plugin"
make UPDATE_LATEST=false SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER plugin_publish
echo "** Plugin built and pushed"
echo "== Tagging and pushing images on docker hub as user $DOCKERHUB_USER"
make UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER publish
echo "** Docker images tagged and pushed"
@@ -219,6 +231,10 @@ publish() {
fi
echo '** Sanity checks OK for publishing tag' $LATEST_TAG as $DOCKERHUB_USER/weave:$VERSION
echo "== Building and pushing plugin"
make UPDATE_LATEST=true SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER plugin_publish
echo "** Plugin built and pushed"
echo "== Tagging and pushing images on docker hub as user $DOCKERHUB_USER"
make PUBLISH_WEAVEDB=$IS_MAINLINE UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER publish
echo "** Docker images tagged and pushed"
@@ -266,6 +282,13 @@ publish() {
--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"
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"
+9 -6
View File
@@ -1,24 +1,27 @@
FROM golang:1.7.4
FROM golang:1.8.1
# Support Raspberry Pi 2 and newer
ENV GOARM 7
# The names of the architectures that we're fetching cross-compilers for from the Ubuntu packages
# The names of the architectures that we're fetching cross-compilers for from the Debian packages
ENV DEB_CROSSPLATFORMS \
armhf \
arm64
arm64 \
ppc64el
# The go platforms we are supporting to cross-compile
ENV GO_CROSSPLATFORMS \
linux/arm \
linux/arm64
linux/arm64 \
linux/ppc64le
# The names of the gcc cross-compilers we have installed
ENV GCC_CROSSCOMPILERS \
arm-linux-gnueabihf \
aarch64-linux-gnu
aarch64-linux-gnu \
powerpc64le-linux-gnu
# Temporarily add the Ubuntu repositories, because we're going to install gcc cross-compilers from there
# Temporarily add the Debian repositories, because we're going to install gcc cross-compilers from there
# Install the build-essential and crossbuild-essential-ARCH packages
RUN echo "deb http://emdebian.org/tools/debian/ jessie main" > /etc/apt/sources.list.d/cgocrosscompiling.list \
&& curl http://emdebian.org/tools/debian/emdebian-toolchain-archive.key | apt-key add - \
-1
View File
@@ -1 +0,0 @@
8f313a9df867c207ae9ceac6e0935d1d2a0360aafce780dd5d1e0687ee98e0c3 docker-1.10.3.tgz
@@ -1 +0,0 @@
7541b5490cee1183d911f909c0e91d3d9d57b2b775e40f14a1a7a6de216ca4a8 docker-1.10.3.tgz
@@ -0,0 +1 @@
926f7f265332076ea4abf6e9586288376dbed2322c155b8d0cafbee614aaa7f2 qemu-ppc64le-static
+7
View File
@@ -0,0 +1,7 @@
## Community Code of Conduct
Weaveworks follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
Instances of abusive, harassing, or otherwise unacceptable behavior
may be reported by contacting a Weaveworks project maintainer, or
Alexis Richardson alexis@weave.works.
+38 -2
View File
@@ -165,13 +165,25 @@ func (pending pendingStarts) finish(id string) {
}
}
// AllContainerIDs returns all the IDs of Docker containers,
// whether they are running or not.
func (c *Client) AllContainerIDs() ([]string, error) {
all, err := c.ListContainers(docker.ListContainersOptions{All: true})
return c.containerIDs(true)
}
// RunningContainerIDs returns all the IDs of the running
// Docker containers.
func (c *Client) RunningContainerIDs() ([]string, error) {
return c.containerIDs(false)
}
func (c *Client) containerIDs(all bool) ([]string, error) {
containers, err := c.ListContainers(docker.ListContainersOptions{All: all})
if err != nil {
return nil, err
}
var ids []string
for _, c := range all {
for _, c := range containers {
ids = append(ids, c.ID)
}
return ids, nil
@@ -213,6 +225,30 @@ func (c *Client) GetContainerIP(nameOrID string) (string, error) {
return info.NetworkSettings.IPAddress, nil
}
func (c *Client) EnsureNetwork(networkName, driver, subnet string, options map[string]interface{}) error {
_, err := c.CreateNetwork(
docker.CreateNetworkOptions{
Name: networkName,
CheckDuplicate: true,
Driver: driver,
IPAM: docker.IPAMOptions{
Driver: driver,
Config: []docker.IPAMConfig{{Subnet: subnet}},
},
Options: options,
})
if err != docker.ErrNetworkAlreadyExists && err != nil {
// Despite appearances to the contrary, CreateNetwork does
// sometimes(always?) *not* return ErrNetworkAlreadyExists
// when the network already exists. Hence we need to check for
// this explicitly.
if _, err2 := c.NetworkInfo(networkName); err2 != nil {
return fmt.Errorf("unable to create network: %s", err)
}
}
return nil
}
// logging
func (c *Client) errorf(fmt string, args ...interface{}) {
+25
View File
@@ -0,0 +1,25 @@
package common
import (
"sync"
"sync/atomic"
)
type WaitGroup struct {
wg sync.WaitGroup
count int32
}
// Increase the count of things waiting and return a closure which calls Done
func (w *WaitGroup) Add() func() {
atomic.AddInt32(&w.count, 1)
w.wg.Add(1)
return func() {
w.wg.Done()
atomic.AddInt32(&w.count, -1)
}
}
func (w *WaitGroup) IsDone() bool {
return atomic.LoadInt32(&w.count) == 0
}
+9 -3
View File
@@ -26,10 +26,15 @@ var (
const (
NameIdent = "peername"
FileName = "data.db"
fileName = "data.db"
)
func NewBoltDB(dbPathname string) (*BoltDB, error) {
func Pathname(dbPrefix string) string {
return dbPrefix + fileName
}
func NewBoltDB(dbPrefix string) (*BoltDB, error) {
dbPathname := Pathname(dbPrefix)
db, err := bolt.Open(dbPathname, 0660, nil)
if err != nil {
return nil, fmt.Errorf("[boltDB] Unable to open %s: %s", dbPathname, err)
@@ -38,8 +43,9 @@ func NewBoltDB(dbPathname string) (*BoltDB, error) {
return &BoltDB{db: db}, err
}
func NewBoltDBReadOnly(dbPathname string) (*BoltDB, error) {
func NewBoltDBReadOnly(dbPrefix string) (*BoltDB, error) {
options := bolt.Options{Timeout: time.Millisecond * 50, ReadOnly: true}
dbPathname := Pathname(dbPrefix)
db, err := bolt.Open(dbPathname, 0660, &options)
if err != nil {
return nil, fmt.Errorf("[boltDB] Unable to open %s: %s", dbPathname, err)
+81
View File
@@ -0,0 +1,81 @@
# Weave Net Benchmarks
## 2017-02-16: Fast Datapath Encryption
Results: https://www.weave.works/weave-net-performance-fast-datapath/
* Two `c3.8xlarge` instances running Ubuntu 16.04 LTS (`ami-d8f4deab`) in
`eu-west-1` region of AWS.
* 10 Gigabit [Enhanced Networking](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enhanced-networking.html).
* `iperf 3.0.11`.
### fastdp
* Encrypted:
```
host1$ WEAVE_MTU=8916 weave launch --password=foobar
host1$ docker $(weave config) run --rm -ti --name server networkstatic/iperf3 -s
host2$ WEAVE_MTU=8916 weave launch --password=foobar host1
host2$ docker $(weave config) run --rm -ti networkstatic/iperf3 -c server
```
* Non-encrypted:
```
host1$ WEAVE_MTU=8950 weave launch
host1$ docker $(weave config) run --rm -ti --name server networkstatic/iperf3 -s
host2$ WEAVE_MTU=8950 weave launch --password=foobar host1
host2$ docker $(weave config) run --rm -ti networkstatic/iperf3 -c server
```
### sleeve
* Encrypted:
```
host1$ WEAVE_NO_FASTDP=1 weave launch --password=foobar
host1$ docker $(weave config) run --rm -ti --name server networkstatic/iperf3 -s
host2$ WEAVE_NO_FASTDP=1 weave launch --password=foobar host1
host2$ docker $(weave config) run --rm -ti networkstatic/iperf3 -c server
```
* Non-encrypted:
```
host1$ WEAVE_NO_FASTDP=1 weave launch
host1$ docker $(weave config) run --rm -ti --name server networkstatic/iperf3 -s
host2$ WEAVE_NO_FASTDP=1 weave launch --password=foobar host1
host2$ docker $(weave config) run --rm -ti networkstatic/iperf3 -c server
```
### host
* Non-encrypted:
```
host1$ iperf -s
host2$ iperf -c host1
```
* Encrypted:
```
host1$ export KEY1="0x466454f2b1a770f8f872f9afbc35ebeac57e00fc11ac86ed1f82716f010b20f0cf532274"
host1$ export KEY2="0x3531151241a770f8f872f9afbc35ebeac57e00fc11ac86ed1f82716f010b20f0cf532274"
host1# ip xfrm state add src ${IP1} dst ${IP2} proto esp spi 0x4c856ffc replay-window 256 flag esn reqid 0 mode transport aead 'rfc4106(gcm(aes))' ${KEY1} 128
host1# ip xfrm state add src ${IP2} dst ${IP1} proto esp spi 0x9b0830bc replay-window 256 flag esn reqid 0 mode transport aead 'rfc4106(gcm(aes))' ${KEY2} 128
host1# ip xfrm policy add src ${IP1}/32 dst ${IP2}/32 dir out tmpl src ${IP1} dst ${IP2} proto esp spi 0x4c856ffc reqid 0 mode transport
host1$ iperf -s
host2$ export KEY1="0x466454f2b1a770f8f872f9afbc35ebeac57e00fc11ac86ed1f82716f010b20f0cf532274"
host2$ export KEY2="0x3531151241a770f8f872f9afbc35ebeac57e00fc11ac86ed1f82716f010b20f0cf532274"
host2# ip xfrm state add src ${IP2} dst ${IP1} proto esp spi 0x9b0830bc reqid 0 replay-window 256 flag esn mode transport aead 'rfc4106(gcm(aes))' ${KEY2} 128
host2# ip xfrm state add src ${IP1} dst ${IP2} proto esp spi 0x4c856ffc reqid 0 replay-window 256 flag esn mode transport aead 'rfc4106(gcm(aes))' ${KEY1} 128
host2# ip xfrm policy add src ${IP2}/32 dst ${IP1}/32 dir out tmpl src ${IP1} dst ${IP2} proto esp spi 0x9b0830bc reqid 0 mode transport
host2$ iperf -c host1
```
+70
View File
@@ -0,0 +1,70 @@
# Entrypoints
This document describes the various ways that weave as a binary gets launched, and where and how it processes options.
The goal is to enable maintainers to modify functionality without having to reverse engineer the code to find all of the places you can start a weave binary and what it depends upon.
## Components
### weaver
`weaver` is the primary binary: it sets up the weave bridge to which containers are attached, manages IP address allocation, serves DNS requests and does many more things.
Since version 2.0, `weaver` also bundles the Docker Plugin (legacy version) and Docker API Proxy which used to be shipped as separate containers.
### weaveutil
weaveutil is a binary which provides a number of functions for managing an existing weave network. It gets information about the network, attaches and detaches containers, etc.
For the majority of interactions with an existing weave network, you will launch `weaveutil` in some manner or another.
Almost all options can be passed as `--option` to `weaveutil`. These options are created in `prog/weaveutil/main.go` with a table mapping each command to a dedicated golang function.
In addition to operating in normal mode, `weaveutil` has several additional operating modes. Before processing any commands, `weaveutil` checks the filename with which it was called.
* If it was `weave-ipam` it delegates responsibility to the `cniIPAM()` function in `prog/weaveutil/cni.go`, which, in turn, calls the standard CNI plugin function `cni.PluginMain()`, passing it weave's IPAM implementation from `plugin/ipam`.
* If it was `weave-net` it delegates responsibility to the `cniNet()` function in `prog/weaveutil/cni.go`, which, in turn, calls the standard CNI plugin function `cni.PluginMain()`, passing it weave's net plugin implementation from `plugin/net`.
Finally, `weaveutil` is called by `weaver` when it needs to operate in a different network namespace.
Go programs cannot safely switch namespaces; see this [issue](http://github.com/vishvananda/netns/issues/17).
The call chain is `weaver`->`nsenter`->`weaveutil`.
### weave
Wrapping `weaver` and `weaveutil` is `weave`, a `sh` script that provides help information and calls `weaveutil` as relevant.
### weave-kube
weave-kube is an image with the weave binaries and a wrapper script installed. It is responsible for:
1. Setting up the weave network
2. Connecting to peers
3. Copy the weave CNI-compatible binary plugin `weaveutil` to `/opt/cni/bin/weave-net` and weave config in `/etc/cni/net.d/10-weave.conf`
4. Running the weave network policy controller (weave-npc) to implement kubernetes' `NetworkPolicy`
Once installation is complete, each network-relevant change in a container leads `kubelet` to:
1. Set certain environment variables to configure the CNI plugin, mostly related to the container ID
2. Launch `/opt/cni/bin/weave-net`
3. Pass the CNI config - the contents of `/etc/cni/net.d/10-weave.conf` to `weave-net`
Thus, when each container is changed, and `kubelet` calls weave as a CNI plugin, it really just is launching `weaveutil` as `weave-net`.
The installation and setup of all of the above - and therefore the entrypoint to the weave-kube image - is the script `prog/weave-kube/launch.sh`. `launch.sh` does the following:
1. Read configuration variables from the environment. When the documentation for `weave-kube` describes configuring the weave network by changing the environment variables in the daemonset in the `.yml` file, `launch.sh` reads these environment variables.
2. Set up the config file at `/etc/cni/net.d/10-weave.conf`
3. Run the `weave` initialization script
4. Run `weaver` with the correct configuration passed as command-line options
## Adding Options
To add new options to how weave should run with each invocation, you would do the following:
1. determine to which `weave` command you want to add the option(s). `weave` normally is launched as `weave <command> <options> ...`.
2. Add the option to `weave` script help for each `weave` command you wish to make it available. As of this writing, all of the commands and their options are listed in the function `usage_no_exist()`.
3. Add the option to `weave` script option processing for the `weave` command, under the `case $COMMAND in` in the main `weave` script.
4. In the function for the `weave` command, determine if the command should be passed on to `weaveutil` or `weaver`. Pass the option on to `weaveutil` or `weaver`, as appropriate, in the format `--option`, in the function for the `weave` command.
5. Add a command-line option `--option` to `weaveutil` or `weaver` as appropriate.
6. If the option can be configured for CNI:
* have `prog/weave-kube/launch.sh` read it as an environment variable and set inside
* set a default for the environment variable in `prog/weave-kube/weave-daemonset-k8s-1.6.yaml` and `weave-daemonset.yaml`
* if it should be set via `weaver` globally on its one-time initialization invocation, pass it on in `launch.sh`
* if it needs to be set via `weaveutil` on each invocation of `weave-net`, have `launch.sh` save it as an option in the CNI config file `/etc/cni/net.d/10-weave.conf` and then have the CNI code in `plugin/net/cni.go` in `weaveutil` read it and use where appropriate
7. Document it!
+1 -2
View File
@@ -4,8 +4,7 @@
* Up-to-date versions of `git`, `go` etc
* Install GitHub release tool `go get github.com/weaveworks/github-release`
* Create a [github token for
github-release](https://help.github.com/articles/creating-an-access-token-for-command-line-use/);
set and export `$GITHUB_TOKEN` with this value
github-release](https://help.github.com/articles/creating-an-access-token-for-command-line-use/); select the `repo` OAuth scope; set and export `$GITHUB_TOKEN` with this value
## Release Types
+19
View File
@@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/net/address"
"github.com/weaveworks/weave/testing/gossip"
@@ -30,6 +31,10 @@ func (alloc *Allocator) SimplyClaim(ident string, cidr address.CIDR) error {
return alloc.Claim(ident, cidr, true, true, returnFalse)
}
func (alloc *Allocator) AnonymousClaim(cidr address.CIDR) error {
return alloc.Claim(api.NoContainerID, cidr, false, true, returnFalse)
}
func TestAllocFree(t *testing.T) {
const (
container1 = "abcdef"
@@ -170,6 +175,8 @@ func TestAllocatorClaim(t *testing.T) {
universe = "10.0.3.0/24"
testAddr1 = "10.0.3.5/24"
testAddr2 = "10.0.4.2/24"
testAddr4 = "10.0.2.3/23"
subnet4 = "10.0.2.0/23"
testPre = "10.0.3.1/24"
)
@@ -203,6 +210,9 @@ func TestAllocatorClaim(t *testing.T) {
// claim for a different container should fail
err = alloc.SimplyClaim(container1, addr1)
require.Error(t, err)
// claim for an anonymous container, will assume it's the same one
err = alloc.AnonymousClaim(addr1)
require.NoError(t, err)
// claiming the address allocated on the other peer should fail
err = alloc.SimplyClaim(container1, address.MakeCIDR(subnet, addrx))
require.Error(t, err, "claiming address allocated on other peer should fail")
@@ -215,6 +225,15 @@ func TestAllocatorClaim(t *testing.T) {
addr2, _ := address.ParseCIDR(testAddr2)
err = alloc.SimplyClaim(container1, addr2)
require.NoError(t, err)
err = alloc.SimplyClaim(container3, addr2)
require.Error(t, err)
// Anonymous claim outside of our universe
addr4, _ := address.ParseCIDR(testAddr4)
subnet4cidr, _ := address.ParseCIDR(subnet4)
require.NoError(t, alloc.AnonymousClaim(addr4))
addr5, err := alloc.Allocate(api.NoContainerID, subnet4cidr, false, returnFalse)
require.NoError(t, err)
require.NotEqual(t, addr4.Start(), addr5)
}
func (alloc *Allocator) pause() func() {
+22 -7
View File
@@ -40,10 +40,29 @@ func (c *claim) Try(alloc *Allocator) bool {
return true
}
addOwned := func() {
if c.ident == api.NoContainerID {
alloc.addOwned(c.cidr.Addr.String(), c.cidr, c.isContainer)
} else {
alloc.addOwned(c.ident, c.cidr, c.isContainer)
}
}
if !alloc.ring.Contains(c.cidr.Addr) {
// Address not within our universe; assume user knows what they are doing
alloc.infof("Address %s claimed by %s - not in our range", c.cidr, c.ident)
alloc.addOwned(c.ident, c.cidr, c.isContainer)
previousOwner := alloc.findOwner(c.cidr.Addr)
switch {
case previousOwner == "":
addOwned()
case previousOwner == c.ident: // already owned by this ID
case c.ident == api.NoContainerID: // already owned by anonymous container
// do nothing (no automatic fall-through in Go)
case !alloc.dead[previousOwner].IsZero(): // already owned by dead container
alloc.removeOwned(previousOwner, c.cidr.Addr)
addOwned()
default:
c.sendResult(fmt.Errorf("address %s already in use by %s", c.cidr, previousOwner))
}
c.sendResult(nil)
return true
}
@@ -85,11 +104,7 @@ func (c *claim) Try(alloc *Allocator) bool {
// Unused address, we try to claim it:
if err := alloc.space.Claim(c.cidr.Addr); err == nil {
alloc.debugln("Claimed", c.cidr, "for", c.ident)
if c.ident == api.NoContainerID {
alloc.addOwned(c.cidr.Addr.String(), c.cidr, c.isContainer)
} else {
alloc.addOwned(c.ident, c.cidr, c.isContainer)
}
addOwned()
c.sendResult(nil)
} else {
c.sendResult(err)
+34 -11
View File
@@ -1,6 +1,7 @@
package ipam
import (
"encoding/json"
"fmt"
"net/http"
@@ -127,6 +128,39 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID
writeAddresses(w, addrs)
})
router.Methods("GET").Path("/ip").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
type mapping struct {
ContainerID string `json:"containerid"`
Addrs []string `json:"addrs"`
}
type mappings struct {
Owned []mapping `json:"owned"`
}
resultChan := make(chan mappings)
alloc.actionChan <- func() {
ms := mappings{}
for containerid, d := range alloc.owned {
m := mapping{
ContainerID: containerid,
Addrs: []string{},
}
for _, addr := range d.Cidrs {
m.Addrs = append(m.Addrs, addr.String())
}
ms.Owned = append(ms.Owned, m)
}
resultChan <- ms
}
ms := <-resultChan
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(ms); err != nil {
common.Log.Warningln("[allocator]:", err.Error())
}
})
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 {
@@ -164,17 +198,6 @@ func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CID
w.WriteHeader(204)
})
router.Methods("DELETE").Path("/peer").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
alloc.Shutdown()
w.WriteHeader(204)
})
router.Methods("DELETE").Path("/peer/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ident := mux.Vars(r)["id"]
transferred := alloc.AdminTakeoverRanges(ident)
fmt.Fprintf(w, "%d IPs taken over from %s\n", transferred, ident)
})
router.Methods("GET").Path("/ipinfo/tracker").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, tracker)
})
+3 -4
View File
@@ -30,7 +30,6 @@ import (
"github.com/vishvananda/netlink"
"github.com/weaveworks/weave/common"
wnet "github.com/weaveworks/weave/net"
"github.com/weaveworks/weave/net/address"
)
@@ -42,7 +41,7 @@ type AWSVPCTracker struct {
}
// NewAWSVPCTracker creates and initialises AWS VPC based tracker.
func NewAWSVPCTracker() (*AWSVPCTracker, error) {
func NewAWSVPCTracker(bridgeName string) (*AWSVPCTracker, error) {
var (
err error
session = session.New()
@@ -69,9 +68,9 @@ func NewAWSVPCTracker() (*AWSVPCTracker, error) {
t.routeTableID = *routeTableID
// Detect Weave bridge link index
link, err := netlink.LinkByName(wnet.WeaveBridgeName)
link, err := netlink.LinkByName(bridgeName)
if err != nil {
return nil, fmt.Errorf("cannot find \"%s\" interface: %s", wnet.WeaveBridgeName, err)
return nil, fmt.Errorf("cannot find \"%s\" interface: %s", bridgeName, err)
}
t.linkIndex = link.Attrs().Index
+3 -8
View File
@@ -27,7 +27,7 @@ func (n *Nameserver) HandleHTTP(router *mux.Router, dockerCli *docker.Client) {
vars = mux.Vars(r)
container = vars["container"]
ipStr = vars["ip"]
hostname = dns.Fqdn(r.FormValue("fqdn"))
fqdn = r.FormValue("fqdn")
ip, err = address.ParseIP(ipStr)
)
if err != nil {
@@ -35,16 +35,11 @@ func (n *Nameserver) HandleHTTP(router *mux.Router, dockerCli *docker.Client) {
return
}
if !dns.IsSubDomain(n.domain, hostname) {
n.infof("Ignoring registration %s %s %s (not a subdomain of %s)", hostname, ipStr, container, n.domain)
return
}
n.AddEntry(hostname, container, n.ourName, ip)
n.AddEntryFQDN(fqdn, container, n.ourName, ip)
if r.FormValue("check-alive") == "true" && dockerCli != nil && dockerCli.IsContainerNotRunning(container) {
n.infof("container '%s' is not running: removing", container)
n.Delete(hostname, container, ipStr, ip)
n.Delete(dns.Fqdn(fqdn), container, ipStr, ip)
}
w.WriteHeader(204)
+9
View File
@@ -91,6 +91,15 @@ func (n *Nameserver) AddEntry(hostname, containerid string, origin mesh.PeerName
n.broadcastEntries(entry)
}
func (n *Nameserver) AddEntryFQDN(fqdn, containerid string, origin mesh.PeerName, addr address.Address) {
hostname := dns.Fqdn(fqdn)
if !dns.IsSubDomain(n.domain, hostname) {
n.infof("Ignoring registration %s %s %s (not a subdomain of %s)", hostname, addr.String(), containerid, n.domain)
return
}
n.AddEntry(hostname, containerid, origin, addr)
}
func (n *Nameserver) Lookup(hostname string) []address.Address {
n.RLock()
defer n.RUnlock()
+5
View File
@@ -160,6 +160,11 @@ func (cidr CIDR) String() string {
return fmt.Sprintf("%s/%d", cidr.Addr.String(), cidr.PrefixLen)
}
func (cidr CIDR) IPNet() (r *net.IPNet) {
mask := net.CIDRMask(cidr.PrefixLen, 8*net.IPv4len)
return &net.IPNet{IP: cidr.Addr.IP4(), Mask: mask}
}
// FromIP4 converts an ipv4 address to our integer address type
func FromIP4(ip4 net.IP) (r Address) {
for _, b := range ip4.To4() {
+13
View File
@@ -1,6 +1,7 @@
package address
import (
"net"
"testing"
"testing/quick"
@@ -67,3 +68,15 @@ func TestCIDRStartAndEnd(t *testing.T) {
require.Equal(t, ip("10.0.0.0"), cidr.Start(), "")
require.Equal(t, ip("10.0.1.0"), cidr.End(), "")
}
func TestConversions(t *testing.T) {
addrStr := "10.2.3.0"
cidrStr := addrStr + "/24"
addr := ip(addrStr)
require.Equal(t, addr.String(), addrStr)
require.Equal(t, addr.IP4(), net.ParseIP(addrStr).To4())
cidr, _ := ParseCIDR(cidrStr)
require.Equal(t, cidr.String(), cidrStr)
_, ipnet, _ := net.ParseCIDR(cidrStr)
require.Equal(t, cidr.IPNet(), ipnet)
}
+12 -12
View File
@@ -1,27 +1,27 @@
package net
import "fmt"
import "io"
import "os"
import (
"fmt"
"io"
"os"
"path/filepath"
)
// Configure the ARP cache parameters for the given interface. This
// makes containers react more quickly to a change in the MAC address
// associated with an IP address.
func ConfigureARPCache(name string) error {
if err := sysctl(fmt.Sprintf("net/ipv4/neigh/%s/base_reachable_time", name), "5"); err != nil {
func ConfigureARPCache(procPath, name string) error {
if err := sysctl(procPath, fmt.Sprintf("net/ipv4/neigh/%s/base_reachable_time", name), "5"); err != nil {
return err
}
if err := sysctl(fmt.Sprintf("net/ipv4/neigh/%s/delay_first_probe_time", name), "2"); err != nil {
if err := sysctl(procPath, fmt.Sprintf("net/ipv4/neigh/%s/delay_first_probe_time", name), "2"); err != nil {
return err
}
if err := sysctl(fmt.Sprintf("net/ipv4/neigh/%s/ucast_solicit", name), "1"); err != nil {
return err
}
return nil
return sysctl(procPath, fmt.Sprintf("net/ipv4/neigh/%s/ucast_solicit", name), "1")
}
func sysctl(variable, value string) error {
f, err := os.OpenFile(fmt.Sprintf("/proc/sys/%s", variable), os.O_WRONLY, 0)
func sysctl(procPath, variable, value string) error {
f, err := os.OpenFile(filepath.Join(procPath, "/sys/", variable), os.O_WRONLY, 0)
if err != nil {
return err
}
+392 -13
View File
@@ -2,43 +2,136 @@ package net
import (
"fmt"
"io/ioutil"
"net"
"path/filepath"
"github.com/Sirupsen/logrus"
"github.com/coreos/go-iptables/iptables"
"github.com/pkg/errors"
"github.com/vishvananda/netlink"
"github.com/weaveworks/weave/common/odp"
)
type BridgeType int
/* This code implements three possible configurations to connect
containers to the Weave Net overlay:
1. Bridge
+-------+
(container-veth)-+ weave +-(vethwe-bridge)--(vethwe-pcap)
+-------+
"weave" is a Linux bridge. "vethwe-pcap" (end of veth pair) is used
to capture and inject packets, by router/pcap.go.
2. BridgedFastdp
+-------+ /----------\
(container-veth)-+ weave +-(vethwe-bridge)--(vethwe-datapath)-+ datapath +
+-------+ \----------/
"weave" is a Linux bridge and "datapath" is an Open vSwitch datapath;
they are connected via a veth pair. Packet capture and injection use
the "datapath" device, via "router/fastdp.go:fastDatapathBridge"
3. Fastdp
/-------\
(container-veth)-+ weave +
\-------/
"weave" is an Open vSwitch datapath, and capture/injection are as in
BridgedFastdp. Not used by default due to missing conntrack support in
datapath of old kernel versions (https://github.com/weaveworks/weave/issues/1577).
*/
const (
WeaveBridgeName = "weave"
DatapathName = "datapath"
None BridgeType = iota
Bridge
Fastdp
BridgedFastdp
Inconsistent
DatapathIfName = "vethwe-datapath"
BridgeIfName = "vethwe-bridge"
PcapIfName = "vethwe-pcap"
)
func DetectBridgeType(weaveBridgeName, datapathName string) BridgeType {
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
}
// Used to indicate a fallback to the Bridge type
var errBridgeNotSupported = errors.New("bridge not supported")
type bridgeImpl struct{ bridge netlink.Link }
type fastdpImpl struct{ datapathName string }
type bridgedFastdpImpl struct {
bridgeImpl
fastdpImpl
}
// Returns a string that is consistent with the weave script
func (bridgeImpl) String() string { return "bridge" }
func (fastdpImpl) String() string { return "fastdp" }
func (bridgedFastdpImpl) String() string { return "bridged_fastdp" }
// Used to decide whether to manage ODP tunnels
func (bridgeImpl) IsFastdp() bool { return false }
func (fastdpImpl) IsFastdp() bool { return true }
func (bridgedFastdpImpl) IsFastdp() bool { return true }
func ExistingBridgeType(weaveBridgeName, datapathName string) (Bridge, error) {
bridge, _ := netlink.LinkByName(weaveBridgeName)
datapath, _ := netlink.LinkByName(datapathName)
switch {
case bridge == nil && datapath == nil:
return None
return nil, nil
case isBridge(bridge) && datapath == nil:
return Bridge
return bridgeImpl{bridge: bridge}, nil
case isDatapath(bridge) && datapath == nil:
return Fastdp
return fastdpImpl{datapathName: datapathName}, nil
case isDatapath(datapath) && isBridge(bridge):
return BridgedFastdp
return bridgedFastdpImpl{bridgeImpl{bridge: bridge}, fastdpImpl{datapathName: datapathName}}, nil
default:
return Inconsistent
return nil, errors.New("Inconsistent bridge state detected. Please do 'weave reset' and try again")
}
}
func EnforceAddrAssignType(bridgeName string) (setAddr bool, err error) {
sysctlFilename := filepath.Join("/sys/class/net/", bridgeName, "/addr_assign_type")
addrAssignType, err := ioutil.ReadFile(sysctlFilename)
if err != nil {
return false, errors.Wrapf(err, "reading %q", sysctlFilename)
}
// From include/uapi/linux/netdevice.h
// #define NET_ADDR_PERM 0 /* address is permanent (default) */
// #define NET_ADDR_RANDOM 1 /* address is generated randomly */
// #define NET_ADDR_STOLEN 2 /* address is stolen from other device */
// #define NET_ADDR_SET 3 /* address is set using dev_set_mac_address() */
// Note the file typically has a newline at the end, so we just look at the first char
if addrAssignType[0] != '3' {
link, err := netlink.LinkByName(bridgeName)
if err != nil {
return false, errors.Wrapf(err, "EnforceAddrAssignType finding bridge %s", bridgeName)
}
mac, err := RandomMAC()
if err != nil {
return false, errors.Wrap(err, "creating random MAC")
}
if err := netlink.LinkSetHardwareAddr(link, mac); err != nil {
return false, errors.Wrapf(err, "setting bridge %s address to %v", bridgeName, mac)
}
return true, nil
}
return false, nil
}
func isBridge(link netlink.Link) bool {
_, isBridge := link.(*netlink.Bridge)
return isBridge
@@ -108,3 +201,289 @@ func FindBridgeIP(bridgeName string, subnet *net.IPNet) (net.IP, error) {
// No subnet, or none in the required subnet; just return the first one
return netdev.CIDRs[0].IP, nil
}
type BridgeConfig struct {
DockerBridgeName string
WeaveBridgeName string
DatapathName string
NoFastdp bool
NoBridgedFastdp bool
AWSVPC bool
NPC bool
MTU int
Mac string
Port int
}
func (config *BridgeConfig) configuredBridgeType() Bridge {
switch {
case config.NoFastdp:
return bridgeImpl{}
case config.NoBridgedFastdp:
return fastdpImpl{datapathName: config.WeaveBridgeName}
default:
return bridgedFastdpImpl{fastdpImpl: fastdpImpl{datapathName: config.DatapathName}}
}
}
func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger) (Bridge, error) {
bridgeType, err := ExistingBridgeType(config.WeaveBridgeName, config.DatapathName)
if bridgeType != nil || err != nil {
return bridgeType, err
}
bridgeType = config.configuredBridgeType()
for {
if err := bridgeType.init(config); err != nil {
if errors.Cause(err) == errBridgeNotSupported {
log.Warnf("Skipping bridge creation of %q due to: %s", bridgeType, err)
bridgeType = bridgeImpl{}
continue
}
return nil, err
}
break
}
if err := configureIPTables(config); err != nil {
return bridgeType, errors.Wrap(err, "configuring iptables")
}
if config.AWSVPC {
// Set proxy_arp on the bridge, so that it could accept packets destined
// to containers within the same subnet but running on remote hosts.
// Without it, exact routes on each container are required.
if err := sysctl(procPath, "net/ipv4/conf/"+config.WeaveBridgeName+"/proxy_arp", "1"); err != nil {
return bridgeType, errors.Wrap(err, "setting proxy_arp")
}
// Avoid delaying the first ARP request. Also, setting it to 0 avoids
// placing the request into a bounded queue as it can be seen:
// https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/net/ipv4/arp.c?id=refs/tags/v4.6.1#n819
if err := sysctl(procPath, "net/ipv4/neigh/"+config.WeaveBridgeName+"/proxy_delay", "0"); err != nil {
return bridgeType, errors.Wrap(err, "setting proxy_arp")
}
}
if err := linkSetUpByName(config.WeaveBridgeName); err != nil {
return bridgeType, err
}
if err := ConfigureARPCache(procPath, config.WeaveBridgeName); err != nil {
return bridgeType, errors.Wrapf(err, "configuring ARP cache on bridge %q", config.WeaveBridgeName)
}
return bridgeType, nil
}
func (b bridgeImpl) initPrep(config *BridgeConfig) error {
mac, err := net.ParseMAC(config.Mac)
if err != nil {
return errors.Wrapf(err, "parsing bridge MAC %q", config.Mac)
}
linkAttrs := netlink.NewLinkAttrs()
linkAttrs.Name = config.WeaveBridgeName
linkAttrs.HardwareAddr = mac
if config.MTU == 0 {
config.MTU = 65535
}
b.bridge = &netlink.Bridge{LinkAttrs: linkAttrs}
if err = netlink.LinkAdd(b.bridge); err != nil {
return errors.Wrapf(err, "creating bridge %q", config.WeaveBridgeName)
}
if err := netlink.LinkSetHardwareAddr(b.bridge, mac); err != nil {
return errors.Wrapf(err, "setting bridge %q mac %v", config.WeaveBridgeName, mac)
}
// Attempting to set the bridge MTU to a high value directly
// fails. Bridges take the lowest MTU of their interfaces. So
// instead we create a temporary interface with the desired MTU,
// attach that to the bridge, and then remove it again.
dummy := &netlink.Dummy{LinkAttrs: netlink.NewLinkAttrs()}
dummy.LinkAttrs.Name = "vethwedu"
if err = netlink.LinkAdd(dummy); err != nil {
return errors.Wrap(err, "creating dummy interface")
}
if err := netlink.LinkSetMTU(dummy, config.MTU); err != nil {
return errors.Wrapf(err, "setting dummy interface mtu to %d", config.MTU)
}
if err := netlink.LinkSetMasterByIndex(dummy, b.bridge.Attrs().Index); err != nil {
return errors.Wrap(err, "setting dummy interface master")
}
if err := netlink.LinkDel(dummy); err != nil {
return errors.Wrap(err, "deleting dummy interface")
}
return nil
}
func (b bridgeImpl) init(config *BridgeConfig) error {
if err := b.initPrep(config); err != nil {
return err
}
if _, err := CreateAndAttachVeth(BridgeIfName, PcapIfName, config.WeaveBridgeName, config.MTU, true, func(veth netlink.Link) error {
return netlink.LinkSetUp(veth)
}); err != nil {
return errors.Wrap(err, "creating pcap veth pair")
}
if err := EthtoolTXOff(config.WeaveBridgeName); err != nil {
return errors.Wrap(err, "setting tx off")
}
return nil
}
func (f fastdpImpl) init(config *BridgeConfig) error {
odpSupported, err := odp.CreateDatapath(f.datapathName)
if !odpSupported {
msg := ""
if err != nil {
msg = err.Error()
}
return errors.Wrap(errBridgeNotSupported, msg)
}
if err != nil {
return errors.Wrapf(err, "creating datapath %q", f.datapathName)
}
datapath, err := netlink.LinkByName(f.datapathName)
if err != nil {
return errors.Wrapf(err, "finding datapath %q", f.datapathName)
}
if config.MTU == 0 {
/* GCE has the lowest underlay network MTU we're likely to encounter on
a local network, at 1460 bytes. To get the overlay MTU from that we
subtract 20 bytes for the outer IPv4 header, 8 bytes for the outer
UDP header, 8 bytes for the vxlan header, and 14 bytes for the inner
ethernet header. In addition, we subtract 34 bytes for the ESP overhead
which is needed for the vxlan encryption. */
config.MTU = 1376
}
if err := netlink.LinkSetMTU(datapath, config.MTU); err != nil {
return errors.Wrapf(err, "setting datapath %q mtu %d", f.datapathName, config.MTU)
}
return nil
}
func (bf bridgedFastdpImpl) init(config *BridgeConfig) error {
if err := bf.fastdpImpl.init(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, func(veth netlink.Link) error {
if err := netlink.LinkSetUp(veth); err != nil {
return errors.Wrapf(err, "setting link up on %q", veth.Attrs().Name)
}
if err := odp.AddDatapathInterface(bf.datapathName, veth.Attrs().Name); err != nil {
return errors.Wrapf(err, "adding interface %q to datapath %q", veth.Attrs().Name, bf.datapathName)
}
return nil
}); err != nil {
return errors.Wrap(err, "creating bridged fastdp veth pair")
}
return linkSetUpByName(bf.datapathName)
}
func (b bridgeImpl) attach(veth *netlink.Veth) error {
return netlink.LinkSetMasterByIndex(veth, b.bridge.Attrs().Index)
}
func (bf bridgedFastdpImpl) attach(veth *netlink.Veth) error {
return bf.bridgeImpl.attach(veth)
}
func (f fastdpImpl) attach(veth *netlink.Veth) error {
return odp.AddDatapathInterface(f.datapathName, veth.Attrs().Name)
}
func configureIPTables(config *BridgeConfig) error {
ipt, err := iptables.New()
if err != nil {
return errors.Wrap(err, "creating iptables object")
}
if config.DockerBridgeName != "" {
if config.WeaveBridgeName != config.DockerBridgeName {
err := ipt.Insert("filter", "FORWARD", 1, "-i", config.DockerBridgeName, "-o", config.WeaveBridgeName, "-j", "DROP")
if err != nil {
return err
}
}
dockerBridgeIP, err := FindBridgeIP(config.DockerBridgeName, nil)
if err != nil {
return err
}
// forbid traffic to the Weave port from other containers
if err = ipt.AppendUnique("filter", "INPUT", "-i", config.DockerBridgeName, "-p", "tcp", "--dst", dockerBridgeIP.String(), "--dport", fmt.Sprint(config.Port), "-j", "DROP"); err != nil {
return err
}
if err = ipt.AppendUnique("filter", "INPUT", "-i", config.DockerBridgeName, "-p", "udp", "--dst", dockerBridgeIP.String(), "--dport", fmt.Sprint(config.Port), "-j", "DROP"); err != nil {
return err
}
if err = ipt.AppendUnique("filter", "INPUT", "-i", config.DockerBridgeName, "-p", "udp", "--dst", dockerBridgeIP.String(), "--dport", fmt.Sprint(config.Port+1), "-j", "DROP"); err != nil {
return err
}
// let DNS traffic to weaveDNS, since otherwise it might get blocked by the likes of UFW
if err = ipt.AppendUnique("filter", "INPUT", "-i", config.DockerBridgeName, "-p", "udp", "--dport", "53", "-j", "ACCEPT"); err != nil {
return err
}
if err = ipt.AppendUnique("filter", "INPUT", "-i", config.DockerBridgeName, "-p", "tcp", "--dport", "53", "-j", "ACCEPT"); err != nil {
return err
}
}
if config.NPC {
// Steer traffic via the NPC
_ = ipt.NewChain("filter", "WEAVE-NPC") // ignore error because it might already exist
// If WEAVE-NPC chain doesn't exist then next line will fail
if err = ipt.AppendUnique("filter", "FORWARD", "-o", config.WeaveBridgeName, "-j", "WEAVE-NPC"); err != nil {
return err
}
if err = ipt.AppendUnique("filter", "FORWARD", "-o", config.WeaveBridgeName, "-m", "state", "--state", "NEW", "-j", "NFLOG", "--nflog-group", "86"); err != nil {
return err
}
if err = ipt.AppendUnique("filter", "FORWARD", "-o", config.WeaveBridgeName, "-j", "DROP"); err != nil {
return err
}
} else {
// Work around the situation where there are no rules allowing traffic
// across our bridge. E.g. ufw
if err = ipt.AppendUnique("filter", "FORWARD", "-i", config.WeaveBridgeName, "-o", config.WeaveBridgeName, "-j", "ACCEPT"); err != nil {
return err
}
}
if !config.NPC {
// Create a chain for allowing ingress traffic when the bridge is exposed
_ = ipt.NewChain("filter", "WEAVE-EXPOSE")
if err = ipt.AppendUnique("filter", "FORWARD", "-o", config.WeaveBridgeName, "-j", "WEAVE-EXPOSE"); err != nil {
return err
}
}
// Forward from weave to the rest of the world
if err = ipt.AppendUnique("filter", "FORWARD", "-i", config.WeaveBridgeName, "!", "-o", config.WeaveBridgeName, "-j", "ACCEPT"); err != nil {
return err
}
// and allow replies back
if err = ipt.AppendUnique("filter", "FORWARD", "-o", config.WeaveBridgeName, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"); err != nil {
return err
}
// create a chain for masquerading
if err = ipt.ClearChain("nat", "WEAVE"); err != nil {
return errors.Wrap(err, "clearing WEAVE chain")
}
return ipt.AppendUnique("nat", "POSTROUTING", "-j", "WEAVE")
}
func linkSetUpByName(linkName string) error {
link, err := netlink.LinkByName(linkName)
if err != nil {
return errors.Wrapf(err, "setting link up on %q", linkName)
}
return netlink.LinkSetUp(link)
}
+115
View File
@@ -0,0 +1,115 @@
package net
import (
"net"
"syscall"
"github.com/coreos/go-iptables/iptables"
"github.com/j-keck/arping"
"github.com/pkg/errors"
"github.com/vishvananda/netlink"
)
// Expose makes the network accessible from a host by assigning a given IP address
// to the weave bridge.
//
// List of params:
// * "bridgeName" - a name of the weave bridge.
// * "ipAddr" - IP addr to be assigned to the bridge.
// * "removeDefaultRoute" - whether to remove a default route installed by the kernel (used only in the AWSVPC mode).
// * "npc" - whether is Weave NPC running.
func Expose(bridgeName string, ipAddr *net.IPNet, removeDefaultRoute, npc bool) error {
ipt, err := iptables.New()
if err != nil {
return errors.Wrap(err, "iptables.New")
}
cidr := ipAddr.String()
if err := addBridgeIPAddr(bridgeName, ipAddr, removeDefaultRoute); err != nil {
return errors.Wrap(err, "addBridgeIPAddr")
}
if err := exposeNAT(ipt, cidr); err != nil {
return errors.Wrap(err, "exposeNAT")
}
if !npc {
// Docker 1.13 has changed a default policy of FORWARD chain to DROP
// (https://github.com/moby/moby/pull/28257) which makes containers
// inaccessible from a remote host when the bridge is exposed.
//
// The change breaks e.g. the AWSVPC mode. To overcome this we install
// an explicit rule for accepting forwarded ingress traffic to an
// exposed subnet.
if err := ipt.AppendUnique("filter", "WEAVE-EXPOSE", "-d", cidr, "-j", "ACCEPT"); err != nil {
return errors.Wrap(err, "ipt.AppendUnique")
}
}
return nil
}
func addBridgeIPAddr(bridgeName string, addr *net.IPNet, removeDefaultRoute bool) error {
link, err := netlink.LinkByName(bridgeName)
if err != nil {
return errors.Wrapf(err, "addBridgeIPAddr finding bridge %q", bridgeName)
}
err = netlink.AddrAdd(link, &netlink.Addr{IPNet: addr})
// The IP addr might have been already set by a concurrent request, just ignore then
if err != nil && err != syscall.Errno(syscall.EEXIST) {
return errors.Wrapf(err, "adding address %v to %q", addr, bridgeName)
}
// Sending multiple ARP REQUESTs in the case of EEXIST above does not hurt
arping.GratuitousArpOverIfaceByName(addr.IP, bridgeName)
// Remove a default route installed by the kernel. Required by the AWSVPC mode.
if removeDefaultRoute {
routeFilter := &netlink.Route{
LinkIndex: link.Attrs().Index,
Dst: &net.IPNet{IP: addr.IP.Mask(addr.Mask), Mask: addr.Mask},
Protocol: 2, // RTPROT_KERNEL
}
filterMask := netlink.RT_FILTER_OIF | netlink.RT_FILTER_DST | netlink.RT_FILTER_PROTOCOL
routes, err := netlink.RouteListFiltered(netlink.FAMILY_V4, routeFilter, filterMask)
if err != nil {
return errors.Wrapf(err, "failed to get route list for bridge %q", bridgeName)
}
for _, r := range routes {
err = netlink.RouteDel(&r)
// Again, there might be a concurrent request for removing routes
if err != nil && err != syscall.Errno(syscall.ESRCH) {
return errors.Wrapf(err, "failed to delete default route %+v", r)
}
}
}
return nil
}
func exposeNAT(ipt *iptables.IPTables, cidr string) error {
if err := addNatRule(ipt, "-s", cidr, "-d", "224.0.0.0/4", "-j", "RETURN"); err != nil {
return err
}
if err := addNatRule(ipt, "-d", cidr, "!", "-s", cidr, "-j", "MASQUERADE"); err != nil {
return err
}
return addNatRule(ipt, "-s", cidr, "!", "-d", cidr, "-j", "MASQUERADE")
}
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
}
}
}
return err
}
return nil
}
}
+22
View File
@@ -82,3 +82,25 @@ func findInterface(ifaceName string) (iface *net.Interface, err error) {
}
return
}
func LocalAddresses() ([]*net.IPNet, error) {
links, err := netlink.LinkList()
if err != nil {
return nil, err
}
retval := []*net.IPNet{}
for _, link := range links {
if _, isBridge := link.(*netlink.Bridge); isBridge || (link.Attrs().Flags&net.FlagLoopback) != 0 {
continue
}
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
if err != nil {
return nil, err
}
for _, addr := range addrs {
retval = append(retval, addr.IPNet)
}
}
return retval, nil
}
+1 -4
View File
@@ -421,10 +421,7 @@ func (ipsec *IPSec) installDropNonEncrypted(srcIP, dstIP net.IP, udpPort int, in
func (ipsec *IPSec) removeDropNonEncrypted(srcIP, dstIP net.IP, udpPort int, inSPI SPI) error {
rules := rulesDropNonEncrypted(srcIP, dstIP, udpPort, inSPI)
if err := ipsec.resetRules(rules, true); err != nil {
return err
}
return nil
return ipsec.resetRules(rules, true)
}
func (ipsec *IPSec) removeDropNonEncryptedInbound(srcIP, dstIP net.IP, inSPI SPI) error {
+6 -1
View File
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"os/exec"
"path/filepath"
"runtime"
"github.com/vishvananda/netlink"
@@ -80,5 +81,9 @@ func WithNetNSByPid(pid int, cmd string, args ...string) ([]byte, error) {
}
func NSPathByPid(pid int) string {
return fmt.Sprintf("/proc/%d/ns/net", pid)
return NSPathByPidWithRoot("/", pid)
}
func NSPathByPidWithRoot(root string, pid int) string {
return filepath.Join(root, fmt.Sprintf("/proc/%d/ns/net", pid))
}
+4 -5
View File
@@ -36,8 +36,8 @@ func getSystemUUID(hostRoot string) ([]byte, error) {
return append(machineid, uuid...), nil
}
func getPersistedPeerName(pathName string) (mesh.PeerName, error) {
d, err := db.NewBoltDBReadOnly(pathName)
func getPersistedPeerName(dbPrefix string) (mesh.PeerName, error) {
d, err := db.NewBoltDBReadOnly(dbPrefix)
if err != nil {
return mesh.UnknownPeerName, err
}
@@ -56,9 +56,8 @@ func getPersistedPeerName(pathName string) (mesh.PeerName, error) {
func GetSystemPeerName(dbPrefix, hostRoot string) (string, error) {
// Check if we have a persisted name that matches the old-style ID for this host
if oldUUID, err := getOldStyleSystemUUID(); err == nil {
pathName := dbPrefix + db.FileName
if _, err := os.Stat(pathName); err == nil {
persistedPeerName, err := getPersistedPeerName(pathName)
if _, err := os.Stat(db.Pathname(dbPrefix)); err == nil {
persistedPeerName, err := getPersistedPeerName(dbPrefix)
if err != nil && !os.IsNotExist(err) {
return "", err
}
+89 -105
View File
@@ -4,15 +4,12 @@ import (
"fmt"
"net"
"strings"
"syscall"
"time"
"github.com/coreos/go-iptables/iptables"
"github.com/j-keck/arping"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
"github.com/weaveworks/weave/common/odp"
)
// create and attach a veth to the Weave bridge
@@ -40,22 +37,17 @@ func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, keepTXOn bo
return nil, fmt.Errorf(format, a...)
}
switch bridgeType := DetectBridgeType(bridgeName, DatapathName); bridgeType {
case Bridge, BridgedFastdp:
if err := netlink.LinkSetMasterByIndex(veth, bridge.Attrs().Index); err != nil {
return cleanup(`unable to set master of %s: %s`, name, err)
bridgeType, err := ExistingBridgeType(bridgeName, DatapathName)
if err != nil {
return cleanup("detect bridge type: %s", err)
}
if err := bridgeType.attach(veth); err != nil {
return cleanup("attaching veth %q to %q: %s", name, bridgeName, err)
}
if !bridgeType.IsFastdp() && !keepTXOn {
if err := EthtoolTXOff(veth.PeerName); err != nil {
return cleanup(`unable to set tx off on %q: %s`, peerName, err)
}
if bridgeType == Bridge && !keepTXOn {
if err := EthtoolTXOff(peerName); err != nil {
return cleanup(`unable to set tx off on %q: %s`, peerName, err)
}
}
case Fastdp:
if err := odp.AddDatapathInterface(bridgeName, name); err != nil {
return cleanup(`failed to attach %s to device "%s": %s`, name, bridgeName, err)
}
default:
return cleanup(`invalid bridge configuration`)
}
if init != nil {
@@ -111,8 +103,6 @@ func interfaceExistsInNamespace(netNSPath string, ifName string) bool {
return err == nil
}
// NB: This function can be used only by a process that terminates immediately
// after calling the function as it changes netns via WithNetNSLinkUnsafe.
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool, hairpinMode bool) error {
ns, err := netns.GetFromPath(netNSPath)
if err != nil {
@@ -120,11 +110,6 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
}
defer ns.Close()
ipt, err := iptables.New()
if err != nil {
return err
}
if !interfaceExistsInNamespace(netNSPath, ifName) {
maxIDLen := IFNAMSIZ - 1 - len(vethPrefix+"pl")
if len(id) > maxIDLen {
@@ -149,57 +134,92 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
}
if err := WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error {
newAddresses, err := AddAddresses(veth, cidrs)
if err != nil {
return err
}
args := []string{ifName, fmt.Sprintf("%t", withMulticastRoute)}
for _, cidr := range cidrs {
args = append(args, cidr.String())
}
if _, err := WithNetNS(netNSPath, "setup-iface-addrs", args...); err != nil {
return fmt.Errorf("error setting up interface addresses: %s", err)
}
return nil
}
// Add multicast ACCEPT rules for new subnets
for _, ipnet := range newAddresses {
acceptRule := []string{"-i", ifName, "-s", subnet(ipnet), "-d", "224.0.0.0/4", "-j", "ACCEPT"}
exists, err := ipt.Exists("filter", "INPUT", acceptRule...)
if err != nil {
return err
}
if !exists {
if err := ipt.Insert("filter", "INPUT", 1, acceptRule...); err != nil {
return err
}
}
}
if err := netlink.LinkSetUp(veth); err != nil {
return err
}
for _, ipnet := range newAddresses {
// If we don't wait for a bit here, we see the arp fail to reach the bridge.
time.Sleep(1 * time.Millisecond)
arping.GratuitousArpOverIfaceByName(ipnet.IP, ifName)
}
if withMulticastRoute {
/* Route multicast packets across the weave network.
This must come last in 'attach'. If you change this, change weavewait to match.
TODO: Add the MTU lock to prevent PMTU discovery for multicast
destinations. Without that, the kernel sets the DF flag on
multicast packets. Since RFC1122 prohibits sending of ICMP
errors for packets with multicast destinations, that causes
packets larger than the PMTU to be dropped silently. */
_, multicast, _ := net.ParseCIDR("224.0.0.0/4")
if err := AddRoute(veth, netlink.SCOPE_LINK, multicast, nil); err != nil {
return err
}
}
return nil
}); err != nil {
// SetupIfaceAddrs is the implementation of the 'setup-iface-addrs' call above,
// running in another process in the container's netns
func SetupIfaceAddrs(veth netlink.Link, withMulticastRoute bool, cidrs []*net.IPNet) error {
newAddresses, err := AddAddresses(veth, cidrs)
if err != nil {
return err
}
ifName := veth.Attrs().Name
ipt, err := iptables.New()
if err != nil {
return err
}
// Add multicast ACCEPT rules for new subnets
for _, ipnet := range newAddresses {
acceptRule := []string{"-i", ifName, "-s", subnet(ipnet), "-d", "224.0.0.0/4", "-j", "ACCEPT"}
exists, err := ipt.Exists("filter", "INPUT", acceptRule...)
if err != nil {
return err
}
if !exists {
if err := ipt.Insert("filter", "INPUT", 1, acceptRule...); err != nil {
return err
}
}
}
if err := netlink.LinkSetUp(veth); err != nil {
return err
}
for _, ipnet := range newAddresses {
// If we don't wait for a bit here, we see the arp fail to reach the bridge.
time.Sleep(1 * time.Millisecond)
arping.GratuitousArpOverIfaceByName(ipnet.IP, ifName)
}
if withMulticastRoute {
/* Route multicast packets across the weave network.
This must come last in 'attach'. If you change this, change weavewait to match.
TODO: Add the MTU lock to prevent PMTU discovery for multicast
destinations. Without that, the kernel sets the DF flag on
multicast packets. Since RFC1122 prohibits sending of ICMP
errors for packets with multicast destinations, that causes
packets larger than the PMTU to be dropped silently. */
_, multicast, _ := net.ParseCIDR("224.0.0.0/4")
if err := AddRoute(veth, netlink.SCOPE_LINK, multicast, nil); err != nil {
return err
}
}
return nil
}
// SetupIface is the implementation of the 'setup-iface' call above,
// running in another process in the container's netns
func SetupIface(ifaceName, newIfName string) error {
ipt, err := iptables.New()
if err != nil {
return err
}
link, err := netlink.LinkByName(ifaceName)
if err != nil {
return err
}
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 {
return err
}
return ipt.Append("filter", "INPUT", "-i", newIfName, "-d", "224.0.0.0/4", "-j", "DROP")
}
// NB: This function can be used only by a process that terminates immediately
// after calling the function as it changes netns via WithNetNSLinkUnsafe.
func DetachContainer(netNSPath, id, ifName string, cidrs []*net.IPNet) error {
@@ -276,39 +296,3 @@ func subnets(addrs []netlink.Addr) map[string]struct{} {
}
return subnets
}
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
}
}
}
return err
}
return nil
}
}
func ExposeNAT(ipnet net.IPNet) error {
ipt, err := iptables.New()
if err != nil {
return err
}
cidr := ipnet.String()
if err := addNatRule(ipt, "-s", cidr, "-d", "224.0.0.0/4", "-j", "RETURN"); err != nil {
return err
}
if err := addNatRule(ipt, "-d", cidr, "!", "-s", cidr, "-j", "MASQUERADE"); err != nil {
return err
}
if err := addNatRule(ipt, "-s", cidr, "!", "-d", cidr, "-j", "MASQUERADE"); err != nil {
return err
}
return nil
}
+121 -28
View File
@@ -3,14 +3,19 @@ package npc
import (
"fmt"
"k8s.io/client-go/pkg/api"
extnapi "k8s.io/client-go/pkg/apis/extensions/v1beta1"
"k8s.io/client-go/pkg/util/intstr"
apiv1 "k8s.io/api/core/v1"
extnapi "k8s.io/api/extensions/v1beta1"
networkingv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"github.com/weaveworks/weave/npc/ipset"
)
func (ns *ns) analysePolicy(policy *extnapi.NetworkPolicy) (
// analysePolicyLegacy is used to analyse extensions/v1beta1/NetworkPolicy (legacy) and
// implements pre-1.7 k8s netpol semantics, whilst analysePolicy - networking.k8s.io/v1/NetworkPolicy
// and 1.7 semantics.
func (ns *ns) analysePolicyLegacy(policy *extnapi.NetworkPolicy) (
rules map[string]*ruleSpec,
nsSelectors, podSelectors map[string]*selectorSpec,
err error) {
@@ -19,7 +24,7 @@ func (ns *ns) analysePolicy(policy *extnapi.NetworkPolicy) (
podSelectors = make(map[string]*selectorSpec)
rules = make(map[string]*ruleSpec)
dstSelector, err := newSelectorSpec(&policy.Spec.PodSelector, ns.name, ipset.HashIP)
dstSelector, err := newSelectorSpec(&policy.Spec.PodSelector, true, ns.name, ipset.HashIP)
if err != nil {
return nil, nil, nil, err
}
@@ -45,7 +50,7 @@ func (ns *ns) analysePolicy(policy *extnapi.NetworkPolicy) (
} else {
// Ports is present and contains at least one item, then this rule allows traffic
// only if the traffic matches at least one port in the ports list.
withNormalisedProtoAndPort(ingressRule.Ports, func(proto, port string) {
withNormalisedProtoAndPortLegacy(ingressRule.Ports, func(proto, port string) {
rule := newRuleSpec(&proto, nil, dstSelector, &port)
rules[rule.key] = rule
})
@@ -56,14 +61,14 @@ func (ns *ns) analysePolicy(policy *extnapi.NetworkPolicy) (
for _, peer := range ingressRule.From {
var srcSelector *selectorSpec
if peer.PodSelector != nil {
srcSelector, err = newSelectorSpec(peer.PodSelector, ns.name, ipset.HashIP)
srcSelector, err = newSelectorSpec(peer.PodSelector, false, ns.name, ipset.HashIP)
if err != nil {
return nil, nil, nil, err
}
podSelectors[srcSelector.key] = srcSelector
}
if peer.NamespaceSelector != nil {
srcSelector, err = newSelectorSpec(peer.NamespaceSelector, "", ipset.ListSet)
srcSelector, err = newSelectorSpec(peer.NamespaceSelector, false, "", ipset.ListSet)
if err != nil {
return nil, nil, nil, err
}
@@ -77,6 +82,80 @@ func (ns *ns) analysePolicy(policy *extnapi.NetworkPolicy) (
} else {
// Ports is present and contains at least one item, then this rule allows traffic
// only if the traffic matches at least one port in the ports list.
withNormalisedProtoAndPortLegacy(ingressRule.Ports, func(proto, port string) {
rule := newRuleSpec(&proto, srcSelector, dstSelector, &port)
rules[rule.key] = rule
})
}
}
}
}
return rules, nsSelectors, podSelectors, nil
}
func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
rules map[string]*ruleSpec,
nsSelectors, podSelectors map[string]*selectorSpec,
err error) {
nsSelectors = make(map[string]*selectorSpec)
podSelectors = make(map[string]*selectorSpec)
rules = make(map[string]*ruleSpec)
// If empty, matches all pods in a namespace
dstSelector, err := newSelectorSpec(&policy.Spec.PodSelector, true, ns.name, ipset.HashIP)
if err != nil {
return nil, nil, nil, err
}
podSelectors[dstSelector.key] = dstSelector
// If ingress is empty then this NetworkPolicy does not allow any traffic
if policy.Spec.Ingress == nil || len(policy.Spec.Ingress) == 0 {
return
}
for _, ingressRule := range policy.Spec.Ingress {
// If Ports is empty or missing, this rule matches all ports
allPorts := ingressRule.Ports == nil || len(ingressRule.Ports) == 0
// If From is empty or missing, this rule matches all sources
allSources := ingressRule.From == nil || len(ingressRule.From) == 0
if allSources {
if allPorts {
rule := newRuleSpec(nil, nil, dstSelector, nil)
rules[rule.key] = rule
} else {
withNormalisedProtoAndPort(ingressRule.Ports, func(proto, port string) {
rule := newRuleSpec(&proto, nil, dstSelector, &port)
rules[rule.key] = rule
})
}
} else {
for _, peer := range ingressRule.From {
var srcSelector *selectorSpec
// NetworkPolicyPeer describes a peer to allow traffic from.
// Exactly one of its fields must be specified.
if peer.PodSelector != nil {
srcSelector, err = newSelectorSpec(peer.PodSelector, false, ns.name, ipset.HashIP)
if err != nil {
return nil, nil, nil, err
}
podSelectors[srcSelector.key] = srcSelector
} else if peer.NamespaceSelector != nil {
srcSelector, err = newSelectorSpec(peer.NamespaceSelector, false, "", ipset.ListSet)
if err != nil {
return nil, nil, nil, err
}
nsSelectors[srcSelector.key] = srcSelector
}
if allPorts {
rule := newRuleSpec(nil, srcSelector, dstSelector, nil)
rules[rule.key] = rule
} else {
withNormalisedProtoAndPort(ingressRule.Ports, func(proto, port string) {
rule := newRuleSpec(&proto, srcSelector, dstSelector, &port)
rules[rule.key] = rule
@@ -89,26 +168,40 @@ func (ns *ns) analysePolicy(policy *extnapi.NetworkPolicy) (
return rules, nsSelectors, podSelectors, nil
}
func withNormalisedProtoAndPort(npps []extnapi.NetworkPolicyPort, f func(proto, port string)) {
func withNormalisedProtoAndPortLegacy(npps []extnapi.NetworkPolicyPort, f func(proto, port string)) {
for _, npp := range npps {
// If no proto is specified, default to TCP
proto := string(api.ProtocolTCP)
if npp.Protocol != nil {
proto = string(*npp.Protocol)
}
// If no port is specified, match any port. Let iptables executable handle
// service name resolution
port := "0:65535"
if npp.Port != nil {
switch npp.Port.Type {
case intstr.Int:
port = fmt.Sprintf("%d", npp.Port.IntVal)
case intstr.String:
port = npp.Port.StrVal
}
}
f(proto, port)
f(proto(npp.Protocol), port(npp.Port))
}
}
func withNormalisedProtoAndPort(npps []networkingv1.NetworkPolicyPort, f func(proto, port string)) {
for _, npp := range npps {
f(proto(npp.Protocol), port(npp.Port))
}
}
func proto(p *apiv1.Protocol) string {
// If no proto is specified, default to TCP
proto := string(apiv1.ProtocolTCP)
if p != nil {
proto = string(*p)
}
return proto
}
func port(p *intstr.IntOrString) string {
// If no port is specified, match any port. Let iptables executable handle
// service name resolution
port := "0:65535"
if p != nil {
switch p.Type {
case intstr.Int:
port = fmt.Sprintf("%d", p.IntVal)
case intstr.String:
port = p.StrVal
}
}
return port
}
+48 -35
View File
@@ -3,13 +3,14 @@ package npc
import (
"sync"
"github.com/coreos/go-iptables/iptables"
"github.com/pkg/errors"
coreapi "k8s.io/client-go/pkg/api/v1"
extnapi "k8s.io/client-go/pkg/apis/extensions/v1beta1"
coreapi "k8s.io/api/core/v1"
extnapi "k8s.io/api/extensions/v1beta1"
networkingv1 "k8s.io/api/networking/v1"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/npc/ipset"
"github.com/weaveworks/weave/npc/iptables"
)
type NetworkPolicyController interface {
@@ -21,9 +22,9 @@ type NetworkPolicyController interface {
UpdatePod(oldObj, newObj *coreapi.Pod) error
DeletePod(obj *coreapi.Pod) error
AddNetworkPolicy(obj *extnapi.NetworkPolicy) error
UpdateNetworkPolicy(oldObj, newObj *extnapi.NetworkPolicy) error
DeleteNetworkPolicy(obj *extnapi.NetworkPolicy) error
AddNetworkPolicy(obj interface{}) error
UpdateNetworkPolicy(oldObj, newObj interface{}) error
DeleteNetworkPolicy(obj interface{}) error
}
type controller struct {
@@ -31,21 +32,25 @@ type controller struct {
nodeName string // my node name
ipt *iptables.IPTables
ipt iptables.Interface
ips ipset.Interface
nss map[string]*ns // ns name -> ns struct
nsSelectors *selectorSet // selector string -> nsSelector
legacy bool // use legacy network policy semantics (k8s pre-1.7)
}
func New(nodeName string, ipt *iptables.IPTables, ips ipset.Interface) NetworkPolicyController {
func New(nodeName string, legacy bool, ipt iptables.Interface, ips ipset.Interface) NetworkPolicyController {
c := &controller{
nodeName: nodeName,
legacy: legacy,
ipt: ipt,
ips: ips,
nss: make(map[string]*ns)}
c.nsSelectors = newSelectorSet(ips, c.onNewNsSelector)
doNothing := func(*selector) error { return nil }
c.nsSelectors = newSelectorSet(ips, c.onNewNsSelector, doNothing, doNothing)
return c
}
@@ -54,7 +59,7 @@ func (npc *controller) onNewNsSelector(selector *selector) error {
for _, ns := range npc.nss {
if ns.namespace != nil {
if selector.matches(ns.namespace.ObjectMeta.Labels) {
if err := ns.ips.AddEntry(selector.spec.ipsetName, string(ns.allPods.ipsetName)); err != nil {
if err := selector.addEntry(ns.namespace.ObjectMeta.UID, string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil {
return err
}
}
@@ -66,7 +71,7 @@ func (npc *controller) onNewNsSelector(selector *selector) error {
func (npc *controller) withNS(name string, f func(ns *ns) error) error {
ns, found := npc.nss[name]
if !found {
newNs, err := newNS(name, npc.ipt, npc.ips, npc.nsSelectors)
newNs, err := newNS(name, npc.nodeName, npc.legacy, npc.ipt, npc.ips, npc.nsSelectors)
if err != nil {
return err
}
@@ -85,21 +90,10 @@ func (npc *controller) withNS(name string, f func(ns *ns) error) error {
return nil
}
func (npc *controller) checkLocalPod(obj *coreapi.Pod, event string) bool {
if obj.Spec.NodeName != npc.nodeName {
common.Log.Debugf("%s ignored for pod %s/%s on node %s", event, obj.ObjectMeta.Namespace, obj.ObjectMeta.Name, obj.Spec.NodeName)
return false
}
return true
}
func (npc *controller) AddPod(obj *coreapi.Pod) error {
npc.Lock()
defer npc.Unlock()
if !npc.checkLocalPod(obj, "AddPod") {
return nil
}
common.Log.Debugf("EVENT AddPod %s", js(obj))
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
return errors.Wrap(ns.addPod(obj), "add pod")
@@ -110,10 +104,6 @@ func (npc *controller) UpdatePod(oldObj, newObj *coreapi.Pod) error {
npc.Lock()
defer npc.Unlock()
// Pods don't move across nodes so we only check the new version
if !npc.checkLocalPod(newObj, "UpdatePod") {
return nil
}
common.Log.Debugf("EVENT UpdatePod %s %s", js(oldObj), js(newObj))
return npc.withNS(oldObj.ObjectMeta.Namespace, func(ns *ns) error {
return errors.Wrap(ns.updatePod(oldObj, newObj), "update pod")
@@ -124,41 +114,53 @@ func (npc *controller) DeletePod(obj *coreapi.Pod) error {
npc.Lock()
defer npc.Unlock()
if !npc.checkLocalPod(obj, "DeletePod") {
return nil
}
common.Log.Debugf("EVENT DeletePod %s", js(obj))
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
return errors.Wrap(ns.deletePod(obj), "delete pod")
})
}
func (npc *controller) AddNetworkPolicy(obj *extnapi.NetworkPolicy) error {
func (npc *controller) AddNetworkPolicy(obj interface{}) error {
npc.Lock()
defer npc.Unlock()
nsName, err := nsName(obj)
if err != nil {
return err
}
common.Log.Infof("EVENT AddNetworkPolicy %s", js(obj))
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
return npc.withNS(nsName, func(ns *ns) error {
return errors.Wrap(ns.addNetworkPolicy(obj), "add network policy")
})
}
func (npc *controller) UpdateNetworkPolicy(oldObj, newObj *extnapi.NetworkPolicy) error {
func (npc *controller) UpdateNetworkPolicy(oldObj, newObj interface{}) error {
npc.Lock()
defer npc.Unlock()
nsName, err := nsName(oldObj)
if err != nil {
return err
}
common.Log.Infof("EVENT UpdateNetworkPolicy %s %s", js(oldObj), js(newObj))
return npc.withNS(oldObj.ObjectMeta.Namespace, func(ns *ns) error {
return npc.withNS(nsName, func(ns *ns) error {
return errors.Wrap(ns.updateNetworkPolicy(oldObj, newObj), "update network policy")
})
}
func (npc *controller) DeleteNetworkPolicy(obj *extnapi.NetworkPolicy) error {
func (npc *controller) DeleteNetworkPolicy(obj interface{}) error {
npc.Lock()
defer npc.Unlock()
nsName, err := nsName(obj)
if err != nil {
return err
}
common.Log.Infof("EVENT DeleteNetworkPolicy %s", js(obj))
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
return npc.withNS(nsName, func(ns *ns) error {
return errors.Wrap(ns.deleteNetworkPolicy(obj), "delete network policy")
})
}
@@ -192,3 +194,14 @@ func (npc *controller) DeleteNamespace(obj *coreapi.Namespace) error {
return errors.Wrap(ns.deleteNamespace(obj), "delete namespace")
})
}
func nsName(obj interface{}) (string, error) {
switch obj := obj.(type) {
case *networkingv1.NetworkPolicy:
return obj.ObjectMeta.Namespace, nil
case *extnapi.NetworkPolicy:
return obj.ObjectMeta.Namespace, nil
}
return "", errInvalidNetworkPolicyObjType
}
+378
View File
@@ -0,0 +1,378 @@
package npc
import (
"log"
"testing"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
"github.com/weaveworks/weave/npc/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"
)
type mockSet struct {
name ipset.Name
setType ipset.Type
subSets map[string]map[types.UID]bool
}
type mockIPSet struct {
sets map[string]mockSet
}
func newMockIPSet() mockIPSet {
return mockIPSet{sets: make(map[string]mockSet)}
}
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)}
return nil
}
func (i *mockIPSet) AddEntry(user types.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)
}
if _, ok := i.sets[string(ipsetName)].subSets[entry][user]; ok {
return errors.Errorf("user %s already owns entry %s", user, entry)
}
i.sets[string(ipsetName)].subSets[entry][user] = true
return nil
}
func (i *mockIPSet) DelEntry(user types.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)
}
if _, ok := i.sets[string(ipsetName)].subSets[entry][user]; !ok {
return errors.Errorf("user %s does not own entry %s", user, entry)
}
delete(i.sets[string(ipsetName)].subSets[entry], user)
if len(i.sets[string(ipsetName)].subSets[entry]) == 0 {
delete(i.sets[string(ipsetName)].subSets, entry)
}
return nil
}
func (i *mockIPSet) Exist(user types.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 {
return len(i.sets[string(ipsetName)].subSets[entry]) > 0
}
func (i *mockIPSet) Flush(ipsetName ipset.Name) error {
return errors.New("Not Implemented")
}
func (i *mockIPSet) FlushAll() error {
return errors.New("Not Implemented")
}
func (i *mockIPSet) Destroy(ipsetName ipset.Name) error {
if _, ok := i.sets[string(ipsetName)]; !ok {
return errors.Errorf("ipset %s does not exist", ipsetName)
}
delete(i.sets, string(ipsetName))
return nil
}
func (i *mockIPSet) DestroyAll() error {
return errors.New("Not Implemented")
}
func (i *mockIPSet) List(prefix string) ([]ipset.Name, error) {
return []ipset.Name{}, errors.New("Not Implemented")
}
type mockIPTables struct {
}
func (ipt *mockIPTables) Append(table, chain string, rulespec ...string) error {
return nil
}
func (ipt *mockIPTables) Delete(table, chain string, rulespec ...string) error {
return nil
}
func (ipt *mockIPTables) Insert(table, chain string, pos int, rulespec ...string) error {
return nil
}
func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
// Test for race condition between namespace and networkpolicy events
// https://github.com/weaveworks/weave/issues/3059
sourceNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "source",
Labels: map[string]string{
"app": "source",
},
},
}
destinationNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "destination",
},
}
port := intstr.FromInt(12345)
networkPolicy := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "network-policy",
Namespace: "destination",
},
Spec: networkingv1.NetworkPolicySpec{
Ingress: []networkingv1.NetworkPolicyIngressRule{
{
From: []networkingv1.NetworkPolicyPeer{
{
NamespaceSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "source",
},
},
},
},
Ports: []networkingv1.NetworkPolicyPort{
{
Port: &port,
},
},
},
},
},
}
// Namespaces first
m := newMockIPSet()
controller := New("foo", false, &mockIPTables{}, &m)
const (
selectorIPSetName = "weave-I239Zp%sCvoVt*D6u=A!2]YEk"
sourceIPSetName = "weave-HboJG1fGgG]/SR%k9H#hv5e96"
)
controller.AddNamespace(sourceNamespace)
controller.AddNamespace(destinationNamespace)
controller.AddNetworkPolicy(networkPolicy)
require.Equal(t, true, len(m.sets[selectorIPSetName].subSets[sourceIPSetName]) > 0)
// NetworkPolicy first
m = newMockIPSet()
controller = New("foo", false, &mockIPTables{}, &m)
controller.AddNetworkPolicy(networkPolicy)
controller.AddNamespace(sourceNamespace)
controller.AddNamespace(destinationNamespace)
require.Equal(t, true, len(m.sets[selectorIPSetName].subSets[sourceIPSetName]) > 0)
}
// Tests default-allow ipset behavior when running in non-legacy mode.
func TestDefaultAllow(t *testing.T) {
const (
defaultAllowIPSetName = "weave-E.1.0W^NGSp]0_t5WwH/]gX@L"
fooPodIP = "10.32.0.10"
barPodIP = "10.32.0.11"
barPodNewIP = "10.32.0.12"
)
m := newMockIPSet()
controller := New("bar", false, &mockIPTables{}, &m)
defaultNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
},
}
controller.AddNamespace(defaultNamespace)
// Should create an ipset for default-allow
require.Contains(t, m.sets, defaultAllowIPSetName)
podFoo := &coreapi.Pod{
ObjectMeta: metav1.ObjectMeta{
UID: "foo",
Namespace: "default",
Name: "foo",
Labels: map[string]string{"run": "foo"}},
Status: coreapi.PodStatus{PodIP: fooPodIP}}
controller.AddPod(podFoo)
// Should add the foo pod to default-allow
require.True(t, m.entryExists(defaultAllowIPSetName, fooPodIP))
podBar := &coreapi.Pod{
ObjectMeta: metav1.ObjectMeta{
UID: "bar",
Namespace: "default",
Name: "bar",
Labels: map[string]string{"run": "bar"}},
Status: coreapi.PodStatus{PodIP: barPodIP}}
podBarNoIP := &coreapi.Pod{ObjectMeta: podBar.ObjectMeta}
controller.AddPod(podBarNoIP)
controller.UpdatePod(podBarNoIP, podBar)
// Should add the bar pod to default-allow
require.True(t, m.entryExists(defaultAllowIPSetName, barPodIP))
// Allow access from the bar pod to the foo pod
netpol := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "allow-from-bar-to-foo",
Namespace: "default",
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{MatchLabels: map[string]string{"run": "foo"}},
Ingress: []networkingv1.NetworkPolicyIngressRule{{
From: []networkingv1.NetworkPolicyPeer{{
PodSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{"run": "bar"},
},
}},
}},
},
}
controller.AddNetworkPolicy(netpol)
// Should remove the foo pod from default-allow as the netpol selects it
require.False(t, m.entryExists(defaultAllowIPSetName, fooPodIP))
require.True(t, m.entryExists(defaultAllowIPSetName, barPodIP))
podBarWithNewIP := *podBar
podBarWithNewIP.Status.PodIP = barPodNewIP
controller.UpdatePod(podBar, &podBarWithNewIP)
// Should update IP addr of the bar pod in default-allow
require.False(t, m.entryExists(defaultAllowIPSetName, barPodIP))
require.True(t, m.entryExists(defaultAllowIPSetName, barPodNewIP))
controller.UpdatePod(&podBarWithNewIP, podBarNoIP)
// Should remove the bar pod from default-allow as it does not have any IP addr
require.False(t, m.entryExists(defaultAllowIPSetName, barPodNewIP))
podFooWithNewLabel := *podFoo
podFooWithNewLabel.ObjectMeta.Labels = map[string]string{"run": "new-foo"}
controller.UpdatePod(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(defaultAllowIPSetName, fooPodIP))
controller.UpdatePod(&podFooWithNewLabel, podFoo)
// Should remove from default-allow as it matches the netpol after the update
require.False(t, m.entryExists(defaultAllowIPSetName, fooPodIP))
controller.DeleteNetworkPolicy(netpol)
// Should bring back the foo pod to default-allow as no netpol selects it
require.True(t, m.entryExists(defaultAllowIPSetName, fooPodIP))
controller.DeletePod(podFoo)
// Should remove foo pod from default-allow
require.False(t, m.entryExists(defaultAllowIPSetName, fooPodIP))
}
func TestOutOfOrderPodEvents(t *testing.T) {
const (
defaultAllowIPSetName = "weave-E.1.0W^NGSp]0_t5WwH/]gX@L"
runBarIPSetName = "weave-bZ~x=yBgzH)Ht()K*Uv3z{M]Y"
podIP = "10.32.0.10"
)
m := newMockIPSet()
controller := New("qux", false, &mockIPTables{}, &m)
defaultNamespace := &coreapi.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
},
}
controller.AddNamespace(defaultNamespace)
podFoo := &coreapi.Pod{
ObjectMeta: metav1.ObjectMeta{
UID: "foo",
Namespace: "default",
Name: "foo",
Labels: map[string]string{"run": "foo"}},
Status: coreapi.PodStatus{PodIP: podIP}}
controller.AddPod(podFoo)
// Should be in default-allow as no netpol selects podFoo
require.True(t, m.entryExists(defaultAllowIPSetName, podIP))
netpol := &networkingv1.NetworkPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "allow-from-bar-to-foo",
Namespace: "default",
},
Spec: networkingv1.NetworkPolicySpec{
PodSelector: metav1.LabelSelector{MatchLabels: map[string]string{"run": "foo"}},
Ingress: []networkingv1.NetworkPolicyIngressRule{{
From: []networkingv1.NetworkPolicyPeer{{
PodSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{"run": "bar"},
},
}},
}},
},
}
controller.AddNetworkPolicy(netpol)
// Shouldn't be in default-allow as netpol above selects podFoo
require.False(t, m.entryExists(defaultAllowIPSetName, podIP))
podBar := &coreapi.Pod{
ObjectMeta: metav1.ObjectMeta{
UID: "bar",
Namespace: "default",
Name: "bar",
Labels: map[string]string{"run": "bar"}},
Status: coreapi.PodStatus{PodIP: podIP}}
controller.AddPod(podBar)
// Should be in default-allow as no netpol selects podBar
require.True(t, m.entryExists(defaultAllowIPSetName, podIP))
require.True(t, m.Exist(podBar.ObjectMeta.UID, defaultAllowIPSetName, podIP))
// Should be in run=bar ipset
require.True(t, m.entryExists(runBarIPSetName, podIP))
controller.DeletePod(podFoo)
// Multiple duplicate events should not affect npc state
controller.DeletePod(podFoo)
controller.DeletePod(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(defaultAllowIPSetName, podIP))
controller.DeletePod(podBar)
// Should remove from default-allow and run=bar ipsets
require.Equal(t, 0, len(m.sets[defaultAllowIPSetName].subSets))
require.False(t, m.entryExists(runBarIPSetName, podIP))
}
+109 -51
View File
@@ -6,6 +6,7 @@ import (
"strings"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/types"
)
type Name string
@@ -19,8 +20,9 @@ const (
type Interface interface {
Create(ipsetName Name, ipsetType Type) error
AddEntry(ipsetName Name, entry string) error
DelEntry(ipsetName Name, entry string) 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
Flush(ipsetName Name) error
Destroy(ipsetName Name) error
@@ -30,52 +32,100 @@ type Interface interface {
DestroyAll() error
}
type entryKey struct {
ipsetName Name
entry string
}
type ipset struct {
refCount
*log.Logger
enableComments bool
// List of users per ipset entry. User is either a namespace or a pod.
// There might be multiple users for the same ipset & entry pair because
// 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{}
}
func New(logger *log.Logger) Interface {
return &ipset{refCount: newRefCount(), Logger: logger}
ips := &ipset{
Logger: logger,
enableComments: true,
users: make(map[entryKey]map[types.UID]struct{}),
}
// Check for comment support
testIpsetName := Name("weave-test-comment")
// Clear it out if it already exists
_ = ips.Destroy(testIpsetName)
// Test for comment support
if err := ips.Create(testIpsetName, HashIP); err != nil {
ips.Logger.Printf("failed to create %s; disabling comment support", testIpsetName)
ips.enableComments = false
}
// If it was created, destroy it
_ = ips.Destroy(testIpsetName)
return ips
}
func (i *ipset) Create(ipsetName Name, ipsetType Type) error {
return doExec("create", string(ipsetName), string(ipsetType))
args := []string{"create", string(ipsetName), string(ipsetType)}
if i.enableComments {
args = append(args, "comment")
}
return doExec(args...)
}
func (i *ipset) AddEntry(ipsetName Name, entry string) error {
i.Logger.Printf("adding entry %s to %s", entry, ipsetName)
if i.inc(ipsetName, entry) > 1 { // already in the set
func (i *ipset) AddEntry(user types.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
return nil
}
return doExec("add", string(ipsetName), entry)
i.Logger.Printf("added entry %s to %s of %s", entry, ipsetName, user)
args := []string{"add", string(ipsetName), entry}
if i.enableComments {
args = append(args, "comment", comment)
}
return doExec(args...)
}
func (i *ipset) DelEntry(ipsetName Name, entry string) error {
i.Logger.Printf("deleting entry %s from %s", entry, ipsetName)
if i.dec(ipsetName, entry) > 0 { // still needed
func (i *ipset) DelEntry(user types.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
return nil
}
i.Logger.Printf("deleted entry %s from %s of %s", entry, ipsetName, user)
return doExec("del", string(ipsetName), entry)
}
func (i *ipset) Exist(user types.UID, ipsetName Name, entry string) bool {
return i.existUser(user, ipsetName, entry)
}
func (i *ipset) Flush(ipsetName Name) error {
i.removeSet(ipsetName)
i.removeSetFromUsers(ipsetName)
return doExec("flush", string(ipsetName))
}
func (i *ipset) FlushAll() error {
i.refCount = newRefCount()
i.users = make(map[entryKey]map[types.UID]struct{})
return doExec("flush")
}
func (i *ipset) Destroy(ipsetName Name) error {
i.removeSet(ipsetName)
i.removeSetFromUsers(ipsetName)
return doExec("destroy", string(ipsetName))
}
func (i *ipset) DestroyAll() error {
i.refCount = newRefCount()
i.users = make(map[entryKey]map[types.UID]struct{})
return doExec("destroy")
}
@@ -97,44 +147,52 @@ func (i *ipset) List(prefix string) ([]Name, error) {
return selected, err
}
// 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 {
k := entryKey{ipsetName, entry}
add := false
if i.users[k] == nil {
i.users[k] = make(map[types.UID]struct{})
}
if len(i.users[k]) == 0 {
add = true
}
i.users[k][user] = struct{}{}
return add
}
// 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 {
k := entryKey{ipsetName, entry}
oneLeft := len(i.users[k]) == 1
delete(i.users[k], user)
if len(i.users[k]) == 0 {
delete(i.users, k)
}
return oneLeft && (len(i.users[k]) == 0)
}
func (i *ipset) existUser(user types.UID, ipsetName Name, entry string) bool {
_, ok := i.users[entryKey{ipsetName, entry}][user]
return ok
}
func (i *ipset) removeSetFromUsers(ipsetName Name) {
for k := range i.users {
if k.ipsetName == ipsetName {
delete(i.users, k)
}
}
}
func doExec(args ...string) error {
if output, err := exec.Command("ipset", args...).CombinedOutput(); err != nil {
return errors.Wrapf(err, "ipset %v failed: %s", args, output)
}
return nil
}
// Reference-counting
type key struct {
ipsetName Name
entry string
}
// note no locking is required as all operations are serialised in the controller
type refCount struct {
ref map[key]int
}
func newRefCount() refCount {
return refCount{ref: make(map[key]int)}
}
func (rc *refCount) inc(ipsetName Name, entry string) int {
k := key{ipsetName, entry}
rc.ref[k]++
return rc.ref[k]
}
func (rc *refCount) dec(ipsetName Name, entry string) int {
k := key{ipsetName, entry}
rc.ref[k]--
return rc.ref[k]
}
func (rc *refCount) removeSet(ipsetName Name) {
for k := range rc.ref {
if k.ipsetName == ipsetName {
delete(rc.ref, k)
}
}
}
+7
View File
@@ -0,0 +1,7 @@
package iptables
type Interface interface {
Append(table, chain string, rulespec ...string) error
Delete(table, chain string, rulespec ...string) error
Insert(table, chain string, pos int, rulespec ...string) error
}
+315 -100
View File
@@ -2,37 +2,50 @@ package npc
import (
"encoding/json"
"errors"
"fmt"
"github.com/coreos/go-iptables/iptables"
"k8s.io/client-go/pkg/api/unversioned"
coreapi "k8s.io/client-go/pkg/api/v1"
extnapi "k8s.io/client-go/pkg/apis/extensions/v1beta1"
"k8s.io/client-go/pkg/types"
"k8s.io/client-go/pkg/util/uuid"
coreapi "k8s.io/api/core/v1"
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/npc/ipset"
"github.com/weaveworks/weave/npc/iptables"
)
var errInvalidNetworkPolicyObjType = errors.New("invalid NetworkPolicy object type")
type ns struct {
ipt *iptables.IPTables // interface to iptables
ipt iptables.Interface // interface to iptables
ips ipset.Interface // interface to ipset
name string // k8s Namespace name
namespace *coreapi.Namespace // k8s Namespace object
pods map[types.UID]*coreapi.Pod // k8s Pod objects by UID
policies map[types.UID]*extnapi.NetworkPolicy // k8s NetworkPolicy objects by UID
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
uid types.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 dst podSelector of
// any netpol; used only in non-legacy mode and is used as a dst in
// the WEAVE-NPC-DEFAULT iptables chain.
defaultAllowIPSet ipset.Name
nsSelectors *selectorSet
podSelectors *selectorSet
rules *ruleSet
legacy bool
}
func newNS(name string, ipt *iptables.IPTables, ips ipset.Interface, nsSelectors *selectorSet) (*ns, error) {
allPods, err := newSelectorSpec(&unversioned.LabelSelector{}, name, ipset.HashIP)
func newNS(name, nodeName string, legacy bool, ipt iptables.Interface, ips ipset.Interface, nsSelectors *selectorSet) (*ns, error) {
allPods, err := newSelectorSpec(&metav1.LabelSelector{}, false, name, ipset.HashIP)
if err != nil {
return nil, err
}
@@ -41,14 +54,24 @@ func newNS(name string, ipt *iptables.IPTables, ips ipset.Interface, nsSelectors
ipt: ipt,
ips: ips,
name: name,
nodeName: nodeName,
pods: make(map[types.UID]*coreapi.Pod),
policies: make(map[types.UID]*extnapi.NetworkPolicy),
policies: make(map[types.UID]interface{}),
uid: uuid.NewUUID(),
allPods: allPods,
nsSelectors: nsSelectors,
rules: newRuleSet(ipt)}
rules: newRuleSet(ipt),
legacy: legacy}
ns.podSelectors = newSelectorSet(ips, ns.onNewPodSelector)
ns.podSelectors = newSelectorSet(ips, ns.onNewPodSelector, ns.onNewDstPodSelector, ns.onDestroyDstPodSelector)
if !legacy {
defaultAllowIPSet := ipset.Name(IpsetNamePrefix + shortName("default-allow:"+name))
if err := ips.Create(defaultAllowIPSet, ipset.HashIP); err != nil {
return nil, err
}
ns.defaultAllowIPSet = defaultAllowIPSet
}
if err := ns.podSelectors.provision(ns.uid, nil, map[string]*selectorSpec{ns.allPods.key: ns.allPods}); err != nil {
return nil, err
@@ -62,25 +85,85 @@ func (ns *ns) empty() bool {
}
func (ns *ns) destroy() error {
if err := ns.podSelectors.deprovision(ns.uid, map[string]*selectorSpec{ns.allPods.key: ns.allPods}, nil); err != nil {
return err
}
return nil
return ns.podSelectors.deprovision(ns.uid, map[string]*selectorSpec{ns.allPods.key: ns.allPods}, nil)
}
func (ns *ns) onNewPodSelector(selector *selector) error {
for _, pod := range ns.pods {
if hasIP(pod) {
if selector.matches(pod.ObjectMeta.Labels) {
if err := selector.addEntry(pod.Status.PodIP); err != nil {
if err := selector.addEntry(pod.ObjectMeta.UID, pod.Status.PodIP, podComment(pod)); err != nil {
return err
}
}
}
}
return nil
}
func (ns *ns) onNewDstPodSelector(selector *selector) error {
if ns.legacy {
return nil
}
for _, pod := range ns.pods {
if hasIP(pod) {
// Remove the pod from default-allow if dst podselector matches the pod
if selector.matches(pod.ObjectMeta.Labels) {
if err := ns.ips.DelEntry(pod.ObjectMeta.UID, ns.defaultAllowIPSet, pod.Status.PodIP); err != nil {
return err
}
}
}
}
return nil
}
func (ns *ns) onDestroyDstPodSelector(selector *selector) error {
if ns.legacy {
return nil
}
for _, pod := range ns.pods {
if hasIP(pod) {
if selector.matches(pod.ObjectMeta.Labels) {
if err := ns.addToDefaultAllowIfNoMatching(pod); err != nil {
return err
}
}
}
}
return nil
}
// Add pod IP addr to default-allow ipset if there are no matching dst selectors
func (ns *ns) addToDefaultAllowIfNoMatching(pod *coreapi.Pod) error {
found := false
// TODO(mp) optimize (avoid iterating over selectors) by ref counting IP addrs.
for _, s := range ns.podSelectors.entries {
if ns.podSelectors.dstSelectorExist(s) && s.matches(pod.ObjectMeta.Labels) {
found = true
break
}
}
if !found {
if err := ns.ips.AddEntry(pod.ObjectMeta.UID, ns.defaultAllowIPSet, 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
@@ -88,8 +171,22 @@ func (ns *ns) addPod(obj *coreapi.Pod) error {
return nil
}
ns.ips.AddEntry(LocalIpset, obj.Status.PodIP)
return ns.podSelectors.addToMatching(obj.ObjectMeta.Labels, obj.Status.PodIP)
if ns.checkLocalPod(obj) {
ns.ips.AddEntry(obj.ObjectMeta.UID, LocalIpset, obj.Status.PodIP, podComment(obj))
}
found, err := ns.podSelectors.addToMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
if err != nil {
return err
}
// If there are no matching dst selectors, add the pod to default-allow
if !ns.legacy && !found {
if err := ns.ips.AddEntry(obj.ObjectMeta.UID, ns.defaultAllowIPSet, obj.Status.PodIP, podComment(obj)); err != nil {
return err
}
}
return nil
}
func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
@@ -101,13 +198,50 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
}
if hasIP(oldObj) && !hasIP(newObj) {
ns.ips.DelEntry(LocalIpset, oldObj.Status.PodIP)
return ns.podSelectors.delFromMatching(oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
if ns.checkLocalPod(oldObj) {
ns.ips.DelEntry(oldObj.ObjectMeta.UID, LocalIpset, oldObj.Status.PodIP)
}
if !ns.legacy {
if err := ns.ips.DelEntry(oldObj.ObjectMeta.UID, ns.defaultAllowIPSet, oldObj.Status.PodIP); err != nil {
return err
}
}
return ns.podSelectors.delFromMatching(oldObj.ObjectMeta.UID, oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
}
if !hasIP(oldObj) && hasIP(newObj) {
ns.ips.AddEntry(LocalIpset, newObj.Status.PodIP)
return ns.podSelectors.addToMatching(newObj.ObjectMeta.Labels, newObj.Status.PodIP)
if ns.checkLocalPod(newObj) {
ns.ips.AddEntry(newObj.ObjectMeta.UID, LocalIpset, newObj.Status.PodIP, podComment(newObj))
}
found, err := ns.podSelectors.addToMatching(newObj.ObjectMeta.UID, newObj.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
if err != nil {
return err
}
if !ns.legacy && !found {
if err := ns.ips.AddEntry(newObj.ObjectMeta.UID, ns.defaultAllowIPSet, newObj.Status.PodIP, podComment(newObj)); err != nil {
return err
}
}
return nil
}
if !ns.legacy &&
oldObj.Status.PodIP != newObj.Status.PodIP &&
ns.ips.Exist(oldObj.ObjectMeta.UID, ns.defaultAllowIPSet, oldObj.Status.PodIP) {
// 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 err := ns.ips.DelEntry(oldObj.ObjectMeta.UID, ns.defaultAllowIPSet, oldObj.Status.PodIP); err != nil {
return err
}
if err := ns.ips.AddEntry(newObj.ObjectMeta.UID, ns.defaultAllowIPSet, newObj.Status.PodIP, podComment(newObj)); err != nil {
return err
}
}
if !equals(oldObj.ObjectMeta.Labels, newObj.ObjectMeta.Labels) ||
@@ -120,15 +254,28 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
continue
}
if oldMatch {
if err := ps.delEntry(oldObj.Status.PodIP); err != nil {
if err := ps.delEntry(oldObj.ObjectMeta.UID, oldObj.Status.PodIP); err != nil {
return err
}
}
if newMatch {
if err := ps.addEntry(newObj.Status.PodIP); err != nil {
if err := ps.addEntry(newObj.ObjectMeta.UID, newObj.Status.PodIP, podComment(newObj)); err != nil {
return err
}
}
if !ns.legacy && ns.podSelectors.dstSelectorExist(ps) {
switch {
case !oldMatch && newMatch:
if err := ns.ips.DelEntry(oldObj.ObjectMeta.UID, ns.defaultAllowIPSet, oldObj.Status.PodIP); err != nil {
return err
}
case oldMatch && !newMatch:
if err := ns.addToDefaultAllowIfNoMatching(newObj); err != nil {
return err
}
}
}
}
}
@@ -142,130 +289,150 @@ func (ns *ns) deletePod(obj *coreapi.Pod) error {
return nil
}
ns.ips.DelEntry(LocalIpset, obj.Status.PodIP)
return ns.podSelectors.delFromMatching(obj.ObjectMeta.Labels, obj.Status.PodIP)
if ns.checkLocalPod(obj) {
ns.ips.DelEntry(obj.ObjectMeta.UID, LocalIpset, obj.Status.PodIP)
}
if !ns.legacy {
if err := ns.ips.DelEntry(obj.ObjectMeta.UID, ns.defaultAllowIPSet, obj.Status.PodIP); err != nil {
return err
}
}
return ns.podSelectors.delFromMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP)
}
func (ns *ns) addNetworkPolicy(obj *extnapi.NetworkPolicy) error {
ns.policies[obj.ObjectMeta.UID] = obj
func (ns *ns) addNetworkPolicy(obj interface{}) error {
// Analyse policy, determine which rules and ipsets are required
rules, nsSelectors, podSelectors, err := ns.analysePolicy(obj)
uid, rules, nsSelectors, podSelectors, err := ns.analyse(obj)
if err != nil {
return err
}
// Provision required resources in dependency order
if err := ns.nsSelectors.provision(obj.ObjectMeta.UID, nil, nsSelectors); err != nil {
if err := ns.nsSelectors.provision(uid, nil, nsSelectors); err != nil {
return err
}
if err := ns.podSelectors.provision(obj.ObjectMeta.UID, nil, podSelectors); err != nil {
if err := ns.podSelectors.provision(uid, nil, podSelectors); err != nil {
return err
}
if err := ns.rules.provision(obj.ObjectMeta.UID, nil, rules); err != nil {
return err
}
return nil
return ns.rules.provision(uid, nil, rules)
}
func (ns *ns) updateNetworkPolicy(oldObj, newObj *extnapi.NetworkPolicy) error {
delete(ns.policies, oldObj.ObjectMeta.UID)
ns.policies[newObj.ObjectMeta.UID] = newObj
func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
// Analyse the old and the new policy so we can determine differences
oldRules, oldNsSelectors, oldPodSelectors, err := ns.analysePolicy(oldObj)
oldUID, oldRules, oldNsSelectors, oldPodSelectors, err := ns.analyse(oldObj)
if err != nil {
return err
}
newRules, newNsSelectors, newPodSelectors, err := ns.analysePolicy(newObj)
newUID, newRules, newNsSelectors, newPodSelectors, err := ns.analyse(newObj)
if err != nil {
return err
}
delete(ns.policies, oldUID)
ns.policies[newUID] = newObj
// Deprovision unused and provision newly required resources in dependency order
if err := ns.rules.deprovision(oldObj.ObjectMeta.UID, oldRules, newRules); err != nil {
if err := ns.rules.deprovision(oldUID, oldRules, newRules); err != nil {
return err
}
if err := ns.nsSelectors.deprovision(oldObj.ObjectMeta.UID, oldNsSelectors, newNsSelectors); err != nil {
if err := ns.nsSelectors.deprovision(oldUID, oldNsSelectors, newNsSelectors); err != nil {
return err
}
if err := ns.podSelectors.deprovision(oldObj.ObjectMeta.UID, oldPodSelectors, newPodSelectors); err != nil {
if err := ns.podSelectors.deprovision(oldUID, oldPodSelectors, newPodSelectors); err != nil {
return err
}
if err := ns.nsSelectors.provision(oldObj.ObjectMeta.UID, oldNsSelectors, newNsSelectors); err != nil {
if err := ns.nsSelectors.provision(oldUID, oldNsSelectors, newNsSelectors); err != nil {
return err
}
if err := ns.podSelectors.provision(oldObj.ObjectMeta.UID, oldPodSelectors, newPodSelectors); err != nil {
if err := ns.podSelectors.provision(oldUID, oldPodSelectors, newPodSelectors); err != nil {
return err
}
if err := ns.rules.provision(oldObj.ObjectMeta.UID, oldRules, newRules); err != nil {
return err
}
return nil
return ns.rules.provision(oldUID, oldRules, newRules)
}
func (ns *ns) deleteNetworkPolicy(obj *extnapi.NetworkPolicy) error {
delete(ns.policies, obj.ObjectMeta.UID)
func (ns *ns) deleteNetworkPolicy(obj interface{}) error {
// Analyse network policy to free resources
rules, nsSelectors, podSelectors, err := ns.analysePolicy(obj)
uid, rules, nsSelectors, podSelectors, err := ns.analyse(obj)
if err != nil {
return err
}
delete(ns.policies, uid)
// Deprovision unused resources in dependency order
if err := ns.rules.deprovision(obj.ObjectMeta.UID, rules, nil); err != nil {
if err := ns.rules.deprovision(uid, rules, nil); err != nil {
return err
}
if err := ns.nsSelectors.deprovision(obj.ObjectMeta.UID, nsSelectors, nil); err != nil {
if err := ns.nsSelectors.deprovision(uid, nsSelectors, nil); err != nil {
return err
}
if err := ns.podSelectors.deprovision(obj.ObjectMeta.UID, podSelectors, nil); err != nil {
return err
return ns.podSelectors.deprovision(uid, podSelectors, nil)
}
func bypassRule(nsIpsetName ipset.Name, namespace string) []string {
return []string{"-m", "set", "--match-set", string(nsIpsetName), "dst", "-j", "ACCEPT", "-m", "comment", "--comment", "DefaultAllow isolation for namespace: " + namespace}
}
func (ns *ns) ensureBypassRule() error {
var ipset ipset.Name
if ns.legacy {
ipset = ns.allPods.ipsetName
} else {
ipset = ns.defaultAllowIPSet
}
return nil
common.Log.Debugf("ensuring rule for DefaultAllow in namespace: %s, set %s", ns.name, ipset)
return ns.ipt.Append(TableFilter, DefaultChain, bypassRule(ipset, ns.name)...)
}
func bypassRule(nsIpsetName ipset.Name) []string {
return []string{"-m", "set", "--match-set", string(nsIpsetName), "dst", "-j", "ACCEPT"}
}
func (ns *ns) deleteBypassRule() error {
var ipset ipset.Name
if ns.legacy {
ipset = ns.allPods.ipsetName
} else {
ipset = ns.defaultAllowIPSet
}
func (ns *ns) ensureBypassRule(nsIpsetName ipset.Name) error {
return ns.ipt.Append(TableFilter, DefaultChain, bypassRule(ns.allPods.ipsetName)...)
}
func (ns *ns) deleteBypassRule(nsIpsetName ipset.Name) error {
return ns.ipt.Delete(TableFilter, DefaultChain, bypassRule(ns.allPods.ipsetName)...)
common.Log.Debugf("removing default rule in namespace: %s, set %s", ns.name, ipset)
return ns.ipt.Delete(TableFilter, DefaultChain, bypassRule(ipset, ns.name)...)
}
func (ns *ns) addNamespace(obj *coreapi.Namespace) error {
ns.namespace = obj
// Insert a rule to bypass policies if namespace is DefaultAllow
if !isDefaultDeny(obj) {
return ns.ensureBypassRule(ns.allPods.ipsetName)
if !ns.isDefaultDeny(obj) {
if err := ns.ensureBypassRule(); err != nil {
return err
}
}
// Add namespace ipset to matching namespace selectors
return ns.nsSelectors.addToMatching(obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
_, err := ns.nsSelectors.addToMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName), namespaceComment(ns))
return err
}
func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
ns.namespace = newObj
// Update bypass rule if ingress default has changed
oldDefaultDeny := isDefaultDeny(oldObj)
newDefaultDeny := isDefaultDeny(newObj)
oldDefaultDeny := ns.isDefaultDeny(oldObj)
newDefaultDeny := ns.isDefaultDeny(newObj)
if oldDefaultDeny != newDefaultDeny {
common.Log.Infof("namespace DefaultDeny changed from %t to %t", oldDefaultDeny, newDefaultDeny)
if oldDefaultDeny {
return ns.ensureBypassRule(ns.allPods.ipsetName)
if err := ns.ensureBypassRule(); err != nil {
return err
}
}
if newDefaultDeny {
return ns.deleteBypassRule(ns.allPods.ipsetName)
if err := ns.deleteBypassRule(); err != nil {
return err
}
}
}
@@ -278,12 +445,12 @@ func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
continue
}
if oldMatch {
if err := selector.delEntry(string(ns.allPods.ipsetName)); err != nil {
if err := selector.delEntry(ns.namespace.ObjectMeta.UID, string(ns.allPods.ipsetName)); err != nil {
return err
}
}
if newMatch {
if err := selector.addEntry(string(ns.allPods.ipsetName)); err != nil {
if err := selector.addEntry(ns.namespace.ObjectMeta.UID, string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil {
return err
}
}
@@ -297,12 +464,37 @@ func (ns *ns) deleteNamespace(obj *coreapi.Namespace) error {
ns.namespace = nil
// Remove bypass rule
if !isDefaultDeny(obj) {
return ns.deleteBypassRule(ns.allPods.ipsetName)
if !ns.isDefaultDeny(obj) {
if err := ns.deleteBypassRule(); err != nil {
return err
}
}
// Remove namespace ipset from any matching namespace selectors
return ns.nsSelectors.delFromMatching(obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
return ns.nsSelectors.delFromMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
}
func (ns *ns) isDefaultDeny(namespace *coreapi.Namespace) bool {
nnpJSON, found := namespace.ObjectMeta.Annotations["net.beta.kubernetes.io/network-policy"]
if !found {
return false
}
if !ns.legacy {
common.Log.Warn("DefaultDeny annotation is supported only in legacy mode (--use-legacy-netpol)")
return false
}
var nnp NamespaceNetworkPolicy
if err := json.Unmarshal([]byte(nnpJSON), &nnp); err != nil {
common.Log.Warn("Ignoring network policy annotation: unmarshal failed:", err)
// If we can't understand the annotation, behave as if it isn't present
return false
}
return nnp.Ingress != nil &&
nnp.Ingress.Isolation != nil &&
*(nnp.Ingress.Isolation) == DefaultDeny
}
func hasIP(pod *coreapi.Pod) bool {
@@ -323,20 +515,43 @@ func equals(a, b map[string]string) bool {
return true
}
func isDefaultDeny(namespace *coreapi.Namespace) bool {
nnpJSON, found := namespace.ObjectMeta.Annotations["net.beta.kubernetes.io/network-policy"]
if !found {
return false
func namespaceComment(namespace *ns) string {
return "namespace: " + namespace.name
}
func podComment(pod *coreapi.Pod) string {
return fmt.Sprintf("namespace: %s, pod: %s", pod.ObjectMeta.Namespace, pod.ObjectMeta.Name)
}
func (ns *ns) analyse(obj interface{}) (
uid types.UID,
rules map[string]*ruleSpec,
nsSelectors, podSelectors map[string]*selectorSpec,
err error) {
switch p := obj.(type) {
case *extnapi.NetworkPolicy:
uid = p.ObjectMeta.UID
case *networkingv1.NetworkPolicy:
uid = p.ObjectMeta.UID
default:
err = errInvalidNetworkPolicyObjType
return
}
ns.policies[uid] = obj
var nnp NamespaceNetworkPolicy
if err := json.Unmarshal([]byte(nnpJSON), &nnp); err != nil {
common.Log.Warn("Ignoring network policy annotation: unmarshal failed:", err)
// If we can't understand the annotation, behave as if it isn't present
return false
// Analyse policy, determine which rules and ipsets are required
if ns.legacy {
rules, nsSelectors, podSelectors, err = ns.analysePolicyLegacy(obj.(*extnapi.NetworkPolicy))
if err != nil {
return
}
} else {
rules, nsSelectors, podSelectors, err = ns.analysePolicy(obj.(*networkingv1.NetworkPolicy))
if err != nil {
return
}
}
return nnp.Ingress != nil &&
nnp.Ingress.Isolation != nil &&
*(nnp.Ingress.Isolation) == DefaultDeny
return
}
+14 -4
View File
@@ -1,12 +1,13 @@
package npc
import (
"fmt"
"strings"
"github.com/coreos/go-iptables/iptables"
"k8s.io/client-go/pkg/types"
"k8s.io/apimachinery/pkg/types"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/npc/iptables"
)
type ruleSpec struct {
@@ -19,27 +20,36 @@ func newRuleSpec(proto *string, srcHost *selectorSpec, dstHost *selectorSpec, ds
if proto != nil {
args = append(args, "-p", *proto)
}
srcComment := "anywhere"
if srcHost != nil {
args = append(args, "-m", "set", "--match-set", string(srcHost.ipsetName), "src")
if srcHost.nsName != "" {
srcComment = fmt.Sprintf("pods: namespace: %s, selector: %s", srcHost.nsName, srcHost.key)
} else {
srcComment = fmt.Sprintf("namespaces: selector: %s", srcHost.key)
}
}
dstComment := "anywhere"
if dstHost != nil {
args = append(args, "-m", "set", "--match-set", string(dstHost.ipsetName), "dst")
dstComment = fmt.Sprintf("pods: namespace: %s, selector: %s", dstHost.nsName, dstHost.key)
}
if dstPort != nil {
args = append(args, "--dport", *dstPort)
}
args = append(args, "-j", "ACCEPT")
args = append(args, "-m", "comment", "--comment", fmt.Sprintf("%s -> %s", srcComment, dstComment))
key := strings.Join(args, " ")
return &ruleSpec{key, args}
}
type ruleSet struct {
ipt *iptables.IPTables
ipt iptables.Interface
users map[string]map[types.UID]struct{}
}
func newRuleSet(ipt *iptables.IPTables) *ruleSet {
func newRuleSet(ipt iptables.Interface) *ruleSet {
return &ruleSet{ipt, make(map[string]map[types.UID]struct{})}
}
+16
View File
@@ -0,0 +1,16 @@
package npc
import (
"github.com/stretchr/testify/require"
"testing"
)
func TestRegressionHandleNil3095(t *testing.T) {
// Test for handling nil values
// https://github.com/weaveworks/weave/issues/3095
rs := newRuleSpec(nil, nil, nil, nil)
require.NotEqual(t, rs.key, "")
}
+75 -29
View File
@@ -1,9 +1,9 @@
package npc
import (
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/labels"
"k8s.io/client-go/pkg/types"
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/npc/ipset"
@@ -12,13 +12,15 @@ import (
type selectorSpec struct {
key string // string representation (for hash keying/equality comparison)
selector labels.Selector // k8s Selector object (for matching)
dst bool // destination selector
ipsetType ipset.Type // type of ipset to provision
ipsetName ipset.Name // generated ipset name
nsName string // Namespace name
}
func newSelectorSpec(json *unversioned.LabelSelector, nsName string, ipsetType ipset.Type) (*selectorSpec, error) {
selector, err := unversioned.LabelSelectorAsSelector(json)
func newSelectorSpec(json *metav1.LabelSelector, dst bool, nsName string, ipsetType ipset.Type) (*selectorSpec, error) {
selector, err := metav1.LabelSelectorAsSelector(json)
if err != nil {
return nil, err
}
@@ -26,11 +28,13 @@ func newSelectorSpec(json *unversioned.LabelSelector, nsName string, ipsetType i
return &selectorSpec{
key: key,
selector: selector,
dst: dst,
// We prefix the selector string with the namespace name when generating
// the shortname because you can specify the same selector in multiple
// namespaces - we need those to map to distinct ipsets
ipsetName: ipset.Name(IpsetNamePrefix + shortName(nsName+":"+key)),
ipsetType: ipsetType}, nil
ipsetType: ipsetType,
nsName: nsName}, nil
}
type selector struct {
@@ -42,12 +46,12 @@ func (s *selector) matches(labelMap map[string]string) bool {
return s.spec.selector.Matches(labels.Set(labelMap))
}
func (s *selector) addEntry(entry string) error {
return s.ips.AddEntry(s.spec.ipsetName, entry)
func (s *selector) addEntry(user types.UID, entry string, comment string) error {
return s.ips.AddEntry(user, s.spec.ipsetName, entry, comment)
}
func (s *selector) delEntry(entry string) error {
return s.ips.DelEntry(s.spec.ipsetName, entry)
func (s *selector) delEntry(user types.UID, entry string) error {
return s.ips.DelEntry(user, s.spec.ipsetName, entry)
}
type selectorFn func(selector *selector) error
@@ -55,22 +59,51 @@ type selectorFn func(selector *selector) error
type selectorSet struct {
ips ipset.Interface
onNewSelector selectorFn
users map[string]map[types.UID]struct{} // list of users per selector
entries map[string]*selector
// invoked after dst selector has been provisioned for the first time
onNewDstSelector selectorFn
// invoked after the last instance of dst selector has been deprovisioned
onDestroyDstSelector selectorFn
users map[string]map[types.UID]struct{} // list of users per selector
entries map[string]*selector
// We need to keep track of dst selector instances to be able to invoke
// onNewDstSelector and onDestroyDstSelector callbacks at the right time;
// selectorSpec.Key -> count
dstSelectorsCount map[string]int
}
func newSelectorSet(ips ipset.Interface, onNewSelector selectorFn) *selectorSet {
func newSelectorSet(ips ipset.Interface, onNewSelector, onNewDstSelector selectorFn, onDestroyDstSelector selectorFn) *selectorSet {
return &selectorSet{
ips: ips,
onNewSelector: onNewSelector,
users: make(map[string]map[types.UID]struct{}),
entries: make(map[string]*selector)}
ips: ips,
onNewSelector: onNewSelector,
onNewDstSelector: onNewDstSelector,
onDestroyDstSelector: onDestroyDstSelector,
users: make(map[string]map[types.UID]struct{}),
entries: make(map[string]*selector),
dstSelectorsCount: make(map[string]int)}
}
func (ss *selectorSet) addToMatching(labelMap map[string]string, entry string) error {
func (ss *selectorSet) addToMatching(user types.UID, labelMap map[string]string, entry string, comment string) (bool, error) {
found := false
for _, s := range ss.entries {
if s.matches(labelMap) {
if err := s.addEntry(entry); err != nil {
if ss.dstSelectorExist(s) {
found = true
}
if err := s.addEntry(user, entry, comment); err != nil {
return found, err
}
}
}
return found, nil
}
func (ss *selectorSet) delFromMatching(user types.UID, labelMap map[string]string, entry string) error {
for _, s := range ss.entries {
if s.matches(labelMap) {
if err := s.delEntry(user, entry); err != nil {
return err
}
}
@@ -78,15 +111,8 @@ func (ss *selectorSet) addToMatching(labelMap map[string]string, entry string) e
return nil
}
func (ss *selectorSet) delFromMatching(labelMap map[string]string, entry string) error {
for _, s := range ss.entries {
if s.matches(labelMap) {
if err := s.delEntry(entry); err != nil {
return err
}
}
}
return nil
func (ss *selectorSet) dstSelectorExist(s *selector) bool {
return ss.dstSelectorsCount[s.spec.key] > 0
}
func (ss *selectorSet) deprovision(user types.UID, current, desired map[string]*selectorSpec) error {
@@ -98,9 +124,19 @@ func (ss *selectorSet) deprovision(user types.UID, current, desired map[string]*
if err := ss.ips.Destroy(spec.ipsetName); err != nil {
return err
}
delete(ss.entries, key)
delete(ss.users, key)
}
if spec.dst {
ss.dstSelectorsCount[key]--
if ss.dstSelectorsCount[key] == 0 {
if err := ss.onDestroyDstSelector(&selector{ss.ips, spec}); err != nil {
return err
}
}
}
}
}
return nil
@@ -109,12 +145,13 @@ func (ss *selectorSet) deprovision(user types.UID, current, desired map[string]*
func (ss *selectorSet) provision(user types.UID, current, desired map[string]*selectorSpec) error {
for key, spec := range desired {
if _, found := current[key]; !found {
selector := &selector{ss.ips, spec}
if _, found := ss.users[key]; !found {
common.Log.Infof("creating ipset: %#v", spec)
if err := ss.ips.Create(spec.ipsetName, spec.ipsetType); err != nil {
return err
}
selector := &selector{ss.ips, spec}
if err := ss.onNewSelector(selector); err != nil {
return err
}
@@ -122,6 +159,15 @@ func (ss *selectorSet) provision(user types.UID, current, desired map[string]*se
ss.entries[key] = selector
}
ss.users[key][user] = struct{}{}
if spec.dst {
ss.dstSelectorsCount[key]++
if ss.dstSelectorsCount[key] == 1 {
if err := ss.onNewDstSelector(selector); err != nil {
return err
}
}
}
}
}
return nil
+2 -2
View File
@@ -38,14 +38,14 @@ func (i *Ipam) Allocate(args *skel.CmdArgs) (types.Result, error) {
var ipnet *net.IPNet
if conf.Subnet == "" {
ipnet, err = i.weave.AllocateIP(containerID)
ipnet, err = i.weave.AllocateIP(containerID, false)
} else {
var subnet *net.IPNet
subnet, err = types.ParseCIDR(conf.Subnet)
if err != nil {
return nil, fmt.Errorf("subnet given in config, but not parseable: %s", err)
}
ipnet, err = i.weave.AllocateIPInSubnet(containerID, subnet)
ipnet, err = i.weave.AllocateIPInSubnet(containerID, subnet, false)
}
if err != nil {
+8 -3
View File
@@ -19,6 +19,11 @@ func NewIpam(weave *api.Client) *Ipam {
return &Ipam{weave: weave}
}
func (i *Ipam) GetCapabilities() (RequiresMACAddress bool, RequiresRequestReplay bool, err error) {
i.logReq("GetCapabilities")
return false, false, nil
}
func (i *Ipam) GetDefaultAddressSpaces() (string, string, error) {
i.logReq("GetDefaultAddressSpaces")
return "weavelocal", "weaveglobal", nil
@@ -73,7 +78,7 @@ func (i *Ipam) RequestAddress(poolID string, address net.IP, options map[string]
i.logReq("RequestAddress", poolID, address, options)
defer func() { i.logRes("RequestAddress", err, ip) }()
if poolID == "weavepool" { // old-style
ip, err = i.weave.AllocateIP(api.NoContainerID)
ip, err = i.weave.AllocateIP(api.NoContainerID, false)
return
}
subnet, iprange, err := splitPoolID(poolID)
@@ -82,12 +87,12 @@ func (i *Ipam) RequestAddress(poolID string, address net.IP, options map[string]
}
if address != nil { // try to claim specific address requested
ip = &net.IPNet{IP: address, Mask: subnet.Mask}
if err = i.weave.ClaimIP(api.NoContainerID, ip); err != nil {
if err = i.weave.ClaimIP(api.NoContainerID, ip, false); err != nil {
return
}
} else {
// We are lying slightly to IPAM here: the range is not a subnet
if ip, err = i.weave.AllocateIPInSubnet(api.NoContainerID, iprange); err != nil {
if ip, err = i.weave.AllocateIPInSubnet(api.NoContainerID, iprange, false); err != nil {
return
}
ip.Mask = subnet.Mask // fix up the subnet we lied about
+7 -23
View File
@@ -6,7 +6,6 @@ import (
"fmt"
"net"
"os"
"syscall"
"github.com/containernetworking/cni/pkg/ipam"
"github.com/containernetworking/cni/pkg/skel"
@@ -100,12 +99,11 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error {
return fmt.Errorf("unable to allocate IP address for bridge: %s", err)
}
bridgeCIDR := bridgeIPResult.IPs[0].Address
if err := assignBridgeIP(conf.BrName, bridgeCIDR); err != nil {
return fmt.Errorf("unable to assign IP address to bridge: %s", err)
}
if err := weavenet.ExposeNAT(bridgeCIDR); err != nil {
return fmt.Errorf("unable to create NAT rules: %s", err)
if err := c.weave.Expose(&bridgeCIDR); err != nil {
return fmt.Errorf("unable to expose bridge %q: %s", conf.BrName, err)
}
bridgeIP = bridgeCIDR.IP
} else if err != nil {
return err
@@ -167,22 +165,6 @@ func setupRoutes(link netlink.Link, name string, ipnet net.IPNet, gw net.IP, rou
return nil
}
func assignBridgeIP(bridgeName string, ipnet net.IPNet) error {
link, err := netlink.LinkByName(bridgeName)
if err != nil {
return err
}
if err := netlink.AddrAdd(link, &netlink.Addr{IPNet: &ipnet}); err != nil {
// Treat as non-error if this address is already there
// - maybe another copy of this program just added it
if err == syscall.Errno(syscall.EEXIST) {
return nil
}
return fmt.Errorf("failed to add IP address to %q: %v", bridgeName, err)
}
return nil
}
// As of CNI 0.5 spec:
// "Plugins should generally complete a DEL action without error even if some resources are missing"
// this method should therefore return nil in most, if not all, cases.
@@ -207,7 +189,9 @@ func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
} else {
err = ipam.ExecDel(conf.IPAM.Type, args.StdinData)
}
logOnStderr(fmt.Errorf("unable to release IP address: %s", err))
if err != nil {
logOnStderr(fmt.Errorf("unable to release IP address: %s", err))
}
return nil
}
+60 -12
View File
@@ -28,25 +28,40 @@ type network struct {
}
type driver struct {
name string
scope string
docker *docker.Client
sync.RWMutex
networks map[string]network
name string
scope string
// Docker API is not available for plugin-v2
docker *docker.Client
dns bool
isPluginV2 bool
// Enable multicast regardless whether multicast opt is passed to Docker;
// used only by plugin-v2
forceMulticast bool
networks map[string]network
}
func New(client *docker.Client, weave *weaveapi.Client, name, scope string) (skel.Driver, error) {
func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns, isPluginV2, forceMulticast bool) (skel.Driver, error) {
driver := &driver{
name: name,
scope: scope,
docker: client,
networks: make(map[string]network),
name: name,
scope: scope,
docker: client,
dns: dns,
isPluginV2: isPluginV2,
// make sure that it's used only by plugin-v2
forceMulticast: isPluginV2 && forceMulticast,
networks: make(map[string]network),
}
_, err := NewWatcher(client, weave, driver)
if err != nil {
return nil, err
// Do not start watcher in the case of plugin v2, which prevents us from
// configuring arp settings of containers.
if client != nil {
_, err := NewWatcher(client, weave, driver)
if err != nil {
return nil, err
}
}
return driver, nil
}
@@ -61,12 +76,27 @@ func (driver *driver) GetCapabilities() (*api.GetCapabilityResponse, error) {
return caps, nil
}
// In Swarm mode, CreateNetwork is called on each Swarm node when a new service
// is created.
func (driver *driver) CreateNetwork(create *api.CreateNetworkRequest) error {
driver.logReq("CreateNetwork", create, create.NetworkID)
_, err := driver.setupNetworkInfo(create.NetworkID, true, stringOptions(create))
return err
}
// NetworkAllocate is called on a Swarm node (master) which creates the network.
// The returned options are passed to CreateNetwork.
func (driver *driver) NetworkAllocate(alloc *api.AllocateNetworkRequest) (*api.AllocateNetworkResponse, error) {
driver.logReq("NetworkAllocate", alloc, alloc.NetworkID)
return &api.AllocateNetworkResponse{Options: alloc.Options}, nil
}
// NetworkFree is called on a Swarm master node which created the network.
func (driver *driver) NetworkFree(free *api.FreeNetworkRequest) (*api.FreeNetworkResponse, error) {
driver.logReq("NetworkFree", free, free.NetworkID)
return nil, nil
}
// Deal with excessively-generic way the options get decoded from JSON
func stringOptions(create *api.CreateNetworkRequest) map[string]string {
if create.Options != nil {
@@ -85,6 +115,7 @@ func stringOptions(create *api.CreateNetworkRequest) map[string]string {
return nil
}
// In Swarm mode, DeleteNetwork is called after a service has been removed.
func (driver *driver) DeleteNetwork(delreq *api.DeleteNetworkRequest) error {
driver.logReq("DeleteNetwork", delreq, delreq.NetworkID)
driver.Lock()
@@ -163,12 +194,29 @@ func (driver *driver) JoinEndpoint(j *api.JoinRequest) (*api.JoinResponse, error
}
func (driver *driver) findNetworkInfo(id string) (network, error) {
var network network
// plugin-v2 does not have access to docker.sock, so we cannot call Docker
// API for the network info.
if driver.isPluginV2 {
// safe to set, as isOurs used only by the watcher which is disabled for plugin-v2
network.isOurs = true
network.hasMulticastRoute = driver.forceMulticast
return network, nil
}
driver.Lock()
network, found := driver.networks[id]
driver.Unlock()
if found {
return network, nil
}
if driver.docker == nil {
return network, fmt.Errorf("Docker client disabled; unable to get network info")
}
info, err := driver.docker.NetworkInfo(id)
if err != nil {
return network, err
+12 -8
View File
@@ -8,10 +8,6 @@ import (
weavenet "github.com/weaveworks/weave/net"
)
const (
WeaveDomain = "weave.local"
)
type watcher struct {
client *docker.Client
weave *weaveapi.Client
@@ -41,11 +37,19 @@ func (w *watcher) ContainerStarted(id string) {
continue
}
if network.isOurs {
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)
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)
}
}
if _, err := weavenet.WithNetNSByPid(info.State.Pid, "configure-arp", weavenet.VethName); err != nil {
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)
if _, err := weavenet.WithNetNS(netNSPath, "configure-arp", weavenet.VethName, rootDir); err != nil {
w.driver.warn("ContainerStarted", "unable to configure interfaces: %s", err)
}
}
+124
View File
@@ -0,0 +1,124 @@
package plugin
import (
"net"
"os"
"path"
"strings"
"github.com/docker/libnetwork/ipamapi"
weaveapi "github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/common/docker"
weavenet "github.com/weaveworks/weave/net"
ipamplugin "github.com/weaveworks/weave/plugin/ipam"
netplugin "github.com/weaveworks/weave/plugin/net"
"github.com/weaveworks/weave/plugin/skel"
)
const (
pluginV2Name = "net-plugin"
defaultNetwork = "weave"
MulticastOption = netplugin.MulticastOption
)
var Log = common.Log
type Config struct {
Socket string
MeshSocket string
Enable bool
EnableV2 bool
EnableV2Multicast bool
DNS bool
DefaultSubnet string
}
type Plugin struct {
Config
}
func NewPlugin(config Config) *Plugin {
if !config.Enable && !config.EnableV2 {
return nil
}
plugin := &Plugin{Config: config}
return plugin
}
func (plugin *Plugin) Start(weaveAPIAddr string, dockerClient *docker.Client, ready func()) {
weave := weaveapi.NewClient(weaveAPIAddr, Log)
Log.Info("Waiting for Weave API Server...")
weave.WaitAPIServer(30)
Log.Info("Finished waiting for Weave API Server")
if err := plugin.run(dockerClient, weave, ready); err != nil {
Log.Fatal(err)
}
}
func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, ready func()) error {
endChan := make(chan error, 1)
if plugin.Socket != "" {
globalListener, err := listenAndServe(dockerClient, weave, plugin.Socket, endChan, "global", false, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast)
if err != nil {
return err
}
defer os.Remove(plugin.Socket)
defer globalListener.Close()
}
if plugin.MeshSocket != "" {
meshListener, err := listenAndServe(dockerClient, weave, plugin.MeshSocket, endChan, "local", true, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast)
if err != nil {
return err
}
defer os.Remove(plugin.MeshSocket)
defer meshListener.Close()
if !plugin.EnableV2 {
Log.Printf("Creating default %q network", defaultNetwork)
options := map[string]interface{}{MulticastOption: "true"}
dockerClient.EnsureNetwork(defaultNetwork, pluginNameFromAddress(plugin.MeshSocket), plugin.DefaultSubnet, options)
}
}
ready()
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) {
var name string
if isPluginV2 {
name = pluginV2Name
} else {
name = pluginNameFromAddress(address)
}
d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2, forceMulticast)
if err != nil {
return nil, err
}
var i ipamapi.Ipam
if withIpam {
i = ipamplugin.NewIpam(weave)
}
listener, err := weavenet.ListenUnixSocket(address)
if err != nil {
return nil, err
}
Log.Printf("Listening on %s for %s scope", address, scope)
go func() {
endChan <- skel.Listen(listener, d, i)
}()
return listener, nil
}
// Take a socket address like "/run/docker/plugins/weavemesh.sock" and extract the plugin name "weavemesh"
func pluginNameFromAddress(address string) string {
return strings.TrimSuffix(path.Base(address), ".sock")
}
+49 -6
View File
@@ -26,11 +26,17 @@ type Driver interface {
DeleteEndpoint(delete *api.DeleteEndpointRequest) error
EndpointInfo(req *api.EndpointInfoRequest) (*api.EndpointInfoResponse, error)
JoinEndpoint(j *api.JoinRequest) (response *api.JoinResponse, error error)
NetworkAllocate(*api.AllocateNetworkRequest) (*api.AllocateNetworkResponse, error)
NetworkFree(*api.FreeNetworkRequest) (*api.FreeNetworkResponse, error)
LeaveEndpoint(leave *api.LeaveRequest) error
DiscoverNew(discover *api.DiscoveryNotification) error
DiscoverDelete(delete *api.DiscoveryNotification) error
}
type IpamCapability interface {
GetCapabilities() (RequiresMACAddress bool, RequiresRequestReplay bool, err error)
}
type listener struct {
d Driver
i ipamapi.Ipam
@@ -58,9 +64,12 @@ func Listen(socket net.Listener, driver Driver, ipamDriver ipamapi.Ipam) error {
handleMethod(networkReceiver, "EndpointOperInfo", listener.infoEndpoint)
handleMethod(networkReceiver, "Join", listener.joinEndpoint)
handleMethod(networkReceiver, "Leave", listener.leaveEndpoint)
handleMethod(networkReceiver, "AllocateNetwork", listener.networkAllocate)
handleMethod(networkReceiver, "FreeNetwork", listener.networkFree)
}
if ipamDriver != nil {
handleMethod(ipamReceiver, "GetCapabilities", listener.getIpamCapabilities)
handleMethod(ipamReceiver, "GetDefaultAddressSpaces", listener.getDefaultAddressSpaces)
handleMethod(ipamReceiver, "RequestPool", listener.requestPool)
handleMethod(ipamReceiver, "ReleasePool", listener.releasePool)
@@ -137,7 +146,7 @@ func (listener *listener) createEndpoint(w http.ResponseWriter, r *http.Request)
func (listener *listener) deleteEndpoint(w http.ResponseWriter, r *http.Request) {
var delete api.DeleteEndpointRequest
if err := json.NewDecoder(r.Body).Decode(&delete); err != nil {
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
return
}
emptyOrErrorResponse(w, listener.d.DeleteEndpoint(&delete))
@@ -146,7 +155,7 @@ func (listener *listener) deleteEndpoint(w http.ResponseWriter, r *http.Request)
func (listener *listener) infoEndpoint(w http.ResponseWriter, r *http.Request) {
var req api.EndpointInfoRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
return
}
info, err := listener.d.EndpointInfo(&req)
@@ -156,17 +165,37 @@ func (listener *listener) infoEndpoint(w http.ResponseWriter, r *http.Request) {
func (listener *listener) joinEndpoint(w http.ResponseWriter, r *http.Request) {
var join api.JoinRequest
if err := json.NewDecoder(r.Body).Decode(&join); err != nil {
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
return
}
res, err := listener.d.JoinEndpoint(&join)
objectOrErrorResponse(w, res, err)
}
func (listener *listener) networkAllocate(w http.ResponseWriter, r *http.Request) {
var alloc api.AllocateNetworkRequest
if err := json.NewDecoder(r.Body).Decode(&alloc); err != nil {
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
return
}
res, err := listener.d.NetworkAllocate(&alloc)
objectOrErrorResponse(w, res, err)
}
func (listener *listener) networkFree(w http.ResponseWriter, r *http.Request) {
var free api.FreeNetworkRequest
if err := json.NewDecoder(r.Body).Decode(&free); err != nil {
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
return
}
res, err := listener.d.NetworkFree(&free)
objectOrErrorResponse(w, res, err)
}
func (listener *listener) leaveEndpoint(w http.ResponseWriter, r *http.Request) {
var l api.LeaveRequest
if err := json.NewDecoder(r.Body).Decode(&l); err != nil {
sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest)
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
return
}
emptyOrErrorResponse(w, listener.d.LeaveEndpoint(&l))
@@ -175,7 +204,7 @@ func (listener *listener) leaveEndpoint(w http.ResponseWriter, r *http.Request)
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 encode payload", http.StatusBadRequest)
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
return
}
emptyOrErrorResponse(w, listener.d.DiscoverNew(&disco))
@@ -184,7 +213,7 @@ func (listener *listener) discoverNew(w http.ResponseWriter, r *http.Request) {
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 encode payload", http.StatusBadRequest)
sendError(w, "Could not decode JSON encoded payload", http.StatusBadRequest)
return
}
emptyOrErrorResponse(w, listener.d.DiscoverDelete(&disco))
@@ -192,6 +221,20 @@ func (listener *listener) discoverDelete(w http.ResponseWriter, r *http.Request)
// ===
func (listener *listener) getIpamCapabilities(w http.ResponseWriter, r *http.Request) {
c, ok := listener.i.(IpamCapability)
if !ok {
http.NotFound(w, r)
return
}
requiresMACAddress, requiresRequestReplay, err := c.GetCapabilities()
response := &ipamapi.Capability{
RequiresMACAddress: requiresMACAddress,
RequiresRequestReplay: requiresRequestReplay,
}
objectOrErrorResponse(w, response, err)
}
func (listener *listener) getDefaultAddressSpaces(w http.ResponseWriter, r *http.Request) {
local, global, err := listener.i.GetDefaultAddressSpaces()
response := &iapi.GetAddressSpacesResponse{
+19
View File
@@ -0,0 +1,19 @@
package plugin
type Status struct {
Config Config
DriverName string
MeshDriverName string `json:"MeshDriverName,omitempty"`
}
func (plugin *Plugin) NewStatus() *Status {
if plugin == nil {
return nil
}
status := &Status{
DriverName: pluginNameFromAddress(plugin.Socket),
MeshDriverName: pluginNameFromAddress(plugin.MeshSocket),
Config: plugin.Config,
}
return status
}
+210
View File
@@ -0,0 +1,210 @@
/*
In order to keep track of active weave peers, we use annotations on the Kubernetes cluster.
Kubernetes uses etcd to distribute and synchronise these annotations so we don't have to.
This module deals with operations on the peerlist backed by Kubernetes' annotation mechanism.
*/
package main
import (
"encoding/json"
"log"
"time"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
kubeErrors "k8s.io/apimachinery/pkg/api/errors"
api "k8s.io/apimachinery/pkg/apis/meta/v1"
wait "k8s.io/apimachinery/pkg/util/wait"
kubernetes "k8s.io/client-go/kubernetes"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
)
type configMapAnnotations struct {
ConfigMapName string
Namespace string
Client corev1client.ConfigMapsGetter
cm *v1.ConfigMap
}
func newConfigMapAnnotations(ns string, configMapName string, clientset *kubernetes.Clientset) *configMapAnnotations {
return &configMapAnnotations{
Namespace: ns,
ConfigMapName: configMapName,
Client: clientset.CoreV1(),
}
}
type peerList struct {
Peers []peerInfo
}
type peerInfo struct {
PeerName string // Weave internal unique ID
NodeName string // Kubernetes node name
}
func (pl peerList) contains(peerName string) bool {
for _, peer := range pl.Peers {
if peer.PeerName == peerName {
return true
}
}
return false
}
func (pl *peerList) add(peerName string, name string) {
pl.Peers = append(pl.Peers, peerInfo{PeerName: peerName, NodeName: name})
}
func (pl *peerList) remove(peerNameToRemove string) {
for i := 0; i < len(pl.Peers); {
if pl.Peers[i].PeerName == peerNameToRemove {
pl.Peers = append(pl.Peers[:i], pl.Peers[i+1:]...)
} else {
i++
}
}
}
const (
retryPeriod = time.Second * 2
jitterFactor = 1.0
// Prefix all our annotation keys with this string so they don't clash with anyone else's
KubePeersPrefix = "kube-peers.weave.works/"
// KubePeersAnnotationKey is the default annotation key
KubePeersAnnotationKey = KubePeersPrefix + "peers"
)
func (cml *configMapAnnotations) Init() error {
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{})
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{
ObjectMeta: api.ObjectMeta{
Name: cml.ConfigMapName,
Namespace: cml.Namespace,
},
})
if err != nil {
if kubeErrors.IsAlreadyExists(err) {
continue
}
return errors.Wrapf(err, "Unable to create ConfigMap %s/%s", cml.Namespace, cml.ConfigMapName)
}
}
break
}
if cml.cm.Annotations == nil {
cml.cm.Annotations = make(map[string]string)
}
return nil
}
func (cml *configMapAnnotations) GetPeerList() (*peerList, error) {
var record peerList
if cml.cm == nil {
return nil, errors.New("endpoint not initialized, call Init first")
}
if recordBytes, found := cml.cm.Annotations[KubePeersAnnotationKey]; found {
if err := json.Unmarshal([]byte(recordBytes), &record); err != nil {
return nil, err
}
}
return &record, nil
}
func (cml *configMapAnnotations) UpdatePeerList(list peerList) error {
recordBytes, err := json.Marshal(list)
if err != nil {
return err
}
return cml.UpdateAnnotation(KubePeersAnnotationKey, string(recordBytes))
}
// Clean up a string so it meets the Kubernetes requiremements for Annotation keys:
// name part must consist of alphanumeric characters, '-', '_' or '.', and must
// start and end with an alphanumeric character (e.g. 'MyName', or 'my.name', or '123-abc')
func cleanKey(key string) string {
buf := []byte(key)
for i, c := range buf {
if (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '/' {
continue
}
buf[i] = '_'
}
return string(buf)
}
func (cml *configMapAnnotations) GetAnnotation(key string) (string, bool) {
value, ok := cml.cm.Annotations[cleanKey(key)]
return value, ok
}
func (cml *configMapAnnotations) UpdateAnnotation(key, value string) (err error) {
if cml.cm == 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 whatever happened
cml.cm.Annotations[cleanKey(key)] = value
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(cml.cm)
return err
}
func (cml *configMapAnnotations) RemoveAnnotation(key string) (err error) {
if cml.cm == 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 whatever happened
delete(cml.cm.Annotations, cleanKey(key))
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(cml.cm)
return err
}
func (cml *configMapAnnotations) RemoveAnnotationsWithValue(valueToRemove string) (err error) {
if cml.cm == 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 whatever happened
for key, value := range cml.cm.Annotations {
if value == valueToRemove {
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)
return err
}
// Loop with jitter, fetching the cml data and calling f() until it
// doesn't get an optimistic locking conflict.
// If it succeeds or gets any other kind of error, stop the loop.
func (cml *configMapAnnotations) LoopUpdate(f func() error) error {
stop := make(chan struct{})
var err error
wait.JitterUntil(func() {
if err = cml.Init(); err != nil {
close(stop)
return
}
err = f()
if err != nil && kubeErrors.IsConflict(err) {
log.Printf("Optimistic locking conflict: trying again: %s", err)
return
}
close(stop)
}, retryPeriod, jitterFactor, true, stop)
return err
}
+196 -31
View File
@@ -1,40 +1,36 @@
/*
Package main deals with weave-net peers on the cluster.
This involves peer management, such as getting the latest peers or removing defunct peers from the cluster
*/
package main
import (
"flag"
"fmt"
"log"
"net"
"os"
api "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
api "k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/rest"
weaveapi "github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
)
func getKubePeers() ([]string, error) {
config, err := rest.InClusterConfig()
if err != nil {
return nil, err
}
c, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
nodeList, err := c.Nodes().List(api.ListOptions{})
if err != nil {
// Fallback for cases (e.g. from kube-up.sh) where kube-proxy is not running on master
config.Host = "http://localhost:8080"
log.Print("error contacting APIServer: ", err, "; trying with fallback: ", config.Host)
c, err = kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
nodeList, err = c.Nodes().List(api.ListOptions{})
}
type nodeInfo struct {
name string
addr string
}
// return the IP addresses of all nodes in the cluster
func getKubePeers(c *kubernetes.Clientset) ([]nodeInfo, error) {
nodeList, err := c.CoreV1().Nodes().List(api.ListOptions{})
if err != nil {
return nil, err
}
addresses := make([]string, 0, len(nodeList.Items))
addresses := make([]nodeInfo, 0, len(nodeList.Items))
for _, peer := range nodeList.Items {
var internalIP, externalIP string
for _, addr := range peer.Status.Addresses {
@@ -52,20 +48,189 @@ func getKubePeers() ([]string, error) {
// Fallback for cases where a Node has an ExternalIP but no InternalIP
if internalIP != "" {
addresses = append(addresses, internalIP)
addresses = append(addresses, nodeInfo{name: peer.Name, addr: internalIP})
} else if externalIP != "" {
addresses = append(addresses, externalIP)
addresses = append(addresses, nodeInfo{name: peer.Name, addr: externalIP})
}
}
return addresses, nil
}
func main() {
peers, err := getKubePeers()
if err != nil {
log.Fatalf("Could not get peers: %v", err)
const (
configMapName = "weave-net"
configMapNamespace = "kube-system"
)
// update the list of all peers that have gone through this code path
func addMyselfToPeerList(cml *configMapAnnotations, c *kubernetes.Clientset, peerName, name string) (*peerList, error) {
var list *peerList
err := cml.LoopUpdate(func() error {
var err error
list, err = cml.GetPeerList()
if err != nil {
return err
}
if !list.contains(peerName) {
list.add(peerName, name)
err = cml.UpdatePeerList(*list)
if err != nil {
return err
}
}
return nil
})
return list, err
}
func checkIamInPeerList(cml *configMapAnnotations, c *kubernetes.Clientset, peerName string) (bool, error) {
if err := cml.Init(); err != nil {
return false, err
}
for _, addr := range peers {
fmt.Println(addr)
list, err := cml.GetPeerList()
if err != nil {
return false, err
}
common.Log.Debugf("[kube-peers] Checking peer %q against list %v", peerName, list)
return list.contains(peerName), nil
}
// For each of those peers that is no longer listed as a node by
// Kubernetes, remove it from Weave IPAM
func reclaimRemovedPeers(weave *weaveapi.Client, cml *configMapAnnotations, nodes []nodeInfo, myPeerName string) error {
for {
if err := cml.Init(); err != nil {
return err
}
// 1. Compare peers stored in the peerList against all peers reported by k8s now.
storedPeerList, err := cml.GetPeerList()
if err != nil {
return err
}
peerMap := make(map[string]peerInfo, len(storedPeerList.Peers))
for _, peer := range storedPeerList.Peers {
peerMap[peer.NodeName] = peer
}
for _, node := range nodes {
delete(peerMap, node.name)
}
common.Log.Debugln("[kube-peers] Nodes that have disappeared:", peerMap)
if len(peerMap) == 0 {
break
}
// 2. Loop for each X in the first set and not in the second - we wish to remove X from our data structures
for _, peer := range peerMap {
common.Log.Debugln("[kube-peers] Preparing to remove disappeared peer", peer)
okToRemove := false
// 3. Check if there is an existing annotation with key X
if existingAnnotation, found := cml.GetAnnotation(KubePeersPrefix + peer.PeerName); found {
common.Log.Debugln("[kube-peers] Existing annotation", existingAnnotation)
// 4. If annotation already contains my identity, ok;
if existingAnnotation == myPeerName {
okToRemove = true
}
} else {
// 5. If non-existent, write an annotation with key X and contents "my identity"
common.Log.Debugln("[kube-peers] Noting I plan to remove ", peer.PeerName)
if err := cml.UpdateAnnotation(KubePeersPrefix+peer.PeerName, myPeerName); err == nil {
okToRemove = true
} else {
common.Log.Debugln("[kube-peers] error from UpdateAnnotation: ", err)
}
}
if okToRemove {
// 6. If step 4 or 5 succeeded, rmpeer X
result, err := weave.RmPeer(peer.PeerName)
common.Log.Infof("[kube-peers] rmpeer of %s: %s", peer.PeerName, result)
if err != nil {
return err
}
cml.LoopUpdate(func() error {
// 7aa. Remove any annotations Z* that have contents X
if err := cml.RemoveAnnotationsWithValue(peer.PeerName); err != nil {
return err
}
// 7a. Remove X from peerList
storedPeerList.remove(peer.PeerName)
if err := cml.UpdatePeerList(*storedPeerList); err != nil {
return err
}
// 7b. Remove annotation with key X
return cml.RemoveAnnotation(KubePeersPrefix + peer.PeerName)
})
}
// 8. If step 5 failed due to optimistic lock conflict, stop: someone else is handling X
// Step 3-5 is to protect against two simultaneous rmpeers of X
// Step 4 is to pick up again after a restart between step 5 and step 7b
// If the peer doing the reclaim disappears between steps 5 and 7a, then someone will clean it up in step 7aa
// If peer doing the reclaim disappears forever between 7a and 7b then we get a dangling annotation
// This should be sufficiently rare that we don't care.
}
// 9. Go back to step 1 until there is no difference between the two sets
}
// Question: Should we narrow step 2 by checking against Weave Net IPAM?
// i.e. If peer X owns any address space and is marked unreachable, we want to rmpeer X
return nil
}
func main() {
var (
justReclaim bool
justCheck bool
peerName string
nodeName string
logLevel string
)
flag.BoolVar(&justReclaim, "reclaim", false, "reclaim IP space from dead peers")
flag.BoolVar(&justCheck, "check-peer-new", false, "return success if peer name is not stored in annotation")
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)")
flag.Parse()
common.SetLogLevel(logLevel)
config, err := rest.InClusterConfig()
if err != nil {
common.Log.Fatalf("[kube-peers] Could not get cluster config: %v", err)
}
c, err := kubernetes.NewForConfig(config)
if err != nil {
common.Log.Fatalf("[kube-peers] Could not make Kubernetes connection: %v", err)
}
if justCheck {
cml := newConfigMapAnnotations(configMapNamespace, configMapName, c)
exists, err := checkIamInPeerList(cml, c, peerName)
if err != nil {
common.Log.Fatalf("[kube-peers] Could not check peer list: %v", err)
}
if exists {
os.Exit(9)
} else {
os.Exit(0)
}
}
peers, err := getKubePeers(c)
if err != nil {
common.Log.Fatalf("[kube-peers] Could not get peers: %v", err)
}
if justReclaim {
cml := newConfigMapAnnotations(configMapNamespace, configMapName, c)
list, err := addMyselfToPeerList(cml, c, peerName, nodeName)
if err != nil {
common.Log.Fatalf("[kube-peers] Could not update peer list: %v", err)
}
common.Log.Infoln("[kube-peers] Added myself to peer list", list)
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), common.Log)
err = reclaimRemovedPeers(weave, cml, peers, peerName)
if err != nil {
common.Log.Fatalf("[kube-peers] Error while reclaiming space: %v", err)
}
return
}
for _, node := range peers {
fmt.Println(node.addr)
}
}
+98
View File
@@ -0,0 +1,98 @@
{
"description": "Weave Net plugin for Docker",
"documentation": "https://weave.works",
"entrypoint": [
"/home/weave/launch.sh"
],
"interface": {
"socket": "weave.sock",
"types": [
"docker.networkdriver/1.0"
]
},
"linux": {
"capabilities": [
"CAP_SYS_ADMIN",
"CAP_NET_ADMIN",
"CAP_SYS_MODULE"
]
},
"mounts": [
{
"destination": "/host/proc/",
"type": "bind",
"source": "/proc/",
"options": ["rbind", "rw"]
},
{
"destination": "/var/run/docker.sock",
"source": "/var/run/docker.sock",
"type": "bind",
"options": ["rbind"]
},
{
"destination": "/host/var/lib/",
"source": "/var/lib/",
"type": "bind",
"options": ["rbind"]
},
{
"destination": "/host/etc/",
"source": "/etc/",
"type": "bind",
"options": ["rbind"]
},
{
"destination": "/lib/modules/",
"source": "/lib/modules/",
"type": "bind",
"options": ["rbind"]
}
],
"env": [
{
"description": "Extra args to `weaver` and `plugin`",
"name": "EXTRA_ARGS",
"settable": [
"value"
],
"value": ""
},
{
"description": "Encryption password",
"name": "WEAVE_PASSWORD",
"settable": [
"value"
],
"value": ""
},
{
"description": "MTU",
"name": "WEAVE_MTU",
"settable": [
"value"
],
"value": ""
},
{
"description": "Enable multicast for all Weave networks",
"name": "WEAVE_MULTICAST",
"settable": [
"value"
],
"value": ""
},
{
"description": "The range of IP addresses used by Weave Net",
"name": "IPALLOC_RANGE",
"settable": [
"value"
],
"value": ""
}
],
"network": {
"type": "host"
},
"workdir": ""
}
+53
View File
@@ -0,0 +1,53 @@
#!/bin/sh
set -e
# 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}
STATUS_ADDR=${WEAVE_STATUS_ADDR:-0.0.0.0:6782}
HOST_ROOT=${HOST_ROOT:-/host}
WEAVE_DIR="/host/var/lib/weave"
mkdir $WEAVE_DIR || true
echo "Starting launch.sh"
# Check if the IP range overlaps anything existing on the host
/usr/bin/weaveutil netcheck $IPALLOC_RANGE weave
# We need to get a list of Swarm nodes which might run the net-plugin:
# - In the case of missing restart.sentinel, we assume that net-plugin has started
# for the first time via the docker-plugin cmd. So it's safe to request docker.sock.
# - If restart.sentinel present, let weaver restore from it as docker.sock is not
# available to any plugin in general (https://github.com/moby/moby/issues/32815).
PEERS=
if [ ! -f "/restart.sentinel" ]; then
PEERS=$(/usr/bin/weaveutil swarm-manager-peers)
fi
router_bridge_opts() {
echo --datapath=datapath
[ -z "$WEAVE_MTU" ] || echo --mtu "$WEAVE_MTU"
[ -z "$WEAVE_NO_FASTDP" ] || echo --no-fastdp
}
multicast_opt() {
[ -z "$WEAVE_MULTICAST" ] || echo "--plugin-v2-multicast"
}
exec /home/weave/weaver $EXTRA_ARGS --port=6783 $(router_bridge_opts) \
--host-root=/host \
--proc-path=/host/proc \
--http-addr=$HTTP_ADDR --status-addr=$STATUS_ADDR \
--no-dns \
--ipalloc-range=$IPALLOC_RANGE \
--nickname "$(hostname)" \
--log-level=debug \
--db-prefix="$WEAVE_DIR/weave" \
--plugin-v2 \
$(multicast_opt) \
--plugin-mesh-socket='' \
--docker-api='' \
$PEERS
-3
View File
@@ -1,3 +0,0 @@
FROM DOCKERHUB_USER/weaveARCH_EXT
ADD ./plugin /home/weave/
ENTRYPOINT ["/home/weave/plugin"]
-140
View File
@@ -1,140 +0,0 @@
package main
import (
"flag"
"fmt"
"net"
"net/http"
"os"
"os/signal"
"path"
"strings"
"syscall"
"github.com/docker/libnetwork/ipamapi"
weaveapi "github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/common/docker"
weavenet "github.com/weaveworks/weave/net"
ipamplugin "github.com/weaveworks/weave/plugin/ipam"
netplugin "github.com/weaveworks/weave/plugin/net"
"github.com/weaveworks/weave/plugin/skel"
)
var version = "unreleased"
var Log = common.Log
func main() {
var (
justVersion bool
address string
meshAddress string
logLevel string
noMulticastRoute bool
)
flag.BoolVar(&justVersion, "version", false, "print version and exit")
flag.StringVar(&logLevel, "log-level", "info", "logging level (debug, info, warning, error)")
flag.StringVar(&address, "socket", "/run/docker/plugins/weave.sock", "socket on which to listen")
flag.StringVar(&meshAddress, "meshsocket", "/run/docker/plugins/weavemesh.sock", "socket on which to listen in mesh mode")
flag.BoolVar(&noMulticastRoute, "no-multicast-route", false, "deprecated (this is now the default)")
flag.Parse()
if justVersion {
fmt.Printf("weave plugin %s\n", version)
os.Exit(0)
}
common.SetLogLevel(logLevel)
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), Log)
// API 1.21 is the first version that supports docker network commands
dockerClient, err := docker.NewVersionedClientFromEnv("1.21")
if err != nil {
Log.Fatalf("unable to connect to docker: %s", err)
}
Log.Println("Weave plugin", version, "Command line options:", os.Args[1:])
if noMulticastRoute {
Log.Warning("--no-multicast-route option has been removed; multicast is off by default")
}
Log.Info(dockerClient.Info())
err = run(dockerClient, weave, address, meshAddress)
if err != nil {
Log.Fatal(err)
}
}
func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddress string) error {
endChan := make(chan error, 1)
if address != "" {
globalListener, err := listenAndServe(dockerClient, weave, address, endChan, "global", false)
if err != nil {
return err
}
defer os.Remove(address)
defer globalListener.Close()
}
if meshAddress != "" {
meshListener, err := listenAndServe(dockerClient, weave, meshAddress, endChan, "local", true)
if err != nil {
return err
}
defer os.Remove(meshAddress)
defer meshListener.Close()
}
statusListener, err := weavenet.ListenUnixSocket("/home/weave/status.sock")
if err != nil {
return err
}
go serveStatus(statusListener)
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
select {
case sig := <-sigChan:
Log.Debugf("Caught signal %s; shutting down", sig)
return nil
case err := <-endChan:
return err
}
}
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam bool) (net.Listener, error) {
name := strings.TrimSuffix(path.Base(address), ".sock")
d, err := netplugin.New(dockerClient, weave, name, scope)
if err != nil {
return nil, err
}
var i ipamapi.Ipam
if withIpam {
i = ipamplugin.NewIpam(weave)
}
listener, err := weavenet.ListenUnixSocket(address)
if err != nil {
return nil, err
}
Log.Printf("Listening on %s for %s scope", address, scope)
go func() {
endChan <- skel.Listen(listener, d, i)
}()
return listener, nil
}
func serveStatus(listener net.Listener) {
server := &http.Server{Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "ok")
})}
if err := server.Serve(listener); err != nil {
Log.Fatalf("ListenAndServeStatus failed: %s", err)
}
}
-12
View File
@@ -1,12 +0,0 @@
package main
import (
"testing"
weavetest "github.com/weaveworks/weave/testing"
)
func TestMain(t *testing.T) {
weavetest.TrimTestArgs()
main()
}
+39 -16
View File
@@ -30,6 +30,7 @@ HTTP_ADDR=${WEAVE_HTTP_ADDR:-127.0.0.1:6784}
STATUS_ADDR=${WEAVE_STATUS_ADDR:-0.0.0.0:6782}
HOST_ROOT=${HOST_ROOT:-/host}
CONN_LIMIT=${CONN_LIMIT:-30}
DB_PREFIX=${DB_PREFIX:-/weavedb/weave-net}
# Check if the IP range overlaps anything existing on the host
/usr/bin/weaveutil netcheck $IPALLOC_RANGE weave
@@ -53,15 +54,12 @@ else
fi
fi
# Explicitly create the bridge so we can pass --expect-npc
# Default is that npc will be running; allow caller to override
WEAVE_NPC_OPTS="--expect-npc"
if [ "${EXPECT_NPC}" = "0" ]; then
WEAVE_NPC_OPTS=""
fi
export HOST_ROOT=/host
/home/weave/weave --local create-bridge --force $WEAVE_NPC_OPTS
# Kubernetes sets HOSTNAME to the host's hostname
# when running a pod in host namespace.
NICKNAME_ARG=""
@@ -69,17 +67,11 @@ if [ -n "$HOSTNAME" ] ; then
NICKNAME_ARG="--nickname=$HOSTNAME"
fi
BRIDGE_OPTIONS="--datapath=datapath"
if [ "$(/home/weave/weave --local bridge-type)" = "bridge" ] ; then
# TODO: Call into weave script to do this
if ! ip link show vethwe-pcap >/dev/null 2>&1 ; then
ip link add name vethwe-bridge type veth peer name vethwe-pcap
ip link set vethwe-bridge up
ip link set vethwe-pcap up
ip link set vethwe-bridge master weave
fi
BRIDGE_OPTIONS="--iface=vethwe-pcap"
fi
router_bridge_opts() {
echo --datapath=datapath
[ -z "$WEAVE_MTU" ] || echo --mtu "$WEAVE_MTU"
[ -z "$WEAVE_NO_FASTDP" ] || echo --no-fastdp
}
if [ -z "$KUBE_PEERS" ]; then
if ! KUBE_PEERS=$(/home/weave/kube-peers) || [ -z "$KUBE_PEERS" ]; then
@@ -96,6 +88,29 @@ if [ -z "$IPALLOC_INIT" ]; then
IPALLOC_INIT="consensus=$(peer_count $KUBE_PEERS)"
fi
# Find out what peer name we will be using
PEERNAME=$(/home/weave/weaver $EXTRA_ARGS --print-peer-name --host-root=$HOST_ROOT --db-prefix="$DB_PREFIX")
if [ -z "$PEERNAME" ]; then
echo "Unable to get peer name" >&2
exit 2
fi
# If we have persisted data and peer reclaim is in use
if [ -f ${DB_PREFIX}data.db ]; then
if /usr/bin/weaveutil get-db-flag "$DB_PREFIX" peer-reclaim >/dev/null ; then
# If this peer name is not stored in the list then we were removed by another peer.
if /home/weave/kube-peers -check-peer-new -peer-name="$PEERNAME" -log-level=debug ; then
# In order to avoid a CRDT clash, clean up
echo "Peer not in list; removing persisted data" >&2
rm -f ${DB_PREFIX}data.db
fi
fi
fi
# flag that peer reclaim is now in use - note we have to do this before
# 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
post_start_actions() {
# Wait for weave process to become responsive
while true ; do
@@ -114,18 +129,26 @@ post_start_actions() {
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-peers -reclaim -node-name="$HOSTNAME" -peer-name="$PEERNAME" -log-level=debug || true
# Expose the weave network so host processes can communicate with pods
/home/weave/weave --local expose $WEAVE_EXPOSE_IP
}
post_start_actions &
/home/weave/weaver $EXTRA_ARGS --port=6783 $BRIDGE_OPTIONS \
/home/weave/weaver $EXTRA_ARGS --port=6783 $(router_bridge_opts) \
--name="$PEERNAME" \
--host-root=$HOST_ROOT \
--http-addr=$HTTP_ADDR --status-addr=$STATUS_ADDR --docker-api='' --no-dns \
--db-prefix="$DB_PREFIX" \
--ipalloc-range=$IPALLOC_RANGE $NICKNAME_ARG \
--ipalloc-init $IPALLOC_INIT \
--conn-limit=$CONN_LIMIT \
$WEAVE_NPC_OPTS \
"$@" \
$KUBE_PEERS
+168 -108
View File
@@ -1,120 +1,180 @@
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: weave-net
rules:
- apiGroups:
- ""
resources:
- pods
- namespaces
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- networkpolicies
verbs:
- get
- list
- watch
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: weave-net
namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: weave-net
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: weave-net
subjects:
- kind: ServiceAccount
name: weave-net
namespace: kube-system
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: weave-net
namespace: kube-system
spec:
template:
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:
hostNetwork: true
hostPID: true
containers:
- name: weave
image: weaveworks/weave-kube:latest
imagePullPolicy: Always
command:
- /home/weave/launch.sh
livenessProbe:
initialDelaySeconds: 30
httpGet:
host: 127.0.0.1
path: /status
port: 6784
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
livenessProbe:
httpGet:
host: 127.0.0.1
path: /status
port: 6784
initialDelaySeconds: 30
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:
privileged: true
volumeMounts:
seLinuxOptions: {}
serviceAccountName: weave-net
tolerations:
- effect: NoSchedule
operator: Exists
volumes:
- name: weavedb
mountPath: /weavedb
hostPath:
path: /var/lib/weave
- name: cni-bin
mountPath: /host/opt
hostPath:
path: /opt
- name: cni-bin2
mountPath: /host/home
hostPath:
path: /home
- name: cni-conf
mountPath: /host/etc
hostPath:
path: /etc
- name: dbus
mountPath: /host/var/lib/dbus
hostPath:
path: /var/lib/dbus
- name: lib-modules
mountPath: /lib/modules
resources:
requests:
cpu: 10m
- name: weave-npc
image: weaveworks/weave-npc:latest
imagePullPolicy: Always
resources:
requests:
cpu: 10m
securityContext:
privileged: true
restartPolicy: Always
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
serviceAccountName: weave-net
securityContext:
seLinuxOptions:
type: spc_t
volumes:
- name: weavedb
emptyDir: {}
- 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
hostPath:
path: /lib/modules
updateStrategy:
type: RollingUpdate
@@ -0,0 +1,199 @@
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
- apiGroups:
- 'networking.k8s.io'
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
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:
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
livenessProbe:
httpGet:
host: 127.0.0.1
path: /status
port: 6784
initialDelaySeconds: 30
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
#npc-args
resources:
requests:
cpu: 10m
securityContext:
privileged: true
volumeMounts:
- name: xtables-lock
mountPath: /run/xtables.lock
readOnly: false
hostNetwork: true
hostPID: true
restartPolicy: Always
securityContext:
seLinuxOptions: {}
serviceAccountName: weave-net
tolerations:
- effect: NoSchedule
operator: Exists
volumes:
- name: weavedb
hostPath:
path: /var/lib/weave
- name: cni-bin
hostPath:
path: /opt
- name: cni-bin2
hostPath:
path: /home
- name: cni-conf
hostPath:
path: /etc
- name: dbus
hostPath:
path: /var/lib/dbus
- name: lib-modules
hostPath:
path: /lib/modules
- name: xtables-lock
hostPath:
path: /run/xtables.lock
updateStrategy:
type: RollingUpdate
+90 -69
View File
@@ -1,80 +1,101 @@
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: weave-net
namespace: kube-system
spec:
template:
apiVersion: v1
kind: List
items:
- apiVersion: v1
kind: ServiceAccount
metadata:
name: weave-net
labels:
name: weave-net
annotations:
scheduler.alpha.kubernetes.io/tolerations: |
[
{
"key": "dedicated",
"operator": "Equal",
"value": "master",
"effect": "NoSchedule"
}
]
namespace: kube-system
- apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: weave-net
labels:
name: weave-net
namespace: kube-system
spec:
hostNetwork: true
hostPID: true
containers:
- name: weave
image: weaveworks/weave-kube:latest
imagePullPolicy: Always
command:
- /home/weave/launch.sh
livenessProbe:
initialDelaySeconds: 30
httpGet:
host: 127.0.0.1
path: /status
port: 6784
template:
metadata:
annotations:
scheduler.alpha.kubernetes.io/tolerations: >-
[{"key":"dedicated","operator":"Equal","value":"master","effect":"NoSchedule"}]
labels:
name: weave-net
spec:
containers:
- name: weave
command:
- /home/weave/launch.sh
env:
- name: HOSTNAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
image: 'weaveworks/weave-kube:latest'
imagePullPolicy: Always
livenessProbe:
httpGet:
host: 127.0.0.1
path: /status
port: 6784
initialDelaySeconds: 30
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:
privileged: true
volumeMounts:
seLinuxOptions: {}
serviceAccountName: weave-net
volumes:
- name: weavedb
mountPath: /weavedb
hostPath:
path: /var/lib/weave
- name: cni-bin
mountPath: /host/opt
hostPath:
path: /opt
- name: cni-bin2
mountPath: /host/home
hostPath:
path: /home
- name: cni-conf
mountPath: /host/etc
hostPath:
path: /etc
- name: dbus
mountPath: /host/var/lib/dbus
hostPath:
path: /var/lib/dbus
- name: lib-modules
mountPath: /lib/modules
resources:
requests:
cpu: 10m
- name: weave-npc
image: weaveworks/weave-npc:latest
imagePullPolicy: Always
resources:
requests:
cpu: 10m
securityContext:
privileged: true
restartPolicy: Always
volumes:
- name: weavedb
emptyDir: {}
- 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
hostPath:
path: /lib/modules
+43 -38
View File
@@ -7,12 +7,13 @@ import (
"github.com/coreos/go-iptables/iptables"
"github.com/spf13/cobra"
coreapi "k8s.io/api/core/v1"
extnapi "k8s.io/api/extensions/v1beta1"
networkingv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
coreapi "k8s.io/client-go/pkg/api/v1"
extnapi "k8s.io/client-go/pkg/apis/extensions/v1beta1"
"k8s.io/client-go/pkg/fields"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/util/wait"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/cache"
@@ -29,12 +30,13 @@ var (
logLevel string
allowMcast bool
nodeName string
legacy bool
)
func handleError(err error) { common.CheckFatal(err) }
func makeController(getter cache.Getter, resource string,
objType runtime.Object, handlers cache.ResourceEventHandlerFuncs) *cache.Controller {
objType runtime.Object, handlers cache.ResourceEventHandlerFuncs) cache.Controller {
listWatch := cache.NewListWatchFromClient(getter, resource, "", fields.Everything())
_, controller := cache.NewInformer(listWatch, objType, 0, handlers)
return controller
@@ -50,11 +52,7 @@ func resetIPTables(ipt *iptables.IPTables) error {
return err
}
if err := ipt.ClearChain(npc.TableFilter, npc.MainChain); err != nil {
return err
}
return nil
return ipt.ClearChain(npc.TableFilter, npc.MainChain)
}
func resetIPSets(ips ipset.Interface) error {
@@ -116,16 +114,13 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
if err := ips.Create(npc.LocalIpset, ipset.HashIP); err != nil {
return err
}
if err := ipt.Append(npc.TableFilter, npc.MainChain,
"-m", "set", "--match-set", npc.LocalIpset, "src",
"-m", "set", "!", "--match-set", npc.LocalIpset, "dst", "-j", "ACCEPT"); err != nil {
return err
}
return nil
return ipt.Append(npc.TableFilter, npc.MainChain,
"-m", "set", "!", "--match-set", npc.LocalIpset, "dst", "-j", "ACCEPT")
}
func root(cmd *cobra.Command, args []string) {
var npController cache.Controller
common.SetLogLevel(logLevel)
if nodeName == "" {
// HOSTNAME is set by Kubernetes for pods in the host network namespace
@@ -136,6 +131,10 @@ func root(cmd *cobra.Command, args []string) {
}
common.Log.Infof("Starting Weaveworks NPC %s; node name %q", version, nodeName)
if legacy {
common.Log.Info("Running in legacy mode (k8s pre-1.7 network policy semantics)")
}
if err := metrics.Start(metricsAddr); err != nil {
common.Log.Fatalf("Failed to start metrics: %v", err)
}
@@ -159,7 +158,7 @@ func root(cmd *cobra.Command, args []string) {
handleError(resetIPSets(ips))
handleError(createBaseRules(ipt, ips))
npc := npc.New(nodeName, ipt, ips)
npc := npc.New(nodeName, legacy, ipt, ips)
nsController := makeController(client.Core().RESTClient(), "namespaces", &coreapi.Namespace{},
cache.ResourceEventHandlerFuncs{
@@ -201,25 +200,30 @@ func root(cmd *cobra.Command, args []string) {
handleError(npc.UpdatePod(old.(*coreapi.Pod), new.(*coreapi.Pod)))
}})
npController := makeController(client.Extensions().RESTClient(), "networkpolicies", &extnapi.NetworkPolicy{},
cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
handleError(npc.AddNetworkPolicy(obj.(*extnapi.NetworkPolicy)))
},
DeleteFunc: func(obj interface{}) {
switch obj := obj.(type) {
case *extnapi.NetworkPolicy:
handleError(npc.DeleteNetworkPolicy(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.DeleteNetworkPolicy(obj.Obj.(*extnapi.NetworkPolicy)))
}
},
UpdateFunc: func(old, new interface{}) {
handleError(npc.UpdateNetworkPolicy(old.(*extnapi.NetworkPolicy), new.(*extnapi.NetworkPolicy)))
}})
npHandlers := cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
handleError(npc.AddNetworkPolicy(obj))
},
DeleteFunc: func(obj interface{}) {
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))
default:
handleError(npc.DeleteNetworkPolicy(obj))
}
},
UpdateFunc: func(old, new interface{}) {
handleError(npc.UpdateNetworkPolicy(old, new))
},
}
if legacy {
npController = makeController(client.Extensions().RESTClient(), "networkpolicies", &extnapi.NetworkPolicy{}, npHandlers)
} else {
npController = makeController(client.NetworkingV1().RESTClient(), "networkpolicies", &networkingv1.NetworkPolicy{}, npHandlers)
}
go nsController.Run(wait.NeverStop)
go podController.Run(wait.NeverStop)
@@ -240,6 +244,7 @@ func main() {
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "debug", "logging level (debug, info, warning, error)")
rootCmd.PersistentFlags().BoolVar(&allowMcast, "allow-mcast", true, "allow all multicast traffic")
rootCmd.PersistentFlags().StringVar(&nodeName, "node-name", "", "only generate rules that apply to this node")
rootCmd.PersistentFlags().BoolVar(&legacy, "use-legacy-netpol", false, "use legacy network policies (pre k8s 1.7 vsn)")
handleError(rootCmd.Execute())
}
+1
View File
@@ -1,6 +1,7 @@
# This is a nearly-empty image that we use to create a data-only container for persistence
FROM scratch
LABEL maintainer "Weaveworks Inc <help@weave.works>"
LABEL works.weave.role=system
ENTRYPOINT ["data-only"]
# Work round Docker refusing to save an empty image
COPY Dockerfile /
+3 -28
View File
@@ -1,34 +1,9 @@
FROM ALPINE_BASEIMAGE
FROM DOCKERHUB_USER/weaveARCH_EXT
# If we're building for another architecture than amd64, the CROSS_BUILD_ placeholder is removed so e.g. CROSS_BUILD_COPY turns into COPY
# If we're building normally, for amd64, CROSS_BUILD lines are removed
CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/
LABEL maintainer "Weaveworks Inc <help@weave.works>"
LABEL works.weave.role=system \
org.label-schema.name="Weave Net" \
org.label-schema.description="Weave Net creates a virtual network that connects Docker containers across multiple hosts and enables their automatic discovery" \
org.label-schema.url="https://weave.works" \
org.label-schema.vcs-url="https://github.com/weaveworks/weave" \
org.label-schema.vendor="Weaveworks"
WORKDIR /home/weave
ENTRYPOINT ["/home/weave/sigproxy", "/home/weave/weave"]
RUN apk add --update \
curl \
ethtool \
iptables \
ipset \
iproute2 \
util-linux \
conntrack-tools \
bind-tools \
&& rm -rf /var/cache/apk/*
ADD ./weave ./sigproxy ./weaveproxy ./symlink /home/weave/
ADD ./weaveutil /usr/bin/
ADD ./sigproxy ./symlink /home/weave/
ADD ./weavewait /w/w
ADD ./weavewait_noop /w-noop/w
ADD ./weavewait_nomcast /w-nomcast/w
ADD ./docker /usr/bin/
WORKDIR /home/weave
-84
View File
@@ -1,84 +0,0 @@
package main
import (
"fmt"
"os"
"strings"
"github.com/weaveworks/common/mflag"
"github.com/weaveworks/common/mflagext"
"github.com/weaveworks/common/signals"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/proxy"
)
var version = "unreleased"
var Log = common.Log
func getenv(key, defaultVal string) string {
if v := os.Getenv(key); v != "" {
return v
}
return defaultVal
}
func main() {
var (
justVersion bool
logLevel = "info"
c proxy.Config
withDNS bool
)
c.Version = version
mflag.BoolVar(&justVersion, []string{"#version", "-version"}, false, "print version and exit")
mflag.StringVar(&logLevel, []string{"-log-level"}, "info", "logging level (debug, info, warning, error)")
mflagext.ListVar(&c.ListenAddrs, []string{"H"}, nil, "addresses on which to listen")
mflag.StringVar(&c.HostnameFromLabel, []string{"-hostname-from-label"}, "", "Key of container label from which to obtain the container's hostname")
mflag.StringVar(&c.HostnameMatch, []string{"-hostname-match"}, "(.*)", "Regexp pattern to apply on container names (e.g. '^aws-[0-9]+-(.*)$')")
mflag.StringVar(&c.HostnameReplacement, []string{"-hostname-replacement"}, "$1", "Expression to generate hostnames based on matches from --hostname-match (e.g. 'my-app-$1')")
mflag.BoolVar(&c.RewriteInspect, []string{"-rewrite-inspect"}, false, "Rewrite 'inspect' calls to return the weave network settings (if attached)")
mflag.BoolVar(&c.NoDefaultIPAM, []string{"#-no-default-ipam", "-no-default-ipalloc"}, false, "do not automatically allocate addresses for containers without a WEAVE_CIDR")
mflag.BoolVar(&c.NoRewriteHosts, []string{"-no-rewrite-hosts"}, false, "do not automatically rewrite /etc/hosts. Use if you need the docker IP to remain in /etc/hosts")
mflag.StringVar(&c.TLSConfig.CACert, []string{"#tlscacert", "-tlscacert"}, "", "Trust certs signed only by this CA")
mflag.StringVar(&c.TLSConfig.Cert, []string{"#tlscert", "-tlscert"}, "", "Path to TLS certificate file")
mflag.BoolVar(&c.TLSConfig.Enabled, []string{"#tls", "-tls"}, false, "Use TLS; implied by --tlsverify")
mflag.StringVar(&c.TLSConfig.Key, []string{"#tlskey", "-tlskey"}, "", "Path to TLS key file")
mflag.BoolVar(&c.TLSConfig.Verify, []string{"#tlsverify", "-tlsverify"}, false, "Use TLS and verify the remote")
mflag.BoolVar(&withDNS, []string{"#-with-dns", "#w"}, false, "option removed")
mflag.BoolVar(&c.WithoutDNS, []string{"-without-dns"}, false, "instruct created containers to never use weaveDNS as their nameserver")
mflag.BoolVar(&c.NoMulticastRoute, []string{"-no-multicast-route"}, false, "do not add a multicast route via the weave interface when attaching containers")
mflag.Parse()
if justVersion {
fmt.Printf("weave proxy %s\n", version)
os.Exit(0)
}
common.SetLogLevel(logLevel)
Log.Infoln("weave proxy", version)
Log.Infoln("Command line arguments:", strings.Join(os.Args[1:], " "))
if withDNS {
Log.Warning("--with-dns option has been removed; DNS is on by default")
}
c.Image = getenv("EXEC_IMAGE", "weaveworks/weaveexec")
c.DockerBridge = getenv("DOCKER_BRIDGE", "docker0")
c.DockerHost = getenv("DOCKER_HOST", "unix:///var/run/docker.sock")
p, err := proxy.NewProxy(c)
if err != nil {
Log.Fatalf("Could not start proxy: %s", err)
}
defer p.Stop()
listeners := p.Listen()
p.AttachExistingContainers()
go p.Serve(listeners)
go p.ListenAndServeStatus("/home/weave/status.sock")
signals.SignalHandlerLoop(common.Log)
}
-12
View File
@@ -1,12 +0,0 @@
package main
import (
"testing"
weavetest "github.com/weaveworks/weave/testing"
)
func TestMain(t *testing.T) {
weavetest.TrimTestArgs()
main()
}
+28 -3
View File
@@ -1,6 +1,31 @@
FROM DOCKERHUB_USER/weaveexecARCH_EXT
WORKDIR /home/weave
ADD ./weaver /home/weave/
FROM ALPINE_BASEIMAGE
# If we're building for another architecture than amd64, the CROSS_BUILD_ placeholder is removed so e.g. CROSS_BUILD_COPY turns into COPY
# If we're building normally, for amd64, CROSS_BUILD lines are removed
CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/
LABEL maintainer "Weaveworks Inc <help@weave.works>"
LABEL works.weave.role=system \
org.label-schema.name="Weave Net" \
org.label-schema.description="Weave Net creates a virtual network that connects Docker containers across multiple hosts and enables their automatic discovery" \
org.label-schema.url="https://weave.works" \
org.label-schema.vcs-url="https://github.com/weaveworks/weave" \
org.label-schema.vendor="Weaveworks"
RUN apk add --update \
curl \
ethtool \
iptables \
ipset \
iproute2 \
util-linux \
conntrack-tools \
bind-tools \
&& rm -rf /var/cache/apk/*
ADD ./weave ./weaver /home/weave/
ADD ./weaveutil /usr/bin/
ADD weavedata.db /weavedb/
COPY ca-certificates.crt /etc/ssl/certs/
ENTRYPOINT ["/home/weave/weaver"]
WORKDIR /home/weave
+104
View File
@@ -0,0 +1,104 @@
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/weaveworks/weave/ipam"
)
// TODO: move these definitions somewhere more shareable
type PeerUpdateRequest struct {
Name string `json:"peername"`
Nickname string `json:"nickname"` // optional
Addresses []string `json:"addresses"` // can be empty
}
type PeerUpdateResponse struct {
Addresses []string `json:"addresses"`
PeerCount int `json:"peercount"`
}
var httpClient = &http.Client{Timeout: 30 * time.Second}
func do(verb string, discoveryEndpoint, token string, request interface{}, response interface{}) error {
body := new(bytes.Buffer)
err := json.NewEncoder(body).Encode(request)
if err != nil {
return err
}
req, err := http.NewRequest(verb, discoveryEndpoint+"/peer", body)
if err != nil {
return err
}
req.Header.Set("Authorization", fmt.Sprintf("Scope-Probe token=%s", token))
req.Header.Set("X-Weave-Net-Version", version)
req.Header.Set("Content-Type", "application/json")
Log.Printf("Calling peer discovery %s with %s", req.URL, request)
resp, err := httpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
rbody, _ := ioutil.ReadAll(resp.Body)
return errors.New(resp.Status + ": " + string(rbody))
}
if response == nil {
return nil
}
err = json.NewDecoder(resp.Body).Decode(response)
Log.Printf("peer discovery result: (%v) %v", err, response)
return err
}
func peerDiscoveryUpdate(discoveryEndpoint, token, peername, nickname string, addresses []string) ([]string, int, error) {
request := PeerUpdateRequest{
Name: peername,
Nickname: nickname,
Addresses: addresses,
}
var updateResponse PeerUpdateResponse
err := do("POST", discoveryEndpoint, token, request, &updateResponse)
return updateResponse.Addresses, updateResponse.PeerCount, err
}
func peerDiscoveryDelete(discoveryEndpoint, token, peername string) error {
request := PeerUpdateRequest{Name: peername}
return do("DELETE", discoveryEndpoint, token, request, nil)
}
func HandleHTTPPeer(router *mux.Router, alloc *ipam.Allocator, discoveryEndpoint, token, peername string) {
router.Methods("DELETE").Path("/peer").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if discoveryEndpoint != "" && token != "" {
if err := peerDiscoveryDelete(discoveryEndpoint, token, peername); err != nil {
Log.Errorf("Error while deleting self from peer discovery: %s", err)
}
}
if alloc != nil {
alloc.Shutdown()
}
w.WriteHeader(204)
})
router.Methods("DELETE").Path("/peer/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ident := mux.Vars(r)["id"]
if discoveryEndpoint != "" && token != "" {
// TODO: deal with this being either a peername or a nickname
if err := peerDiscoveryDelete(discoveryEndpoint, token, ident); err != nil {
Log.Errorf("Error while deleting self from peer discovery: %s", err)
}
}
if alloc != nil {
transferred := alloc.AdminTakeoverRanges(ident)
fmt.Fprintf(w, "%d IPs taken over from %s\n", transferred, ident)
}
})
}
+52 -21
View File
@@ -13,9 +13,12 @@ import (
"github.com/weaveworks/mesh"
"github.com/weaveworks/go-checkpoint"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/ipam"
"github.com/weaveworks/weave/nameserver"
"github.com/weaveworks/weave/net/address"
"github.com/weaveworks/weave/plugin"
"github.com/weaveworks/weave/proxy"
weave "github.com/weaveworks/weave/router"
)
@@ -31,23 +34,7 @@ var rootTemplate = template.New("root").Funcs(map[string]interface{}{
},
"printIPAMRanges": func(router weave.NetworkRouterStatus, status ipam.Status) string {
var buffer bytes.Buffer
type stats struct {
ips uint32
nickname string
reachable bool
}
peerStats := make(map[string]*stats)
for _, entry := range status.Entries {
s, found := peerStats[entry.Peer]
if !found {
s = &stats{nickname: entry.Nickname, reachable: entry.IsKnownPeer}
peerStats[entry.Peer] = s
}
s.ips += entry.Size
}
peerStats := summariseIpamStats(&status)
printOwned := func(name string, nickName string, info string, ips uint32) {
percentageRanges := float32(ips) * 100.0 / float32(status.RangeNumIPs)
@@ -113,6 +100,25 @@ var rootTemplate = template.New("root").Funcs(map[string]interface{}{
"trimSuffix": strings.TrimSuffix,
})
type ipamStats struct {
ips uint32
nickname string
reachable bool
}
func summariseIpamStats(status *ipam.Status) map[string]*ipamStats {
peerStats := make(map[string]*ipamStats)
for _, entry := range status.Entries {
s, found := peerStats[entry.Peer]
if !found {
s = &ipamStats{nickname: entry.Nickname, reachable: entry.IsKnownPeer}
peerStats[entry.Peer] = s
}
s.ips += entry.Size
}
return peerStats
}
func countDNSEntries(entries []nameserver.EntryStatus) int {
count := 0
for _, entry := range entries {
@@ -178,7 +184,7 @@ var statusTemplate = defTemplate("status", `\
{{if allIPAMOwnersUnreachable .IPAM}}\
Status: all IP ranges owned by unreachable peers - use 'rmpeer' if they are dead
{{else if len .IPAM.PendingAllocates}}\
Status: waiting for IP range grant from peers
Status: waiting for IP(s) to become available
{{else}}\
Status: ready
{{end}}\
@@ -202,6 +208,20 @@ var statusTemplate = defTemplate("status", `\
TTL: {{.DNS.TTL}}
Entries: {{countDNSEntries .DNS.Entries}}
{{end}}\
{{if .Proxy}}\
Service: proxy
Address: {{printList .Proxy.Addresses}}
{{end}}\
{{if .Plugin}}\
{{if .Plugin.Config.EnableV2}}\
Service: plugin (v2)
{{else}}\
Service: plugin (legacy)
DriverName: {{.Plugin.DriverName}}
{{end}}\
{{end}}\
`)
var targetsTemplate = defTemplate("targetsTemplate", `\
@@ -273,22 +293,29 @@ func (v *VersionCheck) String() string {
}
type WeaveStatus struct {
Ready bool
Version string
VersionCheck *VersionCheck `json:"VersionCheck,omitempty"`
Router *weave.NetworkRouterStatus `json:"Router,omitempty"`
IPAM *ipam.Status `json:"IPAM,omitempty"`
DNS *nameserver.Status `json:"DNS,omitempty"`
Proxy *proxy.Status `json:"Proxy,omitempty"`
Plugin *plugin.Status `json:"Plugin,omitempty"`
}
// Read-only functions, suitable for exposing on an unprotected socket
func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRouter, allocator *ipam.Allocator, defaultSubnet address.CIDR, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer) {
func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRouter, allocator *ipam.Allocator, defaultSubnet address.CIDR, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer, prxy *proxy.Proxy, plugin *plugin.Plugin, waitReady *common.WaitGroup) {
status := func() WeaveStatus {
return WeaveStatus{
waitReady.IsDone(),
version,
versionCheck(),
weave.NewNetworkRouterStatus(router),
ipam.NewStatus(allocator, defaultSubnet),
nameserver.NewStatus(ns, dnsserver)}
nameserver.NewStatus(ns, dnsserver),
proxy.NewStatus(prxy),
plugin.NewStatus(),
}
}
muxRouter.Methods("GET").Path("/report").Headers("Accept", "application/json").HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
@@ -324,7 +351,11 @@ func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRout
defHandler := func(path string, template *template.Template) {
muxRouter.Methods("GET").Path(path).HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
if err := template.Execute(w, status()); err != nil {
s := status()
if !s.Ready {
w.WriteHeader(http.StatusServiceUnavailable)
}
if err := template.Execute(w, s); err != nil {
http.Error(w, "error during template execution", http.StatusInternalServerError)
Log.Error(err)
}
+228 -80
View File
@@ -14,6 +14,7 @@ import (
"github.com/gorilla/mux"
"github.com/pkg/profile"
"github.com/weaveworks/common/mflag"
"github.com/weaveworks/common/mflagext"
"github.com/weaveworks/common/signals"
"github.com/weaveworks/mesh"
@@ -25,6 +26,8 @@ import (
"github.com/weaveworks/weave/nameserver"
weavenet "github.com/weaveworks/weave/net"
"github.com/weaveworks/weave/net/address"
"github.com/weaveworks/weave/plugin"
weaveproxy "github.com/weaveworks/weave/proxy"
weave "github.com/weaveworks/weave/router"
)
@@ -53,7 +56,7 @@ type dnsConfig struct {
func (c *ipamConfig) Enabled() bool {
var (
hasPeerCount = c.PeerCount > 0
hasMode = len(c.Mode) > 0
hasMode = c.HasMode()
hasRange = c.IPRangeCIDR != ""
hasSubnet = c.IPSubnetCIDR != ""
)
@@ -63,9 +66,7 @@ func (c *ipamConfig) Enabled() bool {
case !hasRange && hasSubnet:
Log.Fatal("--ipalloc-default-subnet specified without --ipalloc-range.")
case !hasRange:
Log.Fatal("--ipalloc-init or --init-peer-count specified without --ipalloc-range.")
case hasMode && hasPeerCount:
Log.Fatal("At most one of --ipalloc-init or --init-peer-count may be specified.")
Log.Fatal("--ipalloc-init specified without --ipalloc-range.")
}
if hasMode {
if err := c.parseMode(); err != nil {
@@ -75,6 +76,10 @@ func (c *ipamConfig) Enabled() bool {
return true
}
func (c ipamConfig) HasMode() bool {
return len(c.Mode) > 0
}
func (c *ipamConfig) parseMode() error {
modeAndParam := strings.SplitN(c.Mode, "=", 2)
@@ -108,6 +113,13 @@ func (c *ipamConfig) parseMode() error {
return nil
}
func getenvOrDefault(key, defaultVal string) string {
if v := os.Getenv(key); v != "" {
return v
}
return defaultVal
}
func main() {
procs := runtime.NumCPU()
// packet sniffing can block an OS thread, so we need one thread
@@ -119,16 +131,17 @@ func main() {
var (
justVersion bool
justPeerName bool
config mesh.Config
bridgeConfig weavenet.BridgeConfig
networkConfig weave.NetworkConfig
protocolMinVersion int
resume bool
ifaceName string
routerName string
nickName string
password string
pktdebug bool
logLevel string
logLevel = "info"
prof string
bufSzMB int
noDiscovery bool
@@ -139,40 +152,42 @@ func main() {
peers []string
noDNS bool
dnsConfig dnsConfig
datapathName string
trustedSubnetStr string
dbPrefix string
isAWSVPC bool
defaultDockerHost = "unix:///var/run/docker.sock"
hostRoot string
procPath string
discoveryEndpoint string
token string
advertiseAddress string
pluginConfig plugin.Config
defaultDockerHost = getenvOrDefault("DOCKER_HOST", "unix:///var/run/docker.sock")
)
if val := os.Getenv("DOCKER_HOST"); val != "" {
defaultDockerHost = val
}
mflag.BoolVar(&justVersion, []string{"#version", "-version"}, false, "print version and exit")
mflag.BoolVar(&justVersion, []string{"-version"}, false, "print version and exit")
mflag.BoolVar(&justPeerName, []string{"-print-peer-name"}, false, "print peer name and exit")
mflag.StringVar(&config.Host, []string{"-host"}, "", "router host")
mflag.IntVar(&config.Port, []string{"#port", "-port"}, mesh.Port, "router port")
mflag.IntVar(&config.Port, []string{"-port"}, mesh.Port, "router port")
mflag.IntVar(&protocolMinVersion, []string{"-min-protocol-version"}, mesh.ProtocolMinVersion, "minimum weave protocol version")
mflag.BoolVar(&resume, []string{"-resume"}, false, "resume connections to previous peers")
mflag.StringVar(&ifaceName, []string{"#iface", "-iface"}, "", "name of interface to capture/inject from (disabled if blank)")
mflag.StringVar(&routerName, []string{"#name", "-name"}, "", "name of router (defaults to MAC of interface)")
mflag.StringVar(&nickName, []string{"#nickname", "-nickname"}, "", "nickname of peer (defaults to hostname)")
mflag.StringVar(&password, []string{"#password", "-password"}, "", "network password")
mflag.StringVar(&bridgeConfig.WeaveBridgeName, []string{"-weave-bridge"}, "weave", "name of weave bridge")
mflag.StringVar(&bridgeConfig.DockerBridgeName, []string{"-docker-bridge"}, "", "name of Docker bridge")
mflag.BoolVar(&bridgeConfig.NPC, []string{"-expect-npc"}, false, "set up iptables rules for npc")
mflag.StringVar(&routerName, []string{"-name"}, "", "name of router (defaults to MAC of interface)")
mflag.StringVar(&nickName, []string{"-nickname"}, "", "nickname of peer (defaults to hostname)")
mflag.StringVar(&password, []string{"-password"}, "", "network password")
mflag.StringVar(&logLevel, []string{"-log-level"}, "info", "logging level (debug, info, warning, error)")
mflag.BoolVar(&pktdebug, []string{"#pktdebug", "#-pktdebug", "-pkt-debug"}, false, "enable per-packet debug logging")
mflag.StringVar(&prof, []string{"#profile", "-profile"}, "", "enable profiling and write profiles to given path")
mflag.IntVar(&config.ConnLimit, []string{"#connlimit", "#-connlimit", "-conn-limit"}, 30, "connection limit (0 for unlimited)")
mflag.BoolVar(&noDiscovery, []string{"#nodiscovery", "#-nodiscovery", "-no-discovery"}, false, "disable peer discovery")
mflag.IntVar(&bufSzMB, []string{"#bufsz", "-bufsz"}, 8, "capture buffer size in MB")
mflag.StringVar(&httpAddr, []string{"#httpaddr", "#-httpaddr", "-http-addr"}, "", "address to bind HTTP interface to (disabled if blank, absolute path indicates unix domain socket)")
mflag.BoolVar(&pktdebug, []string{"-pkt-debug"}, false, "enable per-packet debug logging")
mflag.StringVar(&prof, []string{"-profile"}, "", "enable profiling and write profiles to given path")
mflag.IntVar(&config.ConnLimit, []string{"-conn-limit"}, 30, "connection limit (0 for unlimited)")
mflag.BoolVar(&noDiscovery, []string{"-no-discovery"}, false, "disable peer discovery")
mflag.IntVar(&bufSzMB, []string{"-bufsz"}, 8, "capture buffer size in MB")
mflag.IntVar(&bridgeConfig.MTU, []string{"-mtu"}, 0, "MTU size")
mflag.StringVar(&httpAddr, []string{"-http-addr"}, "", "address to bind HTTP interface to (disabled if blank, absolute path indicates unix domain socket)")
mflag.StringVar(&statusAddr, []string{"-status-addr"}, "", "address to bind status+metrics interface to (disabled if blank, absolute path indicates unix domain socket)")
mflag.StringVar(&ipamConfig.Mode, []string{"-ipalloc-init"}, "", "allocator initialisation strategy (consensus, seed or observer)")
mflag.StringVar(&ipamConfig.IPRangeCIDR, []string{"#iprange", "#-iprange", "-ipalloc-range"}, "", "IP address range reserved for automatic allocation, in CIDR notation")
mflag.StringVar(&ipamConfig.IPSubnetCIDR, []string{"#ipsubnet", "#-ipsubnet", "-ipalloc-default-subnet"}, "", "subnet to allocate within by default, in CIDR notation")
mflag.IntVar(&ipamConfig.PeerCount, []string{"#initpeercount", "#-initpeercount", "-init-peer-count"}, 0, "number of peers in network (for IP address allocation)")
mflag.StringVar(&dockerAPI, []string{"#api", "#-api", "-docker-api"}, defaultDockerHost, "Docker API endpoint")
mflag.StringVar(&ipamConfig.IPRangeCIDR, []string{"-ipalloc-range"}, "", "IP address range reserved for automatic allocation, in CIDR notation")
mflag.StringVar(&ipamConfig.IPSubnetCIDR, []string{"-ipalloc-default-subnet"}, "", "subnet to allocate within by default, in CIDR notation")
mflag.StringVar(&dockerAPI, []string{"-docker-api"}, defaultDockerHost, "Docker API endpoint")
mflag.BoolVar(&noDNS, []string{"-no-dns"}, false, "disable DNS server")
mflag.StringVar(&dnsConfig.Domain, []string{"-dns-domain"}, nameserver.DefaultDomain, "local domain to server requests for")
mflag.StringVar(&dnsConfig.ListenAddress, []string{"-dns-listen-address"}, nameserver.DefaultListenAddress, "address to listen on for DNS requests")
@@ -180,10 +195,24 @@ func main() {
mflag.DurationVar(&dnsConfig.ClientTimeout, []string{"-dns-fallback-timeout"}, nameserver.DefaultClientTimeout, "timeout for fallback DNS requests")
mflag.StringVar(&dnsConfig.EffectiveListenAddress, []string{"-dns-effective-listen-address"}, "", "address DNS will actually be listening, after Docker port mapping")
mflag.StringVar(&dnsConfig.ResolvConf, []string{"-resolv-conf"}, "", "path to resolver configuration for fallback DNS lookups")
mflag.StringVar(&datapathName, []string{"-datapath"}, "", "ODP datapath name")
mflag.StringVar(&bridgeConfig.DatapathName, []string{"-datapath"}, "", "ODP datapath name")
mflag.BoolVar(&bridgeConfig.NoFastdp, []string{"-no-fastdp"}, false, "Disable Fast Datapath")
mflag.StringVar(&trustedSubnetStr, []string{"-trusted-subnets"}, "", "comma-separated list of trusted subnets in CIDR notation")
mflag.StringVar(&dbPrefix, []string{"-db-prefix"}, "/weavedb/weave", "pathname/prefix of filename to store data")
mflag.BoolVar(&isAWSVPC, []string{"-awsvpc"}, false, "use AWS VPC for routing")
mflag.StringVar(&procPath, []string{"-proc-path"}, "/proc", "path to reach host /proc filesystem")
mflag.BoolVar(&bridgeConfig.AWSVPC, []string{"-awsvpc"}, false, "use AWS VPC for routing")
mflag.StringVar(&hostRoot, []string{"-host-root"}, "", "path to reach host filesystem")
mflag.StringVar(&discoveryEndpoint, []string{"-peer-discovery-url"}, "https://cloud.weave.works/api/net", "url for peer discovery")
mflag.StringVar(&token, []string{"-token"}, "", "token for peer discovery")
mflag.StringVar(&advertiseAddress, []string{"-advertise-address"}, "", "address to advertise for peer discovery")
mflag.BoolVar(&pluginConfig.Enable, []string{"-plugin"}, false, "enable Docker plugin (v1)")
mflag.BoolVar(&pluginConfig.EnableV2, []string{"-plugin-v2"}, false, "enable Docker plugin (v2)")
mflag.BoolVar(&pluginConfig.EnableV2Multicast, []string{"-plugin-v2-multicast"}, false, "enable multicast for Docker plugin (v2)")
mflag.StringVar(&pluginConfig.Socket, []string{"-plugin-socket"}, "/run/docker/plugins/weave.sock", "plugin socket on which to listen")
mflag.StringVar(&pluginConfig.MeshSocket, []string{"-plugin-mesh-socket"}, "/run/docker/plugins/weavemesh.sock", "plugin socket on which to listen in mesh mode")
proxyConfig := newProxyConfig()
// crude way of detecting that we probably have been started in a
// container, with `weave launch` --> suppress misleading paths in
@@ -195,19 +224,30 @@ func main() {
mflag.Parse()
if justVersion {
fmt.Printf("weave %s\n", version)
os.Exit(0)
}
name := peerName(routerName, bridgeConfig.WeaveBridgeName, dbPrefix, hostRoot)
if justPeerName {
fmt.Printf("%s\n", name)
os.Exit(0)
}
proxyConfig.DockerHost = dockerAPI
if bridgeConfig.AWSVPC {
proxyConfig.NoMulticastRoute = true
proxyConfig.KeepTXOn = true
}
peers = mflag.Args()
if resume && len(peers) > 0 {
Log.Fatalf("You must not specify an initial peer list in conjunction with --resume")
}
common.SetLogLevel(logLevel)
if justVersion {
fmt.Printf("weave router %s\n", version)
os.Exit(0)
}
Log.Println("Command line options:", options())
Log.Infoln("weave ", version)
if prof != "" {
defer profile.Start(profile.CPUProfile, profile.ProfilePath(prof), profile.NoShutdownHook).Stop()
@@ -218,26 +258,57 @@ func main() {
}
config.ProtocolMinVersion = byte(protocolMinVersion)
var waitReady common.WaitGroup
var proxy *weaveproxy.Proxy
var err error
if proxyConfig.Enabled {
if noDNS {
proxyConfig.WithoutDNS = true
}
// Start Weave Proxy:
proxy, err = weaveproxy.NewProxy(*proxyConfig)
if err != nil {
Log.Fatalf("Could not start proxy: %s", err)
}
defer proxy.Stop()
listeners := proxy.Listen()
proxy.AttachExistingContainers()
go proxy.Serve(listeners, waitReady.Add())
}
if pktdebug {
networkConfig.PacketLogging = packetLogging{}
} else {
networkConfig.PacketLogging = nopPacketLogging{}
}
if bridgeConfig.DockerBridgeName != "" {
if setAddr, err := weavenet.EnforceAddrAssignType(bridgeConfig.DockerBridgeName); err != nil {
Log.Errorf("While checking address assignment type of %s: %s", bridgeConfig.DockerBridgeName, err)
} else if setAddr {
Log.Warningf("Setting %s MAC (mitigate https://github.com/docker/docker/issues/14908)", bridgeConfig.DockerBridgeName)
}
}
bridgeConfig.Mac = name.String()
bridgeConfig.Port = config.Port
bridgeType, err := weavenet.EnsureBridge(procPath, &bridgeConfig, Log)
checkFatal(err)
Log.Println("Bridge type is", bridgeType)
config.Password = determinePassword(password)
overlay, bridge := createOverlay(datapathName, ifaceName, isAWSVPC, config.Host, config.Port, bufSzMB, config.Password != nil)
networkConfig.Bridge = bridge
overlay, injectorConsumer := createOverlay(bridgeType, bridgeConfig, config.Host, config.Port, bufSzMB, config.Password != nil)
networkConfig.InjectorConsumer = injectorConsumer
if bridge != nil {
if injectorConsumer != nil {
if err := weavenet.DetectHairpin("vethwe-bridge", Log); err != nil {
Log.Errorf("Setting may cause connectivity issues : %s", err)
Log.Infof("Hairpin mode may have been enabled by other software on this machine")
}
}
name := peerName(routerName)
if nickName == "" {
var err error
nickName, err = os.Hostname()
@@ -247,19 +318,39 @@ func main() {
config.TrustedSubnets = parseTrustedSubnets(trustedSubnetStr)
config.PeerDiscovery = !noDiscovery
if isAWSVPC && len(config.Password) > 0 {
if bridgeConfig.AWSVPC && len(config.Password) > 0 {
Log.Fatalf("--awsvpc mode is not compatible with the --password option")
}
if bridgeConfig.AWSVPC && !ipamConfig.Enabled() {
Log.Fatalf("--awsvpc mode requires IPAM enabled")
}
db, err := db.NewBoltDB(dbPrefix + db.FileName)
db, err := db.NewBoltDB(dbPrefix)
checkFatal(err)
defer db.Close()
router, err := weave.NewNetworkRouter(config, networkConfig, name, nickName, overlay, db)
router, err := weave.NewNetworkRouter(config, networkConfig, bridgeConfig, name, nickName, overlay, db)
checkFatal(err)
Log.Println("Our name is", router.Ourself)
if peers, err = router.InitialPeers(resume, peers); err != nil {
if token != "" {
var addresses []string
if advertiseAddress == "" {
localAddrs, err := weavenet.LocalAddresses()
checkFatal(err)
for _, addr := range localAddrs {
addresses = append(addresses, addr.IP.String())
}
} else {
addresses = strings.Split(advertiseAddress, ",")
}
discoveredPeers, count, err := peerDiscoveryUpdate(discoveryEndpoint, token, name.String(), nickName, addresses)
checkFatal(err)
if !ipamConfig.HasMode() {
ipamConfig.PeerCount = len(peers) + count
}
peers = append(peers, discoveredPeers...)
} else if peers, err = router.InitialPeers(resume, peers); err != nil {
Log.Fatal("Unable to get initial peer set: ", err)
}
@@ -296,24 +387,26 @@ func main() {
)
if ipamConfig.Enabled() {
var t tracker.LocalRangeTracker
if isAWSVPC {
if bridgeConfig.AWSVPC {
Log.Infoln("Creating AWSVPC LocalRangeTracker")
t, err = tracker.NewAWSVPCTracker()
t, err = tracker.NewAWSVPCTracker(bridgeConfig.WeaveBridgeName)
if err != nil {
Log.Fatalf("Cannot create AWSVPC LocalRangeTracker: %s", err)
}
trackerName = "awsvpc"
}
var allContainerIDs []string
if dockerCli != nil {
allContainerIDs, err = dockerCli.AllContainerIDs()
checkFatal(err)
}
preClaims, err := findExistingAddresses(dockerCli, allContainerIDs, weavenet.WeaveBridgeName)
preClaims, err := findExistingAddresses(dockerCli, bridgeConfig.WeaveBridgeName)
checkFatal(err)
allocator, defaultSubnet = createAllocator(router, ipamConfig, preClaims, db, t, isKnownPeer)
observeContainers(allocator)
allocator.PruneOwned(allContainerIDs)
if dockerCli != nil {
allContainerIDs, err := dockerCli.RunningContainerIDs()
checkFatal(err)
allocator.PruneOwned(allContainerIDs)
}
}
var (
@@ -326,6 +419,9 @@ func main() {
ns.Start()
defer ns.Stop()
dnsserver.ActivateAndServe()
if dockerCli != nil {
populateDNS(ns, dockerCli, name, bridgeConfig.WeaveBridgeName)
}
defer dnsserver.Stop()
}
@@ -335,6 +431,10 @@ func main() {
}
checkFatal(router.CreateRestartSentinel())
pluginConfig.DNS = !noDNS
pluginConfig.DefaultSubnet = defaultSubnet.String()
plugin := plugin.NewPlugin(pluginConfig)
// 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.
@@ -347,8 +447,12 @@ func main() {
ns.HandleHTTP(muxRouter, dockerCli)
}
router.HandleHTTP(muxRouter)
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver)
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))
if proxy != nil {
muxRouter.Methods("GET").Path("/proxyaddrs").HandlerFunc(proxy.StatusHTTP)
}
http.Handle("/", common.LoggingHTTPHandler(muxRouter))
Log.Println("Listening for HTTP control messages on", httpAddr)
go listenAndServeHTTP(httpAddr, nil)
@@ -356,7 +460,7 @@ func main() {
if statusAddr != "" {
muxRouter := mux.NewRouter()
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver)
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, proxy, plugin, &waitReady)
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver))
statusMux := http.NewServeMux()
statusMux.Handle("/", muxRouter)
@@ -364,16 +468,37 @@ func main() {
go listenAndServeHTTP(statusAddr, statusMux)
}
if plugin != nil {
go plugin.Start(httpAddr, dockerCli, waitReady.Add())
}
if bridgeConfig.AWSVPC {
// Run this on its own goroutine because the allocator can block
// We remove the default route installed by the kernel,
// because awsvpc has installed it as well
go exposeForAWSVPC(allocator, defaultSubnet, bridgeConfig.WeaveBridgeName, waitReady.Add())
}
signals.SignalHandlerLoop(common.Log, router)
}
func exposeForAWSVPC(alloc *ipam.Allocator, subnet address.CIDR, bridgeName string, ready func()) {
addr, err := alloc.Allocate("weave:expose", subnet, false, func() bool { return false })
checkFatal(err)
cidr := address.MakeCIDR(subnet, addr)
err = weavenet.Expose(bridgeName, cidr.IPNet(), true, false)
checkFatal(err)
Log.Printf("Bridge %q exposed on address %v", bridgeName, cidr)
ready()
}
func options() map[string]string {
options := make(map[string]string)
mflag.Visit(func(f *mflag.Flag) {
value := f.Value.String()
name := canonicalName(f)
if name == "password" {
value = "<elided>"
if name == "password" || name == "token" {
value = "<redacted>"
}
options[name] = value
})
@@ -407,34 +532,55 @@ func (nopPacketLogging) LogPacket(string, weave.PacketKey) {
func (nopPacketLogging) LogForwardPacket(string, weave.ForwardPacketKey) {
}
func createOverlay(datapathName string, ifaceName string, isAWSVPC bool, host string, port int, bufSzMB int, enableEncryption bool) (weave.NetworkOverlay, weave.Bridge) {
func newProxyConfig() *weaveproxy.Config {
proxyConfig := weaveproxy.Config{
Image: getenvOrDefault("EXEC_IMAGE", "weaveworks/weaveexec"),
DockerBridge: getenvOrDefault("DOCKER_BRIDGE", "docker0"),
}
mflag.BoolVar(&proxyConfig.Enabled, []string{"-proxy"}, false, "instruct Weave Net to start its Docker proxy")
mflagext.ListVar(&proxyConfig.ListenAddrs, []string{"H"}, nil, "addresses on which to listen for Docker proxy")
mflag.StringVar(&proxyConfig.HostnameFromLabel, []string{"-hostname-from-label"}, "", "Key of container label from which to obtain the container's hostname")
mflag.StringVar(&proxyConfig.HostnameMatch, []string{"-hostname-match"}, "(.*)", "Regexp pattern to apply on container names (e.g. '^aws-[0-9]+-(.*)$')")
mflag.StringVar(&proxyConfig.HostnameReplacement, []string{"-hostname-replacement"}, "$1", "Expression to generate hostnames based on matches from --hostname-match (e.g. 'my-app-$1')")
mflag.BoolVar(&proxyConfig.RewriteInspect, []string{"-rewrite-inspect"}, false, "Rewrite 'inspect' calls to return the weave network settings (if attached)")
mflag.BoolVar(&proxyConfig.NoDefaultIPAM, []string{"-no-default-ipalloc"}, false, "proxy: do not automatically allocate addresses for containers without a WEAVE_CIDR")
mflag.BoolVar(&proxyConfig.NoRewriteHosts, []string{"-no-rewrite-hosts"}, false, "proxy: do not automatically rewrite /etc/hosts. Use if you need the docker IP to remain in /etc/hosts")
mflag.StringVar(&proxyConfig.TLSConfig.CACert, []string{"-tlscacert"}, "", "Trust certs signed only by this CA")
mflag.StringVar(&proxyConfig.TLSConfig.Cert, []string{"-tlscert"}, "", "Path to TLS certificate file")
mflag.BoolVar(&proxyConfig.TLSConfig.Enabled, []string{"-tls"}, false, "Use TLS; implied by --tlsverify")
mflag.StringVar(&proxyConfig.TLSConfig.Key, []string{"-tlskey"}, "", "Path to TLS key file")
mflag.BoolVar(&proxyConfig.TLSConfig.Verify, []string{"-tlsverify"}, false, "Use TLS and verify the remote")
mflag.BoolVar(&proxyConfig.WithoutDNS, []string{"-without-dns"}, false, "proxy: instruct created containers to never use weaveDNS as their nameserver")
mflag.BoolVar(&proxyConfig.NoMulticastRoute, []string{"-no-multicast-route"}, false, "proxy: do not add a multicast route via the weave interface when attaching containers")
return &proxyConfig
}
func createOverlay(bridgeType weavenet.Bridge, config weavenet.BridgeConfig, host string, port int, bufSzMB int, enableEncryption bool) (weave.NetworkOverlay, weave.InjectorConsumer) {
overlay := weave.NewOverlaySwitch()
var bridge weave.Bridge
var injectorConsumer weave.InjectorConsumer
var ignoreSleeve bool
switch {
case isAWSVPC:
case config.AWSVPC:
vpc := weave.NewAWSVPC()
overlay.Add("awsvpc", vpc)
bridge = weave.NullBridge{}
injectorConsumer = weave.NullInjectorConsumer{}
// Currently, we do not support any overlay with AWSVPC
ignoreSleeve = true
case datapathName != "" && ifaceName != "":
Log.Fatal("At most one of --datapath and --iface must be specified.")
case datapathName != "":
iface, err := weavenet.EnsureInterface(datapathName)
case bridgeType == nil:
injectorConsumer = weave.NullInjectorConsumer{}
case bridgeType.IsFastdp():
iface, err := weavenet.EnsureInterface(config.DatapathName)
checkFatal(err)
fastdp, err := weave.NewFastDatapath(iface, port, enableEncryption)
checkFatal(err)
bridge = fastdp.Bridge()
injectorConsumer = fastdp.InjectorConsumer()
overlay.Add("fastdp", fastdp.Overlay())
case ifaceName != "":
iface, err := weavenet.EnsureInterface(ifaceName)
case !bridgeType.IsFastdp():
iface, err := weavenet.EnsureInterface(weavenet.PcapIfName)
checkFatal(err)
bridge, err = weave.NewPcap(iface, bufSzMB*1024*1024) // bufsz flag is in MB
injectorConsumer, err = weave.NewPcap(iface, bufSzMB*1024*1024) // bufsz flag is in MB
checkFatal(err)
default:
bridge = weave.NullBridge{}
}
if !ignoreSleeve {
@@ -443,7 +589,7 @@ func createOverlay(datapathName string, ifaceName string, isAWSVPC bool, host st
overlay.SetCompatOverlay(sleeve)
}
return overlay, bridge
return overlay, injectorConsumer
}
func createAllocator(router *weave.NetworkRouter, config ipamConfig, preClaims []ipam.PreClaim, db db.DB, track tracker.LocalRangeTracker, isKnownPeer func(mesh.PeerName) bool) (*ipam.Allocator, address.CIDR) {
@@ -536,13 +682,15 @@ func determinePassword(password string) []byte {
return []byte(password)
}
func peerName(routerName string) mesh.PeerName {
func peerName(routerName, bridgeName, dbPrefix, hostRoot string) mesh.PeerName {
if routerName == "" {
iface, err := net.InterfaceByName(weavenet.WeaveBridgeName)
if err != nil {
Log.Fatalf("Unable to find bridge %q", weavenet.WeaveBridgeName)
iface, err := net.InterfaceByName(bridgeName)
if err == nil {
routerName = iface.HardwareAddr.String()
} else {
routerName, err = weavenet.GetSystemPeerName(dbPrefix, hostRoot)
checkFatal(err)
}
routerName = iface.HardwareAddr.String()
}
name, err := mesh.PeerNameFromUserInput(routerName)
checkFatal(err)
+3 -2
View File
@@ -7,6 +7,7 @@ import (
)
func TestMain(t *testing.T) {
weavetest.TrimTestArgs()
main()
if weavetest.TrimTestArgs() {
main()
}
}
+25 -4
View File
@@ -82,6 +82,27 @@ var metrics = []metric{
ch <- intGauge(desc, metrics.Flows)
}
}},
{desc("weave_ipam_unreachable_count", "Number of unreachable peers."),
func(s WeaveStatus, desc *prometheus.Desc, ch chan<- prometheus.Metric) {
var count int
for _, entry := range summariseIpamStats(s.IPAM) {
if !entry.reachable {
count++
}
}
ch <- intGauge(desc, count)
}},
{desc("weave_ipam_unreachable_percentage", "Percentage of IP addresses owned by unreachable peers."),
func(s WeaveStatus, desc *prometheus.Desc, ch chan<- prometheus.Metric) {
var totalUnreachable uint32
for _, entry := range summariseIpamStats(s.IPAM) {
if !entry.reachable {
totalUnreachable += entry.ips
}
}
percentage := float64(totalUnreachable) * 100.0 / float64(s.IPAM.RangeNumIPs)
ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, percentage)
}},
{desc("weave_ipam_pending_allocates", "Number of pending allocates."),
func(s WeaveStatus, desc *prometheus.Desc, ch chan<- prometheus.Metric) {
if s.IPAM != nil {
@@ -118,10 +139,10 @@ func newMetrics(router *weave.NetworkRouter, allocator *ipam.Allocator, ns *name
func (m *collector) Collect(ch chan<- prometheus.Metric) {
status := WeaveStatus{"", nil,
weave.NewNetworkRouterStatus(m.router),
ipam.NewStatus(m.allocator, address.CIDR{}),
nameserver.NewStatus(m.ns, m.dnsserver)}
status := WeaveStatus{
Router: weave.NewNetworkRouterStatus(m.router),
IPAM: ipam.NewStatus(m.allocator, address.CIDR{}),
DNS: nameserver.NewStatus(m.ns, m.dnsserver)}
for _, metric := range metrics {
metric.Collect(status, metric.Desc, ch)
+55 -1
View File
@@ -2,13 +2,16 @@ package main
import (
"net"
"strings"
docker "github.com/fsouza/go-dockerclient"
"github.com/weaveworks/mesh"
"github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
weavedocker "github.com/weaveworks/weave/common/docker"
"github.com/weaveworks/weave/ipam"
"github.com/weaveworks/weave/nameserver"
weavenet "github.com/weaveworks/weave/net"
"github.com/weaveworks/weave/net/address"
)
@@ -20,7 +23,7 @@ func a(cidr *net.IPNet) address.CIDR {
// Get all the existing Weave IPs at startup, so we can stop IPAM
// giving out any as duplicates
func findExistingAddresses(dockerCli *weavedocker.Client, containerIDs []string, bridgeName string) (addrs []ipam.PreClaim, err error) {
func findExistingAddresses(dockerCli *weavedocker.Client, bridgeName string) (addrs []ipam.PreClaim, err error) {
Log.Infof("Checking for pre-existing addresses on %s bridge", bridgeName)
// First get the address for the bridge
bridgeNetDev, err := weavenet.GetBridgeNetDev(bridgeName)
@@ -50,6 +53,11 @@ func findExistingAddresses(dockerCli *weavedocker.Client, containerIDs []string,
// Now iterate over all containers to see if they have a network
// namespace with an attached interface
if dockerCli != nil {
containerIDs, err := dockerCli.RunningContainerIDs()
if err != nil {
return nil, err
}
for _, cid := range containerIDs {
container, err := dockerCli.InspectContainer(cid)
if err != nil {
@@ -82,3 +90,49 @@ func findExistingAddresses(dockerCli *weavedocker.Client, containerIDs []string,
}
return addrs, nil
}
func populateDNS(ns *nameserver.Nameserver, dockerCli *weavedocker.Client, ourName mesh.PeerName, bridgeName string) (addrs []ipam.PreClaim, err error) {
// Find all veths connected to the bridge
peerIDs, err := weavenet.ConnectedToBridgeVethPeerIds(bridgeName)
if err != nil {
return nil, err
}
// Now iterate over all containers to see if they have a network
// namespace with an attached interface
if dockerCli != nil {
containerIDs, err := dockerCli.RunningContainerIDs()
if err != nil {
return nil, err
}
for _, cid := range containerIDs {
container, err := dockerCli.InspectContainer(cid)
if err != nil {
if _, ok := err.(*docker.NoSuchContainer); ok {
continue
}
return nil, err
}
if container.State.Pid != 0 {
// Docker allows containers to have fqdns in two wauys:
// where the container explicitly has a domain name, and when its
// hostname contains the domain name, recognized by it having dots.
if container.Config.Domainname == "" && !strings.Contains(container.Config.Hostname, ".") {
continue
}
netDevs, err := weavenet.GetNetDevsByVethPeerIds(container.State.Pid, peerIDs)
if err != nil {
return nil, err
}
fqdn := container.Config.Hostname + "." + container.Config.Domainname
for _, netDev := range netDevs {
for _, cidr := range netDev.CIDRs {
ns.AddEntryFQDN(fqdn, cid, ourName, address.FromIP4(cidr.IP))
}
}
}
}
}
return addrs, nil
}
+16 -1
View File
@@ -27,10 +27,25 @@ func containerAddrs(args []string) error {
return err
}
containerArgs := []string{}
for _, cid := range args[1:] {
if cid == "weave:allids" { // expand to all container IDs
all, err := client.ListContainers(docker.ListContainersOptions{})
if err != nil {
return err
}
for _, c := range all {
containerArgs = append(containerArgs, c.ID)
}
} else {
containerArgs = append(containerArgs, cid)
}
}
var containerIDs []string
containers := make(map[string]*docker.Container)
for _, cid := range args[1:] {
for _, cid := range containerArgs {
if cid == "weave:expose" {
netDev, err := weavenet.GetBridgeNetDev(bridgeName)
if err != nil {
+40 -16
View File
@@ -3,13 +3,15 @@ package main
import (
"fmt"
"net"
"os"
"strconv"
"strings"
"syscall"
docker "github.com/fsouza/go-dockerclient"
"github.com/vishvananda/netns"
weavenet "github.com/weaveworks/weave/net"
"github.com/weaveworks/weave/proxy"
)
func attach(args []string) error {
@@ -67,21 +69,6 @@ func attach(args []string) error {
return err
}
func containerPid(containerID string) (int, error) {
c, err := docker.NewVersionedClientFromEnv("1.18")
if err != nil {
return 0, fmt.Errorf("unable to connect to docker: %s", err)
}
container, err := c.InspectContainer(containerID)
if err != nil {
return 0, fmt.Errorf("unable to inspect container %s: %s", containerID, err)
}
if container.State.Pid == 0 {
return 0, fmt.Errorf("container %s not running", containerID)
}
return container.State.Pid, nil
}
func processExists(pid int) bool {
err := syscall.Kill(pid, syscall.Signal(0))
return err == nil || err == syscall.EPERM
@@ -114,3 +101,40 @@ func detach(args []string) error {
}
return weavenet.DetachContainer(weavenet.NSPathByPid(pid), args[0], weavenet.VethName, cidrs)
}
func rewriteEtcHosts(args []string) error {
if len(args) < 3 {
cmdUsage("rewrite-etc-hosts", "<container-id> <image> <cidr> [name:addr...]")
}
containerID := args[0]
image := args[1]
cidrs := args[2]
extraHosts := args[3:]
container, err := inspectContainer(containerID)
if err != nil {
return err
}
hostsPath := container.HostsPath
fqdn := container.Config.Hostname + "." + container.Config.Domainname
var ips []*net.IPNet
for _, cidr := range strings.Fields(cidrs) {
_, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
return err
}
ips = append(ips, ipnet)
}
docker := os.Getenv("DOCKER_HOST")
if docker == "" {
docker = "unix:///var/run/docker.sock"
}
p, err := proxy.StubProxy(proxy.Config{DockerHost: docker, Image: image})
if err != nil {
return err
}
return p.RewriteEtcHosts(hostsPath, fqdn, ips, extraHosts)
}
+57
View File
@@ -0,0 +1,57 @@
package main
import (
"fmt"
"strconv"
"github.com/weaveworks/weave/common"
weavenet "github.com/weaveworks/weave/net"
)
func detectBridgeType(args []string) error {
if len(args) != 2 {
cmdUsage("detect-bridge-type", "<weave-bridge-name> <datapath-name>")
}
bridgeType, err := weavenet.ExistingBridgeType(args[0], args[1])
if err != nil {
return err
} else if bridgeType == nil {
fmt.Println("none")
} else {
fmt.Println(bridgeType.String())
}
return nil
}
func createBridge(args []string) error {
if len(args) != 10 {
cmdUsage("create-bridge", "<docker-bridge-name> <weave-bridge-name> <datapath-name> <mtu> <port> <mac> <no-fastdp> <no-bridged-fastdp> <proc-path> <expect-npc>")
}
mtu, err := strconv.Atoi(args[3])
if err != nil && args[3] != "" {
return err
}
port, err := strconv.Atoi(args[4])
if err != nil {
return err
}
config := weavenet.BridgeConfig{
DockerBridgeName: args[0],
WeaveBridgeName: args[1],
DatapathName: args[2],
MTU: mtu,
Port: port,
Mac: args[5],
NoFastdp: args[6] != "",
NoBridgedFastdp: args[7] != "",
NPC: args[9] == "--expect-npc",
}
procPath := args[8]
bridgeType, err := weavenet.EnsureBridge(procPath, &config, common.Log)
if err != nil {
return err
}
fmt.Println(bridgeType.String())
return nil
}
+285
View File
@@ -0,0 +1,285 @@
package main
import (
"fmt"
"os"
"strings"
docker "github.com/fsouza/go-dockerclient"
)
func inspectContainer(containerNameOrID string) (*docker.Container, error) {
c, err := docker.NewVersionedClientFromEnv("1.18")
if err != nil {
return nil, fmt.Errorf("unable to connect to docker: %s", err)
}
container, err := c.InspectContainer(containerNameOrID)
if err != nil {
return nil, fmt.Errorf("unable to inspect container %s: %s", containerNameOrID, err)
}
return container, nil
}
func containerPid(containerID string) (int, error) {
container, err := inspectContainer(containerID)
if err != nil {
return 0, err
}
if container.State.Pid == 0 {
return 0, fmt.Errorf("container %s not running", containerID)
}
return container.State.Pid, nil
}
func containerID(args []string) error {
if len(args) < 1 {
cmdUsage("container-id", "<container-name-or-short-id>")
}
container, err := inspectContainer(args[0])
if err != nil {
return err
}
fmt.Print(container.ID)
return nil
}
func containerState(args []string) error {
if len(args) < 1 {
cmdUsage("container-state", "<container-id> [<image-prefix>]")
}
container, err := inspectContainer(args[0])
if err != nil {
return err
}
if len(args) == 1 {
fmt.Print(container.State.StateString())
} else {
imagePrefix := args[1]
if strings.HasPrefix(container.Config.Image, imagePrefix) {
fmt.Print(container.State.StateString())
} else {
if container.State.Running {
fmt.Print("running image mismatch: ", container.Config.Image)
} else {
fmt.Print("image mismatch: ", container.Config.Image)
}
}
}
return nil
}
func containerFQDN(args []string) error {
if len(args) < 1 {
cmdUsage("container-fqdn", "<container-id>")
}
container, err := inspectContainer(args[0])
if err != nil {
return err
}
fmt.Print(container.Config.Hostname, ".", container.Config.Domainname)
return nil
}
func runContainer(args []string) error {
env := []string{}
name := ""
net := ""
pid := ""
privileged := false
restart := docker.NeverRestart()
volumes := []string{}
volumesFrom := []string{}
done := false
for i := 0; i < len(args) && !done; {
switch args[i] {
case "-e", "--env":
if v := os.Getenv(args[i+1]); v != "" {
env = append(env, args[i+1]+"="+v)
} else {
env = append(env, args[i+1])
}
args = append(args[:i], args[i+2:]...)
case "--name":
name = args[i+1]
args = append(args[:i], args[i+2:]...)
case "--net":
net = args[i+1]
args = append(args[:i], args[i+2:]...)
case "--pid":
pid = args[i+1]
args = append(args[:i], args[i+2:]...)
case "--privileged":
privileged = true
args = append(args[:i], args[i+1:]...)
case "--restart":
restart = docker.RestartPolicy{Name: args[i+1]}
args = append(args[:i], args[i+2:]...)
case "-v", "--volume":
// Must dedup binds, otherwise, container fails creation
skip := false
for _, v := range volumes {
if v == args[i+1] {
skip = true
}
}
if !skip {
volumes = append(volumes, args[i+1])
}
args = append(args[:i], args[i+2:]...)
case "--volumes-from":
volumesFrom = append(volumesFrom, args[i+1])
args = append(args[:i], args[i+2:]...)
default:
done = true
}
}
if len(args) < 2 {
cmdUsage("run-container", `[options] <image> <cmd> [[<cmd-options>] <cmd-arg1> [<cmd-arg2> ...]]
-e, --env list Set environment variables
--name string Assign a name to the container
--net string Network Mode
--pid string PID namespace to use
--privileged Give extended privileges to this container
--restart string Restart policy to apply when a container exits (default "no")
-v, --volume list Bind mount a volume
--volumes-from list Mount volumes from the specified container(s)
`)
}
image := args[0]
cmds := args[1:]
c, err := docker.NewVersionedClientFromEnv("1.18")
if err != nil {
return fmt.Errorf("unable to connect to docker: %s", err)
}
config := docker.Config{Image: image, Env: env, Cmd: cmds}
hostConfig := docker.HostConfig{NetworkMode: net, PidMode: pid, Privileged: privileged, RestartPolicy: restart, Binds: volumes, VolumesFrom: volumesFrom}
container, err := c.CreateContainer(docker.CreateContainerOptions{Name: name, Config: &config, HostConfig: &hostConfig})
if err != nil {
return fmt.Errorf("unable to create container: %s", err)
}
err = c.StartContainer(container.ID, &hostConfig)
if err != nil {
return fmt.Errorf("unable to start container: %s", err)
}
fmt.Print(container.ID)
return nil
}
func listContainers(args []string) error {
if len(args) > 1 {
cmdUsage("list-containers", "[<label>]")
}
c, err := docker.NewVersionedClientFromEnv("1.18")
if err != nil {
return fmt.Errorf("unable to connect to docker: %s", err)
}
opts := docker.ListContainersOptions{All: true}
if len(args) == 1 {
label := args[0]
opts.Filters = map[string][]string{"label": {label}}
}
containers, err := c.ListContainers(opts)
if err != nil {
return fmt.Errorf("unable to list containers: %s", err)
}
for _, container := range containers {
fmt.Println(container.ID)
}
return nil
}
func stopContainer(args []string) error {
if len(args) < 1 {
cmdUsage("stop-container", "<container-id> [<container-id2> ...]")
}
c, err := docker.NewVersionedClientFromEnv("1.18")
if err != nil {
return fmt.Errorf("unable to connect to docker: %s", err)
}
for _, containerID := range args {
err = c.StopContainer(containerID, 10)
if err != nil {
return fmt.Errorf("unable to stop container %s: %s", containerID, err)
}
}
return nil
}
func killContainer(args []string) error {
if len(args) < 1 {
cmdUsage("kill-container", "<container-id> [<container-id2> ...]")
}
c, err := docker.NewVersionedClientFromEnv("1.18")
if err != nil {
return fmt.Errorf("unable to connect to docker: %s", err)
}
for _, containerID := range args {
err = c.KillContainer(docker.KillContainerOptions{ID: containerID, Signal: docker.SIGKILL})
if err != nil {
return fmt.Errorf("unable to stop container %s: %s", containerID, err)
}
}
return nil
}
func removeContainer(args []string) error {
if len(args) < 1 {
cmdUsage("remove-container", "[-f | --force] [-v | --volumes] <container-id> [<container-id2> ...]")
}
force := false
volumes := false
for i := 0; i < len(args); {
switch args[i] {
case "--force":
case "-f":
force = true
args = append(args[:i], args[i+1:]...)
case "--volumes":
case "-v":
volumes = true
args = append(args[:i], args[i+1:]...)
default:
i++
}
}
c, err := docker.NewVersionedClientFromEnv("1.18")
if err != nil {
return fmt.Errorf("unable to connect to docker: %s", err)
}
for _, containerID := range args {
err = c.RemoveContainer(docker.RemoveContainerOptions{
ID: containerID, Force: force, RemoveVolumes: volumes})
if err != nil {
return fmt.Errorf("unable to stop container %s: %s", containerID, err)
}
}
return nil
}
+54
View File
@@ -0,0 +1,54 @@
// Get/set arbitrary flags in the Weave Net persistence DB
package main
import (
"fmt"
"github.com/weaveworks/weave/db"
)
const dbFlagPrefix = "flag:"
func getDBFlag(args []string) error {
if len(args) != 2 {
cmdUsage("check-db-flag", "<db-prefix> <flag-name>")
}
dbPrefix := args[0]
flagName := args[1]
d, err := db.NewBoltDBReadOnly(dbPrefix)
if err != nil {
return err
}
defer d.Close()
var value string
nameFound, err := d.Load(dbFlagPrefix+flagName, &value)
if err != nil {
return err
}
if !nameFound {
return fmt.Errorf("")
}
fmt.Print(value)
return nil
}
func setDBFlag(args []string) error {
if len(args) != 3 {
cmdUsage("set-db-flag", "<db-prefix> <flag-name> <flag-value>")
}
dbPrefix := args[0]
flagName := args[1]
value := args[2]
d, err := db.NewBoltDB(dbPrefix)
if err != nil {
return err
}
defer d.Close()
err = d.Save(dbFlagPrefix+flagName, value)
if err != nil {
return err
}
return nil
}
-23
View File
@@ -1,23 +0,0 @@
package main
import (
weavenet "github.com/weaveworks/weave/net"
)
func exposeNAT(args []string) error {
if len(args) < 1 {
cmdUsage("expose-nat", "<cidr>...")
}
cidrs, err := parseCIDRs(args)
if err != nil {
return err
}
for _, cidr := range cidrs {
if err := weavenet.ExposeNAT(*cidr); err != nil {
return err
}
}
return nil
}
+42 -24
View File
@@ -14,29 +14,44 @@ var commands map[string]func([]string) error
func init() {
commands = map[string]func([]string) error{
"help": help,
"netcheck": netcheck,
"docker-tls-args": dockerTLSArgs,
"create-datapath": createDatapath,
"delete-datapath": deleteDatapath,
"check-datapath": checkDatapath,
"add-datapath-interface": addDatapathInterface,
"create-plugin-network": createPluginNetwork,
"remove-plugin-network": removePluginNetwork,
"container-addrs": containerAddrs,
"process-addrs": processAddrs,
"attach-container": attach,
"detach-container": detach,
"configure-arp": configureARP,
"check-iface": checkIface,
"del-iface": delIface,
"setup-iface": setupIface,
"list-netdevs": listNetDevs,
"cni-net": cniNet,
"cni-ipam": cniIPAM,
"expose-nat": exposeNAT,
"bridge-ip": bridgeIP,
"unique-id": uniqueID,
"help": help,
"netcheck": netcheck,
"docker-tls-args": dockerTLSArgs,
"create-bridge": createBridge,
"detect-bridge-type": detectBridgeType,
"create-datapath": createDatapath,
"delete-datapath": deleteDatapath,
"check-datapath": checkDatapath,
"add-datapath-interface": addDatapathInterface,
"remove-plugin-network": removePluginNetwork,
"container-addrs": containerAddrs,
"process-addrs": processAddrs,
"container-id": containerID,
"container-state": containerState,
"container-fqdn": containerFQDN,
"run-container": runContainer,
"list-containers": listContainers,
"stop-container": stopContainer,
"kill-container": killContainer,
"remove-container": removeContainer,
"create-volume-container": createVolumeContainer,
"attach-container": attach,
"detach-container": detach,
"configure-arp": configureARP,
"check-iface": checkIface,
"del-iface": delIface,
"setup-iface": setupIface,
"setup-iface-addrs": setupIfaceAddrs,
"list-netdevs": listNetDevs,
"cni-net": cniNet,
"cni-ipam": cniIPAM,
"bridge-ip": bridgeIP,
"unique-id": uniqueID,
"swarm-manager-peers": swarmManagerPeers,
"is-docker-plugin-enabled": isDockerPluginEnabled,
"rewrite-etc-hosts": rewriteEtcHosts,
"get-db-flag": getDBFlag,
"set-db-flag": setDBFlag,
}
}
@@ -65,11 +80,14 @@ func main() {
}
cmd, found := commands[os.Args[1]]
if !found {
fmt.Fprintf(os.Stderr, "%q cmd is not found\n", os.Args[1])
usage()
os.Exit(1)
}
if err := cmd(os.Args[2:]); err != nil {
fmt.Fprintln(os.Stderr, err)
if err.Error() != "" {
fmt.Fprintln(os.Stderr, err)
}
os.Exit(1)
}
}
+17 -16
View File
@@ -6,7 +6,6 @@ import (
"strconv"
"strings"
"github.com/coreos/go-iptables/iptables"
"github.com/j-keck/arping"
"github.com/vishvananda/netlink"
@@ -48,33 +47,35 @@ func setupIface(args []string) error {
ifaceName := args[0]
newIfName := args[1]
ipt, err := iptables.New()
return weavenet.SetupIface(ifaceName, newIfName)
}
// setupIfaceAddrs sets up addresses on an interface. It expects to be called inside the container's netns.
func setupIfaceAddrs(args []string) error {
if len(args) < 1 {
cmdUsage("setup-iface-addrs", "<iface-name> <with-multicast> <cidr>...")
}
link, err := netlink.LinkByName(args[0])
if err != nil {
return err
}
link, err := netlink.LinkByName(ifaceName)
withMulticastRoute, err := strconv.ParseBool(args[1])
if err != nil {
return err
}
if err := netlink.LinkSetName(link, newIfName); err != nil {
cidrs, err := parseCIDRs(args[2:])
if err != nil {
return err
}
if err := weavenet.ConfigureARPCache(newIfName); err != nil {
return err
}
if err := ipt.Append("filter", "INPUT", "-i", newIfName, "-d", "224.0.0.0/4", "-j", "DROP"); err != nil {
return err
}
return nil
return weavenet.SetupIfaceAddrs(link, withMulticastRoute, cidrs)
}
func configureARP(args []string) error {
if len(args) != 1 {
cmdUsage("configure-arp", "<iface-name-prefix>")
if len(args) != 2 {
cmdUsage("configure-arp", "<iface-name-prefix> <root-path>")
}
prefix := args[0]
rootPath := args[1]
links, err := netlink.LinkList()
if err != nil {
@@ -83,7 +84,7 @@ func configureARP(args []string) error {
for _, link := range links {
ifName := link.Attrs().Name
if strings.HasPrefix(ifName, prefix) {
weavenet.ConfigureARPCache(ifName)
weavenet.ConfigureARPCache(rootPath+"/proc", ifName)
if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil {
for _, addr := range addrs {
arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName)
+39 -36
View File
@@ -2,47 +2,14 @@
package main
import (
"context"
"fmt"
"strings"
"github.com/docker/docker/client"
docker "github.com/fsouza/go-dockerclient"
"github.com/weaveworks/weave/plugin/net"
)
func createPluginNetwork(args []string) error {
if len(args) != 3 {
cmdUsage("create-plugin-network", "<network-name> <driver-name> <default-subnet>")
}
networkName := args[0]
driverName := args[1]
subnet := args[2]
d, err := newDockerClient()
if err != nil {
return err
}
_, err = d.CreateNetwork(
docker.CreateNetworkOptions{
Name: networkName,
CheckDuplicate: true,
Driver: driverName,
IPAM: docker.IPAMOptions{
Driver: driverName,
Config: []docker.IPAMConfig{{Subnet: subnet}},
},
Options: map[string]interface{}{plugin.MulticastOption: "true"},
})
if err != docker.ErrNetworkAlreadyExists && err != nil {
// Despite appearances to the contrary, CreateNetwork does
// sometimes(always?) *not* return ErrNetworkAlreadyExists
// when the network already exists. Hence we need to check for
// this explicitly.
if _, err2 := d.NetworkInfo(networkName); err2 != nil {
return fmt.Errorf("unable to create network: %s", err)
}
}
return nil
}
func removePluginNetwork(args []string) error {
if len(args) != 1 {
cmdUsage("remove-plugin-network", "<network-name>")
@@ -71,6 +38,41 @@ while Weave is not running`, networkName, containers)
return nil
}
// Exits with 0 if the given plugin (v2) is enabled.
//
// Any failure due to missing plugin support is non-harmful as plugin (v2)
// cannot be enabled when Docker does not support it.
func isDockerPluginEnabled(args []string) error {
if len(args) != 1 {
cmdUsage("is-docker-plugin-enabled", "<plugin-name>")
}
pluginName := args[0]
// This is messed up: we are using docker/docker/client instead of
// fsouza/go-dockerclient because the latter does not support plugins.
c, err := client.NewEnvClient()
if err != nil {
return fmt.Errorf("unable to connect to docker: %s", err)
}
ctx := context.Background()
plugins, err := c.PluginList(ctx)
if err != nil {
return err
}
for _, p := range plugins {
if p.Enabled && strings.Contains(p.Name, pluginName) {
fmt.Println(p.Name)
return nil
}
}
return fmt.Errorf("plugin %q not found", pluginName)
}
func newDockerClient() (*docker.Client, error) {
// API 1.21 is the first version that supports docker network
// commands
@@ -82,5 +84,6 @@ func newDockerClient() (*docker.Client, error) {
if err != nil {
return nil, fmt.Errorf("unable to connect to docker: %s", err)
}
return c, nil
}
+55
View File
@@ -0,0 +1,55 @@
package main
import (
"fmt"
"strings"
"github.com/fsouza/go-dockerclient"
"github.com/pkg/errors"
)
const DOCKER_API_VERSION = "1.26"
func swarmManagerPeers(args []string) error {
info, err := dockerInfo()
if err != nil {
return err
}
ips := make([]string, 0)
for _, managerNode := range info.Swarm.RemoteManagers {
ip, err := ipFromAddr(managerNode.Addr)
if err != nil {
return errors.Wrap(err, "ipFromAddr")
}
ips = append(ips, ip)
}
fmt.Println(strings.Join(ips, " "))
return nil
}
func dockerInfo() (*docker.DockerInfo, error) {
client, err := docker.NewVersionedClientFromEnv(DOCKER_API_VERSION)
if err != nil {
return nil, errors.Wrap(err, "docker.NewVersionedClientFromEnv")
}
info, err := client.Info()
if err != nil {
return nil, errors.Wrap(err, "docker.Info")
}
return info, nil
}
func ipFromAddr(addr string) (string, error) {
parts := strings.Split(addr, ":")
if len(parts) != 2 {
return "", fmt.Errorf("invalid address: %q", addr)
}
return parts[0], nil
}
+42
View File
@@ -0,0 +1,42 @@
package main
import (
"fmt"
docker "github.com/fsouza/go-dockerclient"
)
func createVolumeContainer(args []string) error {
if len(args) < 3 {
cmdUsage("create-volume-container", "<name> <image-name-or-id> <label> [<bind-mount1> <bind-mount2> ...]")
}
containerName := args[0]
image := args[1]
label := args[2]
bindMounts := args[3:]
c, err := docker.NewVersionedClientFromEnv("1.18")
if err != nil {
return fmt.Errorf("unable to connect to docker: %s", err)
}
container, err := c.InspectContainer(containerName)
if err == nil {
fmt.Println("volume container already exists " + containerName + ":" + container.ID)
return nil
}
volumes := make(map[string]struct{})
for _, m := range bindMounts {
volumes[m] = struct{}{}
}
labels := map[string]string{label: ""}
config := docker.Config{Image: image, Volumes: volumes, Labels: labels, Entrypoint: []string{"data-only"}}
hostConfig := docker.HostConfig{}
_, err = c.CreateContainer(docker.CreateContainerOptions{Name: containerName, Config: &config, HostConfig: &hostConfig})
if err != nil {
return fmt.Errorf("unable to create container: %s", err)
}
return nil
}
+2 -36
View File
@@ -6,13 +6,12 @@ import (
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"regexp"
"strings"
"github.com/fsouza/go-dockerclient"
"github.com/weaveworks/weave/common"
weavedocker "github.com/weaveworks/weave/common/docker"
)
var (
@@ -24,39 +23,6 @@ var (
Log = common.Log
)
func callWeave(args ...string) ([]byte, []byte, error) {
args = append([]string{"--local"}, args...)
cmd := exec.Command("./weave", args...)
cmd.Env = []string{
"PATH=/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
}
propagateEnv := func(key string) {
if val := os.Getenv(key); val != "" {
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, val))
}
}
propagateEnv("DOCKER_HOST")
// Propagate WEAVE_DEBUG, to make debugging easier.
propagateEnv("WEAVE_DEBUG")
// This prevents the code coverage contortions in our
// integration test suite breaking things.
propagateEnv("COVERAGE")
// In case the router control endpoint address is non-standard.
propagateEnv("WEAVE_HTTP_ADDR")
Log.Debug("Calling weave args: ", args, "env: ", cmd.Env)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
return stdout.Bytes(), stderr.Bytes(), err
}
func unmarshalRequestBody(r *http.Request, target interface{}) error {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
@@ -113,7 +79,7 @@ func marshalResponseBody(r *http.Response, body interface{}) error {
return nil
}
func inspectContainerInPath(client *docker.Client, path string) (*docker.Container, error) {
func inspectContainerInPath(client *weavedocker.Client, path string) (*docker.Container, error) {
subs := containerIDRegexp.FindStringSubmatch(path)
if subs == nil {
err := fmt.Errorf("No container id found in request with path %s", path)
+64
View File
@@ -0,0 +1,64 @@
package proxy
import (
"bytes"
"fmt"
"io"
"net"
"path"
"strings"
)
// rewrite /etc/hosts, unlinking the file (so Docker does not modify it again) but
// leaving it with valid contents...
func (proxy *Proxy) RewriteEtcHosts(hostsPath, fqdn string, ips []*net.IPNet, extraHosts []string) error {
hostsPathDir := path.Dir(hostsPath)
mnt := "/container"
mntHosts := path.Join(mnt, path.Base(hostsPath))
var buf bytes.Buffer
writeEtcHostsContents(&buf, fqdn, ips, extraHosts)
contents := buf.String()
cmdLine := fmt.Sprintf("echo '%s' > %s && rm -f %s && echo '%s' > %s", contents, mntHosts, mntHosts, contents, mntHosts)
mounts := []string{hostsPathDir + ":" + mnt}
return proxy.runTransientContainer([]string{"sh"}, []string{"-c", cmdLine}, mounts)
}
// we assume (for compatibility with the weave script) that fqdn has a dot
// between hostname and domain. domain may be blank.
func writeEtcHostsContents(w io.Writer, fqdn string, cidrs []*net.IPNet, extraHosts []string) {
index := strings.Index(fqdn, ".")
name := fqdn[:index]
var hostnames string
if index == len(fqdn)-1 { // dot comes at the end - no domain
hostnames = name
} else {
if fqdn[len(fqdn)-1] == '.' { // strip a final trailing dot
fqdn = fqdn[:len(fqdn)-1]
}
hostnames = fqdn + " " + name
}
fmt.Fprintln(w, "# created by Weave - BEGIN")
fmt.Fprintln(w, "# container hostname")
for _, cidr := range cidrs {
fmt.Fprintf(w, "%-15s %s\n", cidr.IP, hostnames)
}
fmt.Fprintln(w)
fmt.Fprintln(w, "# static names added with --add-host")
for _, eh := range extraHosts {
parts := strings.SplitN(eh, ":", 2)
if len(parts) != 2 {
continue
}
fmt.Fprintf(w, "%-15s %s\n", parts[1], parts[0])
}
fmt.Fprintln(w)
fmt.Fprintln(w, "# default localhost entries")
fmt.Fprintln(w, "127.0.0.1 localhost")
fmt.Fprintln(w, "::1 ip6-localhost ip6-loopback")
fmt.Fprintln(w, "fe00::0 ip6-localnet")
fmt.Fprintln(w, "ff00::0 ip6-mcastprefix")
fmt.Fprintln(w, "ff02::1 ip6-allnodes")
fmt.Fprintln(w, "ff02::2 ip6-allrouters")
fmt.Fprintln(w, "# created by Weave - END")
}
+98 -77
View File
@@ -3,7 +3,6 @@ package proxy
import (
"bytes"
"crypto/tls"
"errors"
"fmt"
"net"
"net/http"
@@ -16,10 +15,11 @@ import (
"time"
docker "github.com/fsouza/go-dockerclient"
"github.com/pkg/errors"
weaveapi "github.com/weaveworks/weave/api"
weavedocker "github.com/weaveworks/weave/common/docker"
weavenet "github.com/weaveworks/weave/net"
"github.com/weaveworks/weave/net/address"
)
const (
@@ -50,6 +50,7 @@ func dockerAPIEndpoint(endpoint string) *regexp.Regexp {
}
type Config struct {
Enabled bool
HostnameFromLabel string
HostnameMatch string
HostnameReplacement string
@@ -59,9 +60,9 @@ type Config struct {
NoDefaultIPAM bool
NoRewriteHosts bool
TLSConfig TLSConfig
Version string
WithoutDNS bool
NoMulticastRoute bool
KeepTXOn bool
DockerBridge string
DockerHost string
}
@@ -75,7 +76,8 @@ type wait struct {
type Proxy struct {
sync.Mutex
Config
client *docker.Client
client *weavedocker.Client
weave *weaveapi.Client
dockerBridgeIP string
hostnameMatchRegexp *regexp.Regexp
weaveWaitVolume string
@@ -122,16 +124,13 @@ func (j attachJob) Stop() {
j.timer.Stop()
}
func NewProxy(c Config) (*Proxy, error) {
func StubProxy(c Config) (*Proxy, error) {
p := &Proxy{
Config: c,
waiters: make(map[*http.Request]*wait),
attachJobs: make(map[string]*attachJob),
quit: make(chan struct{}),
}
if err := p.TLSConfig.LoadCerts(); err != nil {
Log.Fatalf("Could not configure tls for proxy: %s", err)
weave: weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), Log),
}
// We pin the protocol version to 1.18 (which corresponds to
@@ -143,9 +142,21 @@ func NewProxy(c Config) (*Proxy, error) {
if err != nil {
return nil, err
}
Log.Info(client.Info())
p.client = client
return p, nil
}
p.client = client.Client
func NewProxy(c Config) (*Proxy, error) {
p, err := StubProxy(c)
if err != nil {
return nil, err
}
if err := p.TLSConfig.LoadCerts(); err != nil {
Log.Fatalf("Could not configure tls for proxy: %s", err)
}
Log.Info(p.client.Info())
if !p.WithoutDNS {
ip, err := weavenet.FindBridgeIP(c.DockerBridge, nil)
@@ -166,7 +177,7 @@ func NewProxy(c Config) (*Proxy, error) {
return nil, err
}
client.AddObserver(p)
p.client.AddObserver(p)
return p, nil
}
@@ -204,7 +215,7 @@ func (proxy *Proxy) findWeaveWaitVolumes() error {
}
func (proxy *Proxy) findVolume(v string) (string, error) {
container, err := proxy.client.InspectContainer("weaveproxy")
container, err := proxy.client.InspectContainer("weave")
if err != nil {
return "", fmt.Errorf("Could not find the weavewait volume: %s", err)
}
@@ -279,13 +290,17 @@ func (proxy *Proxy) Listen() []net.Listener {
return listeners
}
func (proxy *Proxy) Serve(listeners []net.Listener) {
func (proxy *Proxy) Serve(listeners []net.Listener, ready func()) {
errs := make(chan error)
for _, listener := range listeners {
go func(listener net.Listener) {
errs <- (&http.Server{Handler: proxy}).Serve(listener)
}(listener)
}
// It would be better if we could delay calling Done() until all
// the listeners are ready, but it doesn't seem to be possible to
// hook the right point in http.Server
ready()
for range listeners {
err := <-errs
if err != nil {
@@ -294,17 +309,6 @@ func (proxy *Proxy) Serve(listeners []net.Listener) {
}
}
func (proxy *Proxy) ListenAndServeStatus(socket string) {
listener, err := weavenet.ListenUnixSocket(socket)
if err != nil {
Log.Fatalf("ListenAndServeStatus failed: %s", err)
}
handler := http.HandlerFunc(proxy.StatusHTTP)
if err := (&http.Server{Handler: handler}).Serve(listener); err != nil {
Log.Fatalf("ListenAndServeStatus failed: %s", err)
}
}
func (proxy *Proxy) StatusHTTP(w http.ResponseWriter, r *http.Request) {
for _, addr := range proxy.normalisedAddrs {
fmt.Fprintln(w, addr)
@@ -325,11 +329,7 @@ func copyOwnerAndPermissions(from, to string) error {
return nil
}
if err = os.Chown(to, int(moreStat.Uid), int(moreStat.Gid)); err != nil {
return err
}
return nil
return os.Chown(to, int(moreStat.Uid), int(moreStat.Gid))
}
func (proxy *Proxy) listen(protoAndAddr string) (net.Listener, string, error) {
@@ -408,11 +408,6 @@ func containerShouldAttach(container *docker.Container) bool {
return len(container.Config.Entrypoint) > 0 && container.Config.Entrypoint[0] == weaveWaitEntrypoint[0]
}
func containerIsWeaveRouter(container *docker.Container) bool {
return container.Name == weaveContainerName &&
len(container.Config.Entrypoint) > 0 && container.Config.Entrypoint[0] == weaveEntrypoint
}
func (proxy *Proxy) createWait(r *http.Request, ident string) {
proxy.Lock()
proxy.waiters[r] = &wait{ident: ident, ch: make(chan error, 1)}
@@ -489,10 +484,6 @@ func (proxy *Proxy) attach(containerID string) error {
}
return nil
}
if containerIsWeaveRouter(container) {
Log.Infof("Attaching weave router container: %s", container.ID)
return callWeaveAttach(container, []string{"attach-router"})
}
if !containerShouldAttach(container) || !container.State.Running {
return nil
}
@@ -503,53 +494,80 @@ func (proxy *Proxy) attach(containerID string) error {
return nil
}
Log.Infof("Attaching container %s with WEAVE_CIDR \"%s\" to weave network", container.ID, strings.Join(cidrs, " "))
if err := validateCIDRs(cidrs); err != nil {
ips, err := proxy.allocateCIDRs(container.ID, cidrs)
if err != nil {
return err
}
args := []string{"attach"}
args = append(args, cidrs...)
fqdn := container.Config.Hostname + "." + container.Config.Domainname
if !proxy.NoRewriteHosts {
args = append(args, "--rewrite-hosts")
var extraHosts []string
if container.HostConfig != nil {
for _, eh := range container.HostConfig.ExtraHosts {
args = append(args, fmt.Sprintf("--add-host=%s", eh))
extraHosts = container.HostConfig.ExtraHosts
}
if err := proxy.RewriteEtcHosts(container.HostsPath, fqdn, ips, extraHosts); err != nil {
Log.Errorf("Error from rewriting container's /etc/hosts: %s", err)
// carry on since the original /etc/hosts is good enough in most cases
}
}
pid := container.State.Pid
// Passing 0 for mtu means it will be taken from the bridge
err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, weavenet.WeaveBridgeName, 0, !proxy.NoMulticastRoute, ips, proxy.KeepTXOn, true)
if err != nil {
return err
}
if !proxy.WithoutDNS {
for _, ip := range ips {
if err := proxy.weave.RegisterWithDNS(container.ID, fqdn, ip.IP.String()); err != nil {
return errors.Wrapf(err, "unable to register %s with weaveDNS: %s", container.ID, err)
}
}
}
if proxy.NoMulticastRoute {
args = append(args, "--no-multicast-route")
}
args = append(args, container.ID)
return callWeaveAttach(container, args)
return err
}
func callWeaveAttach(container *docker.Container, args []string) error {
if _, stderr, err := callWeave(args...); err != nil {
Log.Warningf("Attaching container %s to weave network failed: %s", container.ID, string(stderr))
return errors.New(string(stderr))
} else if len(stderr) > 0 {
Log.Warningf("Attaching container %s to weave network: %s", container.ID, string(stderr))
func (proxy *Proxy) allocateCIDRs(containerID string, cidrs []string) ([]*net.IPNet, error) {
if len(cidrs) == 0 {
cidrs = []string{"net:default"}
}
return nil
}
func validateCIDRs(cidrs []string) error {
var ipnet *net.IPNet
var err error
var ipnets []*net.IPNet
for _, cidr := range cidrs {
if cidr == "net:default" {
continue
}
for _, prefix := range []string{"ip:", "net:", ""} {
if strings.HasPrefix(cidr, prefix) {
if _, err := address.ParseCIDR(strings.TrimPrefix(cidr, prefix)); err == nil {
break
}
return fmt.Errorf("invalid WEAVE_CIDR: %s", cidr)
switch {
case cidr == "net:default":
ipnet, err = proxy.weave.AllocateIP(containerID, true)
case strings.HasPrefix(cidr, "net:"):
var subnet *net.IPNet
_, subnet, err = net.ParseCIDR(strings.TrimPrefix(cidr, "net:"))
if err != nil {
break
}
ipnet, err = proxy.weave.AllocateIPInSubnet(containerID, subnet, true)
case strings.HasPrefix(cidr, "ip:"):
ipnet, err = proxy.claimCIDR(containerID, strings.TrimPrefix(cidr, "ip:"))
default:
ipnet, err = proxy.claimCIDR(containerID, cidr)
}
if err != nil {
return nil, errors.Wrapf(err, "for %q", cidr)
}
ipnets = append(ipnets, ipnet)
}
return nil
return ipnets, nil
}
func (proxy *Proxy) claimCIDR(containerID, cidr string) (*net.IPNet, error) {
ip, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
return nil, err
}
ipnet.IP = ip // we want the specific IP plus the mask
err = proxy.weave.ClaimIP(containerID, ipnet, true)
return ipnet, err
}
func (proxy *Proxy) weaveCIDRs(networkMode string, env []string) ([]string, error) {
@@ -598,8 +616,7 @@ func (proxy *Proxy) getDNSDomain() string {
if proxy.WithoutDNS {
return ""
}
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), Log)
domain, _ := weave.DNSDomain()
domain, _ := proxy.weave.DNSDomain()
return domain
}
@@ -638,7 +655,6 @@ func (proxy *Proxy) updateContainerNetworkSettings(container jsonObject) error {
}
func (proxy *Proxy) symlink(unixAddrs []string) (err error) {
var container *docker.Container
binds := []string{"/var/run/weave:/var/run/weave"}
froms := []string{}
for _, addr := range unixAddrs {
@@ -654,7 +670,10 @@ func (proxy *Proxy) symlink(unixAddrs []string) (err error) {
if len(froms) == 0 {
return
}
return proxy.runTransientContainer([]string{"/home/weave/symlink", weaveSock}, froms, binds)
}
func (proxy *Proxy) runTransientContainer(entrypoint, cmd, binds []string) (err error) {
env := []string{
"PATH=/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
}
@@ -663,14 +682,16 @@ func (proxy *Proxy) symlink(unixAddrs []string) (err error) {
env = append(env, fmt.Sprintf("%s=%s", "WEAVE_DEBUG", val))
}
Log.Debugf("Running image %q; entrypoint=%q; cmd=%q; binds=%q", proxy.Image, entrypoint, fmt.Sprintf("%.72s", cmd), binds)
var container *docker.Container
container, err = proxy.client.CreateContainer(docker.CreateContainerOptions{
Config: &docker.Config{
Image: proxy.Image,
Entrypoint: []string{"/home/weave/symlink", weaveSock},
Cmd: froms,
Entrypoint: entrypoint,
Cmd: cmd,
Env: env,
},
HostConfig: &docker.HostConfig{Binds: binds},
HostConfig: &docker.HostConfig{Binds: binds, NetworkMode: "none"},
})
if err != nil {
return
+15
View File
@@ -0,0 +1,15 @@
package proxy
type Status struct {
Addresses []string
}
func NewStatus(proxy *Proxy) *Status {
if proxy == nil {
return nil
}
status := &Status{
Addresses: proxy.normalisedAddrs,
}
return status
}
+10 -10
View File
@@ -209,25 +209,25 @@ func (lock *fastDatapathLock) relock() {
}
}
// Bridge bits
// InjectorConsumer bits
type fastDatapathBridge struct {
type fastDatapathInjectorConsumer struct {
*FastDatapath
}
func (fastdp *FastDatapath) Bridge() Bridge {
return fastDatapathBridge{fastdp}
func (fastdp *FastDatapath) InjectorConsumer() InjectorConsumer {
return fastDatapathInjectorConsumer{fastdp}
}
func (fastdp fastDatapathBridge) Interface() *net.Interface {
func (fastdp fastDatapathInjectorConsumer) Interface() *net.Interface {
return fastdp.iface
}
func (fastdp fastDatapathBridge) String() string {
func (fastdp fastDatapathInjectorConsumer) String() string {
return fmt.Sprint(fastdp.iface.Name, " (via ODP)")
}
func (fastdp fastDatapathBridge) Stats() map[string]int {
func (fastdp fastDatapathInjectorConsumer) Stats() map[string]int {
lock := fastdp.startLock()
defer lock.unlock()
@@ -238,12 +238,12 @@ func (fastdp fastDatapathBridge) Stats() map[string]int {
var routerBridgePortID = bridgePortID{router: true}
func (fastdp fastDatapathBridge) StartConsumingPackets(consumer BridgeConsumer) error {
func (fastdp fastDatapathInjectorConsumer) StartConsumingPackets(consumer Consumer) error {
fastdp.lock.Lock()
defer fastdp.lock.Unlock()
if fastdp.sendToPort[routerBridgePortID] != nil {
return fmt.Errorf("FastDatapath already has a BridgeConsumer")
return fmt.Errorf("FastDatapath already has a Consumer")
}
// set up delivery to the weave router port on the bridge
@@ -257,7 +257,7 @@ func (fastdp fastDatapathBridge) StartConsumingPackets(consumer BridgeConsumer)
return nil
}
func (fastdp fastDatapathBridge) InjectPacket(key PacketKey) FlowOp {
func (fastdp fastDatapathInjectorConsumer) InjectPacket(key PacketKey) FlowOp {
lock := fastdp.startLock()
defer lock.unlock()
return fastdp.bridge(routerBridgePortID, key, &lock)
+19
View File
@@ -5,7 +5,10 @@ import (
"net/http"
"github.com/gorilla/mux"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/net"
"github.com/weaveworks/weave/net/address"
)
func (router *NetworkRouter) HandleHTTP(muxRouter *mux.Router) {
@@ -26,4 +29,20 @@ func (router *NetworkRouter) HandleHTTP(muxRouter *mux.Router) {
router.ForgetConnections(r.Form["peer"])
})
muxRouter.Methods("POST").Path("/expose/{ip}/{prefixlen}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
cidr, err := address.ParseCIDR(vars["ip"] + "/" + vars["prefixlen"])
if err != nil {
http.Error(w, fmt.Sprint("unable to parse ip addr: ", err.Error()), http.StatusBadRequest)
return
}
if err = net.Expose(router.BridgeConfig.WeaveBridgeName, cidr.IPNet(), router.BridgeConfig.AWSVPC, router.BridgeConfig.NPC); err != nil {
http.Error(w, fmt.Sprint("unable to expose: ", err.Error()), http.StatusInternalServerError)
return
}
w.WriteHeader(204)
})
}
@@ -5,13 +5,13 @@ import (
)
// Interface to packet handling on the local virtual bridge
type Bridge interface {
type InjectorConsumer interface {
// Inject a packet to be delivered locally
InjectPacket(PacketKey) FlowOp
// Start consuming packets from the bridge. Injected packets
// should not be included.
StartConsumingPackets(BridgeConsumer) error
StartConsumingPackets(Consumer) error
Interface() *net.Interface
String() string
@@ -19,26 +19,26 @@ type Bridge interface {
}
// A function that determines how to handle locally captured packets.
type BridgeConsumer func(PacketKey) FlowOp
type Consumer func(PacketKey) FlowOp
type NullBridge struct{}
type NullInjectorConsumer struct{}
func (NullBridge) InjectPacket(PacketKey) FlowOp {
func (NullInjectorConsumer) InjectPacket(PacketKey) FlowOp {
return nil
}
func (NullBridge) StartConsumingPackets(BridgeConsumer) error {
func (NullInjectorConsumer) StartConsumingPackets(Consumer) error {
return nil
}
func (NullBridge) Interface() *net.Interface {
func (NullInjectorConsumer) Interface() *net.Interface {
return nil
}
func (NullBridge) String() string {
func (NullInjectorConsumer) String() string {
return "no overlay bridge"
}
func (NullBridge) Stats() map[string]int {
func (NullInjectorConsumer) Stats() map[string]int {
return nil
}
+12 -10
View File
@@ -11,6 +11,7 @@ import (
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/db"
weavenet "github.com/weaveworks/weave/net"
)
const (
@@ -34,9 +35,9 @@ var (
)
type NetworkConfig struct {
BufSz int
PacketLogging PacketLogging
Bridge Bridge
BufSz int
PacketLogging PacketLogging
InjectorConsumer InjectorConsumer
}
type PacketLogging interface {
@@ -47,23 +48,24 @@ type PacketLogging interface {
type NetworkRouter struct {
*mesh.Router
NetworkConfig
weavenet.BridgeConfig
Macs *MacCache
db db.DB
}
func NewNetworkRouter(config mesh.Config, networkConfig NetworkConfig, name mesh.PeerName, nickName string, overlay NetworkOverlay, db db.DB) (*NetworkRouter, error) {
func NewNetworkRouter(config mesh.Config, networkConfig NetworkConfig, bridgeConfig weavenet.BridgeConfig, name mesh.PeerName, nickName string, overlay NetworkOverlay, db db.DB) (*NetworkRouter, error) {
if overlay == nil {
overlay = NullNetworkOverlay{}
}
if networkConfig.Bridge == nil {
networkConfig.Bridge = NullBridge{}
if networkConfig.InjectorConsumer == nil {
networkConfig.InjectorConsumer = NullInjectorConsumer{}
}
meshRouter, err := mesh.NewRouter(config, name, nickName, overlay, common.LogLogger())
if err != nil {
return nil, err
}
router := &NetworkRouter{Router: meshRouter, NetworkConfig: networkConfig, db: db}
router := &NetworkRouter{Router: meshRouter, NetworkConfig: networkConfig, BridgeConfig: bridgeConfig, db: db}
router.Peers.OnInvalidateShortIDs(overlay.InvalidateShortIDs)
router.Routes.OnChange(overlay.InvalidateRoutes)
router.Macs = NewMacCache(macMaxAge,
@@ -77,8 +79,8 @@ func NewNetworkRouter(config mesh.Config, networkConfig NetworkConfig, name mesh
// Start listening for TCP connections, locally captured packets, and
// forwarded packets.
func (router *NetworkRouter) Start() {
log.Println("Sniffing traffic on", router.Bridge)
checkFatal(router.Bridge.StartConsumingPackets(router.handleCapturedPacket))
log.Println("Sniffing traffic on", router.InjectorConsumer)
checkFatal(router.InjectorConsumer.StartConsumingPackets(router.handleCapturedPacket))
checkFatal(router.Overlay.(NetworkOverlay).StartConsumingPackets(router.Ourself.Peer, router.Peers, router.handleForwardedPacket))
router.Router.Start()
}
@@ -156,7 +158,7 @@ func (router *NetworkRouter) handleForwardedPacket(key ForwardPacketKey) FlowOp
}
router.PacketLogging.LogForwardPacket("Injecting", key)
injectFop := router.Bridge.InjectPacket(key.PacketKey)
injectFop := router.InjectorConsumer.InjectPacket(key.PacketKey)
dstPeer := router.Macs.Lookup(dstMac)
if dstPeer == router.Ourself.Peer {
return injectFop
Loaded 100 of 256 files, more files were not shown because too many files have changed in this diff. Show more