github.com/rawahars/moby@v24.0.4+incompatible/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 msg, errs := client.Events(ctx, types.EventsOptions{ 47 Filters: filters.NewArgs( 48 filters.Arg("container", cID), 49 filters.Arg("event", "exec_die"), 50 ), 51 }) 52 53 err = client.ContainerExecStart(ctx, id.ID, 54 types.ExecStartCheck{ 55 Detach: true, 56 Tty: false, 57 }, 58 ) 59 assert.NilError(t, err) 60 61 select { 62 case m := <-msg: 63 assert.Equal(t, m.Type, "container") 64 assert.Equal(t, m.Actor.ID, cID) 65 assert.Equal(t, m.Action, "exec_die") 66 assert.Equal(t, m.Actor.Attributes["execID"], id.ID) 67 assert.Equal(t, m.Actor.Attributes["exitCode"], "0") 68 case err = <-errs: 69 assert.NilError(t, err) 70 case <-time.After(time.Second * 3): 71 t.Fatal("timeout hit") 72 } 73 } 74 75 // Test case for #18888: Events messages have been switched from generic 76 // `JSONMessage` to `events.Message` types. The switch does not break the 77 // backward compatibility so old `JSONMessage` could still be used. 78 // This test verifies that backward compatibility maintains. 79 func TestEventsBackwardsCompatible(t *testing.T) { 80 skip.If(t, testEnv.OSType == "windows", "Windows doesn't support back-compat messages") 81 defer setupTest(t)() 82 ctx := context.Background() 83 client := testEnv.APIClient() 84 85 since := request.DaemonTime(ctx, t, client, testEnv) 86 ts := strconv.FormatInt(since.Unix(), 10) 87 88 cID := container.Create(ctx, t, client) 89 90 // In case there is no events, the API should have responded immediately (not blocking), 91 // The test here makes sure the response time is less than 3 sec. 92 expectedTime := time.Now().Add(3 * time.Second) 93 emptyResp, emptyBody, err := req.Get("/events") 94 assert.NilError(t, err) 95 defer emptyBody.Close() 96 assert.Check(t, is.DeepEqual(http.StatusOK, emptyResp.StatusCode)) 97 assert.Check(t, time.Now().Before(expectedTime), "timeout waiting for events api to respond, should have responded immediately") 98 99 // We also test to make sure the `events.Message` is compatible with `JSONMessage` 100 q := url.Values{} 101 q.Set("since", ts) 102 _, body, err := req.Get("/events?" + q.Encode()) 103 assert.NilError(t, err) 104 defer body.Close() 105 106 dec := json.NewDecoder(body) 107 var containerCreateEvent *jsonmessage.JSONMessage 108 for { 109 var event jsonmessage.JSONMessage 110 if err := dec.Decode(&event); err != nil { 111 if err == io.EOF { 112 break 113 } 114 assert.NilError(t, err) 115 } 116 if event.Status == "create" && event.ID == cID { 117 containerCreateEvent = &event 118 break 119 } 120 } 121 122 assert.Check(t, containerCreateEvent != nil) 123 assert.Check(t, is.Equal("create", containerCreateEvent.Status)) 124 assert.Check(t, is.Equal(cID, containerCreateEvent.ID)) 125 assert.Check(t, is.Equal("busybox", containerCreateEvent.From)) 126 } 127 128 // TestEventsVolumeCreate verifies that volume create events are only fired 129 // once: when creating the volume, and not when attaching to a container. 130 func TestEventsVolumeCreate(t *testing.T) { 131 skip.If(t, testEnv.OSType == "windows", "FIXME: Windows doesn't trigger the events? Could be a race") 132 133 defer setupTest(t)() 134 ctx, cancel := context.WithCancel(context.Background()) 135 defer cancel() 136 137 client := testEnv.APIClient() 138 139 since := request.DaemonUnixTime(ctx, t, client, testEnv) 140 volName := t.Name() 141 getEvents := func(messages <-chan events.Message, errs <-chan error) ([]events.Message, error) { 142 var evts []events.Message 143 144 for { 145 select { 146 case m := <-messages: 147 evts = append(evts, m) 148 case err := <-errs: 149 if err == io.EOF { 150 return evts, nil 151 } 152 return nil, err 153 case <-time.After(time.Second * 3): 154 return nil, errors.New("timeout hit") 155 } 156 } 157 } 158 159 _, err := client.VolumeCreate(ctx, volume.CreateOptions{Name: volName}) 160 assert.NilError(t, err) 161 162 filter := filters.NewArgs( 163 filters.Arg("type", "volume"), 164 filters.Arg("event", "create"), 165 filters.Arg("volume", volName), 166 ) 167 messages, errs := client.Events(ctx, types.EventsOptions{ 168 Since: since, 169 Until: request.DaemonUnixTime(ctx, t, client, testEnv), 170 Filters: filter, 171 }) 172 173 volEvents, err := getEvents(messages, errs) 174 assert.NilError(t, err) 175 assert.Equal(t, len(volEvents), 1, "expected volume create event when creating a volume") 176 177 container.Create(ctx, t, client, container.WithMount(mount.Mount{ 178 Type: mount.TypeVolume, 179 Source: volName, 180 Target: "/tmp/foo", 181 })) 182 183 messages, errs = client.Events(ctx, types.EventsOptions{ 184 Since: since, 185 Until: request.DaemonUnixTime(ctx, t, client, testEnv), 186 Filters: filter, 187 }) 188 189 volEvents, err = getEvents(messages, errs) 190 assert.NilError(t, err) 191 assert.Equal(t, len(volEvents), 1, "expected volume create event to be fired only once") 192 }