streamPreStartLogs returns a channel that is closed once the hook log stream has been fully drained (or never opened). Callers must wait on it before returning so the goroutine cannot outlive the hook.
(ctx context.Context, containerID string, service types.ServiceConfig, index int, listener api.ContainerEventListener)
| 260 | // has been fully drained (or never opened). Callers must wait on it before |
| 261 | // returning so the goroutine cannot outlive the hook. |
| 262 | func (s *composeService) streamPreStartLogs(ctx context.Context, containerID string, service types.ServiceConfig, index int, listener api.ContainerEventListener) <-chan struct{} { |
| 263 | done := make(chan struct{}) |
| 264 | if listener == nil { |
| 265 | close(done) |
| 266 | return done |
| 267 | } |
| 268 | source := fmt.Sprintf("%s pre_start[%d] ->", service.Name, index) |
| 269 | logs, err := s.apiClient().ContainerLogs(ctx, containerID, client.ContainerLogsOptions{ |
| 270 | ShowStdout: true, |
| 271 | ShowStderr: true, |
| 272 | Follow: true, |
| 273 | }) |
| 274 | if err != nil { |
| 275 | listener(api.ContainerEvent{ |
| 276 | Type: api.HookEventLog, |
| 277 | Source: source, |
| 278 | ID: containerID, |
| 279 | Service: service.Name, |
| 280 | Line: fmt.Sprintf("warning: could not attach pre_start log stream: %s", err), |
| 281 | }) |
| 282 | close(done) |
| 283 | return done |
| 284 | } |
| 285 | go func() { |
| 286 | defer close(done) |
| 287 | defer logs.Close() //nolint:errcheck |
| 288 | w := utils.GetWriter(func(line string) { |
| 289 | listener(api.ContainerEvent{ |
| 290 | Type: api.HookEventLog, |
| 291 | Source: source, |
| 292 | ID: containerID, |
| 293 | Service: service.Name, |
| 294 | Line: line, |
| 295 | }) |
| 296 | }) |
| 297 | defer w.Close() //nolint:errcheck |
| 298 | _, _ = stdcopy.StdCopy(w, w, logs) |
| 299 | }() |
| 300 | return done |
| 301 | } |
no test coverage detected