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