github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/integration/system/event_test.go (about) 1 package system // import "github.com/docker/docker/integration/system" 2 3 import ( 4 "context" 5 "encoding/json" 6 "errors" 7 "io" 8 "net/http" 9 "net/url" 10 "strconv" 11 "testing" 12 "time" 13 14 "github.com/docker/docker/api/types" 15 "github.com/docker/docker/api/types/events" 16 "github.com/docker/docker/api/types/filters" 17 "github.com/docker/docker/api/types/mount" 18 "github.com/docker/docker/api/types/strslice" 19 "github.com/docker/docker/api/types/versions" 20 "github.com/docker/docker/api/types/volume" 21 "github.com/docker/docker/integration/internal/container" 22 "github.com/docker/docker/pkg/jsonmessage" 23 "github.com/docker/docker/testutil/request" 24 req "github.com/docker/docker/testutil/request" 25 "gotest.tools/v3/assert" 26 is "gotest.tools/v3/assert/cmp" 27 "gotest.tools/v3/skip" 28 ) 29 30 func TestEventsExecDie(t *testing.T) { 31 skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.36"), "broken in earlier versions") 32 skip.If(t, testEnv.OSType == "windows", "FIXME. Suspect may need to wait until container is running before exec") 33 defer setupTest(t)() 34 ctx := context.Background() 35 client := testEnv.APIClient() 36 37 cID := container.Run(ctx, t, client) 38 39 id, err := client.ContainerExecCreate(ctx, cID, 40 types.ExecConfig{ 41 Cmd: strslice.StrSlice([]string{"echo", "hello"}), 42 }, 43 ) 44 assert.NilError(t, err) 45 46 filters := filters.NewArgs( 47 filters.Arg("container", cID), 48 filters.Arg("event", "exec_die"), 49 ) 50 msg, errors := client.Events(ctx, types.EventsOptions{ 51 Filters: filters, 52 }) 53 54 err = client.ContainerExecStart(ctx, id.ID, 55 types.ExecStartCheck{ 56 Detach: true, 57 Tty: false, 58 }, 59 ) 60 assert.NilError(t, err) 61 62 select { 63 case m := <-msg: 64 assert.Equal(t, m.Type, "container") 65 assert.Equal(t, m.Actor.ID, cID) 66 assert.Equal(t, m.Action, "exec_die") 67 assert.Equal(t, m.Actor.Attributes["execID"], id.ID) 68 assert.Equal(t, m.Actor.Attributes["exitCode"], "0") 69 case err = <-errors: 70 assert.NilError(t, err) 71 case <-time.After(time.Second * 3): 72 t.Fatal("timeout hit") 73 } 74 } 75 76 // Test case for #18888: Events messages have been switched from generic 77 // `JSONMessage` to `events.Message` types. The switch does not break the 78 // backward compatibility so old `JSONMessage` could still be used. 79 // This test verifies that backward compatibility maintains. 80 func TestEventsBackwardsCompatible(t *testing.T) { 81 skip.If(t, testEnv.OSType == "windows", "Windows doesn't support back-compat messages") 82 defer setupTest(t)() 83 ctx := context.Background() 84 client := testEnv.APIClient() 85 86 since := request.DaemonTime(ctx, t, client, testEnv) 87 ts := strconv.FormatInt(since.Unix(), 10) 88 89 cID := container.Create(ctx, t, client) 90 91 // In case there is no events, the API should have responded immediately (not blocking), 92 // The test here makes sure the response time is less than 3 sec. 93 expectedTime := time.Now().Add(3 * time.Second) 94 emptyResp, emptyBody, err := req.Get("/events") 95 assert.NilError(t, err) 96 defer emptyBody.Close() 97 assert.Check(t, is.DeepEqual(http.StatusOK, emptyResp.StatusCode)) 98 assert.Check(t, time.Now().Before(expectedTime), "timeout waiting for events api to respond, should have responded immediately") 99 100 // We also test to make sure the `events.Message` is compatible with `JSONMessage` 101 q := url.Values{} 102 q.Set("since", ts) 103 _, body, err := req.Get("/events?" + q.Encode()) 104 assert.NilError(t, err) 105 defer body.Close() 106 107 dec := json.NewDecoder(body) 108 var containerCreateEvent *jsonmessage.JSONMessage 109 for { 110 var event jsonmessage.JSONMessage 111 if err := dec.Decode(&event); err != nil { 112 if err == io.EOF { 113 break 114 } 115 assert.NilError(t, err) 116 } 117 if event.Status == "create" && event.ID == cID { 118 containerCreateEvent = &event 119 break 120 } 121 } 122 123 assert.Check(t, containerCreateEvent != nil) 124 assert.Check(t, is.Equal("create", containerCreateEvent.Status)) 125 assert.Check(t, is.Equal(cID, containerCreateEvent.ID)) 126 assert.Check(t, is.Equal("busybox", containerCreateEvent.From)) 127 } 128 129 // TestEventsVolumeCreate verifies that volume create events are only fired 130 // once: when creating the volume, and not when attaching to a container. 131 func TestEventsVolumeCreate(t *testing.T) { 132 skip.If(t, testEnv.OSType == "windows", "FIXME: Windows doesn't trigger the events? Could be a race") 133 134 defer setupTest(t)() 135 ctx, cancel := context.WithCancel(context.Background()) 136 defer cancel() 137 138 client := testEnv.APIClient() 139 140 since := request.DaemonUnixTime(ctx, t, client, testEnv) 141 volName := t.Name() 142 getEvents := func(messages <-chan events.Message, errs <-chan error) ([]events.Message, error) { 143 var evts []events.Message 144 145 for { 146 select { 147 case m := <-messages: 148 evts = append(evts, m) 149 case err := <-errs: 150 if err == io.EOF { 151 return evts, nil 152 } 153 return nil, err 154 case <-time.After(time.Second * 3): 155 return nil, errors.New("timeout hit") 156 } 157 } 158 } 159 160 _, err := client.VolumeCreate(ctx, volume.CreateOptions{Name: volName}) 161 assert.NilError(t, err) 162 163 filter := filters.NewArgs( 164 filters.Arg("type", "volume"), 165 filters.Arg("event", "create"), 166 filters.Arg("volume", volName), 167 ) 168 messages, errs := client.Events(ctx, types.EventsOptions{ 169 Since: since, 170 Until: request.DaemonUnixTime(ctx, t, client, testEnv), 171 Filters: filter, 172 }) 173 174 volEvents, err := getEvents(messages, errs) 175 assert.NilError(t, err) 176 assert.Equal(t, len(volEvents), 1, "expected volume create event when creating a volume") 177 178 container.Create(ctx, t, client, container.WithMount(mount.Mount{ 179 Type: mount.TypeVolume, 180 Source: volName, 181 Target: "/tmp/foo", 182 })) 183 184 messages, errs = client.Events(ctx, types.EventsOptions{ 185 Since: since, 186 Until: request.DaemonUnixTime(ctx, t, client, testEnv), 187 Filters: filter, 188 }) 189 190 volEvents, err = getEvents(messages, errs) 191 assert.NilError(t, err) 192 assert.Equal(t, len(volEvents), 1, "expected volume create event to be fired only once") 193 }