Skip to content
This repository has been archived by the owner on Jun 20, 2024. It is now read-only.

Remove stale records for short-lived containers #865

Merged
merged 3 commits into from
Jun 12, 2015

Conversation

inercia
Copy link
Contributor

@inercia inercia commented Jun 5, 2015

This PR removes stale records for short-lived containers by asking Docker about the container that corresponds to the new name:IP that has been introduced.

This can be tested by following the procedure described by @rade in #821: with (and without) docker kill $CONTAINER_ID in weave:put_dns_fqdn() and then running something like:

#!/bin/sh

make clean
make all

./weave launch
./weave launch-dns 10.2.1.1/24 --debug
./weave run 10.2.0.1/24 -h foo.weave.local -ti ubuntu
echo "Checking if 'foo.weave.local' is there"
./weave status | grep "foo.weave.local"
echo "Stopping everything"
./weave stop-dns
./weave stop

Fixes #821

running = false
}
} else {
running = container.State.Running

This comment was marked as abuse.

This comment was marked as abuse.

This comment was marked as abuse.

This comment was marked as abuse.

@rade
Copy link
Member

rade commented Jun 5, 2015

I think the abstraction isn't quite right here. There's too much machinery in weavedns and too little in updater. Bear in mind that solving #819 will likely require very similar machinery.

@inercia
Copy link
Contributor Author

inercia commented Jun 5, 2015

@rade If with "too much machinery in weavedns" you mean lines 72-86, IMO fourteen lines are not so much machinery, specially when they are pretty specific of WeaveDNS (eg, deleting records in the Zone).

Adding this mechanism in the "updater" would not be the right place either, as the "updater" is really a Docker listener, and this does not listen for anything: it just checks whether the container is running. I raised the question in HipChat whether we should have a general "docker client" in common...

So I would wait until #819 before trying to do an early generalization...

@rade
Copy link
Member

rade commented Jun 5, 2015

fourteen lines is a lot of machinery when we could have something like if isContainerRunning(container) {...}.

Also, there's all the startup machinery in weavedns/main.go

@inercia
Copy link
Contributor Author

inercia commented Jun 5, 2015

Yes, it would be nice to have isContainerRunning(), but the thing is where to put that method. And, as you mentioned, "the startup machinery in weavedns/main.go" is the Docker client initialization, used both by the "updater" and by this code. So I would prefer not to transform the issue "stale records for short-lived containers" into "refactor all our Docker code into a common client"...

@rade
Copy link
Member

rade commented Jun 5, 2015

weavedns/main.go has no business initialising a docker client. This should be well abstracted away. The new import of "github.com/fsouza/go-dockerclient" in main.go is a dead giveaway.

@inercia
Copy link
Contributor Author

inercia commented Jun 5, 2015

Ok, then we will have a common/docker/client.go file... :)

client *docker.Client
}

// NewClint creates a new Docker client

This comment was marked as abuse.

}

return running
}

This comment was marked as abuse.

This comment was marked as abuse.

@rade
Copy link
Member

rade commented Jun 9, 2015

The wrapping can be simpler:

diff --git a/common/docker/client.go b/common/docker/client.go
index ecd213d..73c5cfd 100644
--- a/common/docker/client.go
+++ b/common/docker/client.go
@@ -11,7 +11,7 @@ type ContainerObserver interface {
 }

 type Client struct {
-       client *docker.Client
+       *docker.Client
 }

 // NewClient creates a new Docker client
@@ -21,10 +21,7 @@ func NewClient(apiPath string) (*Client, error) {
                return nil, err
        }

-       c := Client{
-               client: dc,
-       }
-       return &c, nil
+       return &Client{dc}, nil
 }

 // Start starts the client
