The only slight trickiness is Shutdown. Generally connections shut
down when an error is encountered, but we also need to be able to shut
down connections w/o an error. Rather than making all the actor
methods return a (terminated bool, error) tuple, we signal the
non-error shutdown by sending nil as the action (instead of a
closure).
Introduce an intermediary - GossipSender - between GossipChannel and
Connection. This accumulates gossip data (now represented by the new
GossipData interface) from the former until it can be passed onto the
latter, allowing the former to proceed when the latter may be blocked
on i/o.
This
1) prevents deadlocks that arise from cycles in the communication
topology
2) improves performance by allowing GossipChannel and its calling code
to proceed when connection i/o is blocked
3) improves performance by accumulating GossipData - the accumulated
data often is considerably more compact than the sum of all the
accumulated bits, and it is transmitted in a single communication
event.
In order to support accumulation, the GossipData interface has a Merge
method. Furthermore, encoding is deferred until the data can actually
be sent, since accumulation would be hard/impossible to encoded
data. This required changes on some interfaces, most notably Gossiper.
The implementation of GossipData for topology gossip is
TopologyGossipData. It carries a reference to Peers and a set of
PeerNames, indexing into Peers and referencing the Peer entries which
have changed. Previously updates were represented as a list of Peer
entries. The indirection via PeerNames allows Encode to omit entries
which have been removed. The change in representation required changes
to the signature of some methods on Peers.
Note that all the above only applies to the "periodic gossip" portion
of the Gossiper API, which topology gossip in fact uses for *all*
gossip. GossipUnicast and GossipBroadcast are unchanged, but could
conceivably receive the same treatment in the future.
Fixes#445.
As noted in #388 comment 76958961, we need the docker client to be as
old as possible while supporting what weave needs to do. At the minute
that means version 1.3.1.
The `apk` package index does not have old versions of docker, so the
most direct way of getting a docker executable is to download the
specific version from https://get.docker.com.
We want to be compatible with whatever docker the user has; `weave
run` is the only command that passes on arbitrary args to docker
(i.e., that doesn't have a fixed set of docker features that it
needs).
To make this workable we still need to do some things on the remote
host: the IP attachment and figuring out the DNS settings (since those
may depend on the bridge IP).
This is to make a visible break with previous releases, such that a
newly downloaded weave script will definitely work.
Without this change in name, an existing weavetools image that doesn't
include the script might be invoked, resulting in a confusing message
for the user.
`apk-install` is a script that runs apk then tidies up. The problem is
that it doesn't exit with an error if the install fails, which means
that if some packages are unavailable at the time of building, it will
still all go ahead.
This rearrangement means that the `weave` command can be used
remotely; and, as a side-effect, the script that does all the work is
using executables in its own filesystem, rather than invoking them via
docker.
The remote weavetools is given a terminal so it can be interrupted.
With the flag `--local`, the script will assume all its dependencies
are available and run then and there. Without the flag, it will run
via the weavetools image (adding the flag to the invocation).
A choice here is whether to base the tools image on scratch and add
all the deps, or base it on something else. I've used alpine linux,
which itself is based on busybox. This gives us the usual tools (sed
etc.) while keeping the image size small.
Adding the docker binary adds substantially to the image size, but it
cannot always be e.g., bind-mounted. To mitigate this image bloat, we
might build or otherwise get a client-only docker executable, or write
a special-purpose client, or indeed rewrite the driver script and use
a client library.
This also makes the dockerhub user part of the image names
parameterised, to make it easier to test the release process in full.
Tests weren't compiling due to change of ListenHttp() signature. Fixed
for now by reintroducing domain parameter in addition to server, as this
allows the HTTP tests to pass in a nil server parameter. In the long
term DNSServer should probably become an interface so we can mock it
easily in such a scenario.