This is useful for cluster systems such as swarm to sync the image
state when new images are successfully built.
Signed-off-by: Shijiang Wei <mountkin@gmail.com>
| ... | ... |
@@ -462,7 +462,6 @@ func (s *router) postImagesTag(ctx context.Context, w http.ResponseWriter, r *ht |
| 462 | 462 |
if err := s.daemon.TagImage(repo, tag, name, force); err != nil {
|
| 463 | 463 |
return err |
| 464 | 464 |
} |
| 465 |
- s.daemon.EventsService.Log("tag", utils.ImageReference(repo, tag), "")
|
|
| 466 | 465 |
w.WriteHeader(http.StatusCreated) |
| 467 | 466 |
return nil |
| 468 | 467 |
} |
| ... | ... |
@@ -50,6 +50,7 @@ import ( |
| 50 | 50 |
"github.com/docker/docker/pkg/truncindex" |
| 51 | 51 |
"github.com/docker/docker/registry" |
| 52 | 52 |
"github.com/docker/docker/runconfig" |
| 53 |
+ "github.com/docker/docker/utils" |
|
| 53 | 54 |
volumedrivers "github.com/docker/docker/volume/drivers" |
| 54 | 55 |
"github.com/docker/docker/volume/local" |
| 55 | 56 |
"github.com/docker/docker/volume/store" |
| ... | ... |
@@ -1026,7 +1027,11 @@ func (daemon *Daemon) Graph() *graph.Graph {
|
| 1026 | 1026 |
// imageName. If force is true, an existing tag with the same name may be |
| 1027 | 1027 |
// overwritten. |
| 1028 | 1028 |
func (daemon *Daemon) TagImage(repoName, tag, imageName string, force bool) error {
|
| 1029 |
- return daemon.repositories.Tag(repoName, tag, imageName, force) |
|
| 1029 |
+ if err := daemon.repositories.Tag(repoName, tag, imageName, force); err != nil {
|
|
| 1030 |
+ return err |
|
| 1031 |
+ } |
|
| 1032 |
+ daemon.EventsService.Log("tag", utils.ImageReference(repoName, tag), "")
|
|
| 1033 |
+ return nil |
|
| 1030 | 1034 |
} |
| 1031 | 1035 |
|
| 1032 | 1036 |
// PullImage initiates a pull operation. image is the repository name to pull, and |
| ... | ... |
@@ -7,6 +7,7 @@ import ( |
| 7 | 7 |
"encoding/json" |
| 8 | 8 |
"fmt" |
| 9 | 9 |
"io/ioutil" |
| 10 |
+ "net/http" |
|
| 10 | 11 |
"os" |
| 11 | 12 |
"os/exec" |
| 12 | 13 |
"path/filepath" |
| ... | ... |
@@ -6223,3 +6224,37 @@ func (s *DockerSuite) TestBuildNoNamedVolume(c *check.C) {
|
| 6223 | 6223 |
_, err := buildImage("test", dockerFile, false)
|
| 6224 | 6224 |
c.Assert(err, check.NotNil, check.Commentf("image build should have failed"))
|
| 6225 | 6225 |
} |
| 6226 |
+ |
|
| 6227 |
+func (s *DockerSuite) TestBuildTagEvent(c *check.C) {
|
|
| 6228 |
+ testRequires(c, DaemonIsLinux) |
|
| 6229 |
+ resp, rc, err := sockRequestRaw("GET", `/events?filters={"event":["tag"]}`, nil, "application/json")
|
|
| 6230 |
+ c.Assert(err, check.IsNil) |
|
| 6231 |
+ defer rc.Close() |
|
| 6232 |
+ c.Assert(resp.StatusCode, check.Equals, http.StatusOK) |
|
| 6233 |
+ |
|
| 6234 |
+ type event struct {
|
|
| 6235 |
+ Status string `json:"status"` |
|
| 6236 |
+ ID string `json:"id"` |
|
| 6237 |
+ } |
|
| 6238 |
+ ch := make(chan event) |
|
| 6239 |
+ go func() {
|
|
| 6240 |
+ ev := event{}
|
|
| 6241 |
+ if err := json.NewDecoder(rc).Decode(&ev); err == nil {
|
|
| 6242 |
+ ch <- ev |
|
| 6243 |
+ } |
|
| 6244 |
+ }() |
|
| 6245 |
+ |
|
| 6246 |
+ dockerFile := `FROM busybox |
|
| 6247 |
+ RUN echo events |
|
| 6248 |
+ ` |
|
| 6249 |
+ _, err = buildImage("test", dockerFile, false)
|
|
| 6250 |
+ c.Assert(err, check.IsNil) |
|
| 6251 |
+ |
|
| 6252 |
+ select {
|
|
| 6253 |
+ case ev := <-ch: |
|
| 6254 |
+ c.Assert(ev.Status, check.Equals, "tag") |
|
| 6255 |
+ c.Assert(ev.ID, check.Equals, "test:") |
|
| 6256 |
+ case <-time.After(time.Second): |
|
| 6257 |
+ c.Fatal("The 'tag' event not heard from the server")
|
|
| 6258 |
+ } |
|
| 6259 |
+} |
| ... | ... |
@@ -414,13 +414,13 @@ func (s *DockerSuite) TestEventsFilterLabels(c *check.C) {
|
| 414 | 414 |
func (s *DockerSuite) TestEventsFilterImageLabels(c *check.C) {
|
| 415 | 415 |
testRequires(c, DaemonIsLinux) |
| 416 | 416 |
since := daemonTime(c).Unix() |
| 417 |
- name := "labelfilterimage" |
|
| 417 |
+ name := "labelfiltertest" |
|
| 418 | 418 |
label := "io.docker.testing=image" |
| 419 | 419 |
|
| 420 | 420 |
// Build a test image. |
| 421 |
- _, err := buildImage(name, ` |
|
| 421 |
+ _, err := buildImage(name, fmt.Sprintf(` |
|
| 422 | 422 |
FROM busybox:latest |
| 423 |
- LABEL io.docker.testing=image`, true) |
|
| 423 |
+ LABEL %s`, label), true) |
|
| 424 | 424 |
if err != nil {
|
| 425 | 425 |
c.Fatalf("Couldn't create image: %q", err)
|
| 426 | 426 |
} |
| ... | ... |
@@ -437,7 +437,9 @@ func (s *DockerSuite) TestEventsFilterImageLabels(c *check.C) {
|
| 437 | 437 |
"--filter", fmt.Sprintf("label=%s", label))
|
| 438 | 438 |
|
| 439 | 439 |
events := strings.Split(strings.TrimSpace(out), "\n") |
| 440 |
- c.Assert(len(events), checker.Equals, 2, check.Commentf("Events == %s", events))
|
|
| 440 |
+ |
|
| 441 |
+ // 2 events from the "docker tag" command, another one is from "docker build" |
|
| 442 |
+ c.Assert(len(events), checker.Equals, 3, check.Commentf("Events == %s", events))
|
|
| 441 | 443 |
for _, e := range events {
|
| 442 | 444 |
c.Assert(e, checker.Contains, "labelfiltertest") |
| 443 | 445 |
} |