@@ -47,7 +44,7 @@ func (c *Client) Start(apiPath string) error {
 // AddObserver adds an observer for docker events
 func (c *Client) AddObserver(ob ContainerObserver) error {
        events := make(chan *docker.APIEvents)
-       if err := c.client.AddEventListener(events); err != nil {
+       if err := c.AddEventListener(events); err != nil {
                Error.Printf("[docker] Unable to add listener to Docker API: %s"
                return err
        }
@@ -69,7 +66,7 @@ func (c *Client) IsContainerRunning(idStr string) bool {
        running := true

        // check with Docker whether the container is really running
-       if container, err := c.client.InspectContainer(idStr); err != nil {
+       if container, err := c.InspectContainer(idStr); err != nil {
                if _, notThere := err.(*docker.NoSuchContainer); notThere {
                        running = false
                }

@rade rade assigned inercia and unassigned awh Jun 9, 2015
@inercia
Copy link
Contributor Author

inercia commented Jun 9, 2015

IMO that would not be appropriate here. Defining a struct like type Client struct { *docker.Client } does not make much sense, not only because it provides nothing on top of the original struct but also because we do not want to expose the whole docker.Client API, and that would do it... I think common/docker/client.go should remain as a facade for the docker API, not as an alias.

@rade
Copy link
Member

rade commented Jun 9, 2015

it provides nothing on top of the original struct

But it does. Namely the methods defined here.

we do not want to expose the whole docker.Client API

I actually see no problem with that.

@rade
Copy link
Member

rade commented Jun 9, 2015

what's happening with this?

@inercia
Copy link
Contributor Author

inercia commented Jun 9, 2015

@rade finishing #836, then I will resume this PR...

(anyway, I think you last comment is personal preference more than a real problem you found when reviewing the code, and I think this kind of comments slow down the review...)

@rade
Copy link
Member

rade commented Jun 9, 2015

The code I posted is shorter and just as readable, if not more so, than the original.

@inercia
Copy link
Contributor Author

inercia commented Jun 9, 2015

I also considered that solution when writing the code, and I discarded it because I think type aliases are not a good idea, even when they lead to shorter code (eg, type i int is not a good idea, even when produces shorter code and you can also add your own methods). But I will change it because I don't like to engage in endless discussions like this... ;)

@rade
Copy link
Member

rade commented Jun 9, 2015

Can it actually be done with a type alias? I tried and failed.

@inercia
Copy link
Contributor Author

inercia commented Jun 9, 2015

(facepalm)

@inercia
Copy link
Contributor Author

inercia commented Jun 9, 2015

You can do this:

type s string
func (something s) IsEmpty() bool { return len(something) == 0 }

so should we replace all our strings with s? 😕

@rade
Copy link
Member

rade commented Jun 9, 2015

I know about type aliases, but I cannot get them to work in this situation. Can you? The problem I am encountering is that we get a pointer to the docker client, which I cannot figure out how to turn into the right type, if that is even possible.

@rade
Copy link
Member

rade commented Jun 9, 2015

Found the answer; so the wrapper struct actually works better than an alias.

@inercia
Copy link
Contributor Author

inercia commented Jun 9, 2015

Changed the client...

@rade
Copy link
Member

rade commented Jun 9, 2015

Does this handle the non-container ids case correctly, e.g. when we add records for weave:expose?

@rade
Copy link
Member

rade commented Jun 9, 2015

and the linter is unhappy.

@inercia
Copy link
Contributor Author

inercia commented Jun 9, 2015

Good point about the weave:expose thing: I think I will need a if...

And I will make the linter happy again...

@rade
Copy link
Member

rade commented Jun 10, 2015

To address the weave:expose problem, I suggest you exclude idents from the aliveness check that are not container IDs, e.g. ^[a-f0-9]+$.

@inercia
Copy link
Contributor Author

inercia commented Jun 10, 2015

Fixed the container id check.


// IsContainerId returns True if the string provided is a valid container id
func IsContainerId(idStr string) bool {
matched, err := regexp.MatchString("^[a-f0-9]+$", idStr)

This comment was marked as abuse.

This comment was marked as abuse.

@rade
Copy link
Member

rade commented Jun 10, 2015

also, it looks like this needs rebasing.

@inercia inercia force-pushed the weave-821 branch 2 times, most recently from 3635671 to 89f0595 Compare June 10, 2015 19:21
@rade
Copy link
Member

rade commented Jun 11, 2015

The outdent still needs doing. Rest looks fine.

dockerCli, err = docker.NewClient(apiPath)
if err != nil {
Error.Fatal("[main] Unable to start docker client", err)
}

This comment was marked as abuse.

This comment was marked as abuse.

@bboreham
Copy link
Contributor

I'm going to take this over in @inercia's absence.

@bboreham bboreham assigned bboreham and unassigned inercia Jun 12, 2015
@rade rade merged commit 698d352 into weaveworks:master Jun 12, 2015
rade added a commit that referenced this pull request Jun 12, 2015
Remove stale records for short-lived containers (bis)

Fixes #821. Replaces and hence closes #865.
@rade rade modified the milestone: 1.0 Jun 12, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants