(ctx context.Context, client *containerd.Client, container string, options types.ContainerLogsOptions)
| 40 | ) |
| 41 | |
| 42 | func Logs(ctx context.Context, client *containerd.Client, container string, options types.ContainerLogsOptions) error { |
| 43 | dataStore, err := clientutil.DataStore(options.GOptions.DataRoot, options.GOptions.Address) |
| 44 | if err != nil { |
| 45 | return err |
| 46 | } |
| 47 | |
| 48 | switch options.GOptions.Namespace { |
| 49 | case "moby": |
| 50 | log.G(ctx).Warn("Currently, `nerdctl logs` only supports containers created with `nerdctl run -d` or CRI") |
| 51 | } |
| 52 | |
| 53 | stopChannel := make(chan os.Signal, 1) |
| 54 | // catch OS signals: |
| 55 | signal.Notify(stopChannel, syscall.SIGTERM, syscall.SIGINT) |
| 56 | |
| 57 | walker := &containerwalker.ContainerWalker{ |
| 58 | Client: client, |
| 59 | OnFound: func(ctx context.Context, found containerwalker.Found) error { |
| 60 | if found.MatchCount > 1 { |
| 61 | return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) |
| 62 | } |
| 63 | l, err := found.Container.Labels(ctx) |
| 64 | if err != nil { |
| 65 | return err |
| 66 | } |
| 67 | |
| 68 | logPath, err := getLogPath(ctx, found.Container) |
| 69 | if err != nil { |
| 70 | return err |
| 71 | } |
| 72 | |
| 73 | follow := options.Follow |
| 74 | if follow { |
| 75 | task, err := found.Container.Task(ctx, nil) |
| 76 | if err != nil { |
| 77 | if !errdefs.IsNotFound(err) { |
| 78 | return err |
| 79 | } |
| 80 | follow = false |
| 81 | } else { |
| 82 | status, err := task.Status(ctx) |
| 83 | if err != nil { |
| 84 | return err |
| 85 | } |
| 86 | if status.Status != containerd.Running { |
| 87 | follow = false |
| 88 | } else { |
| 89 | waitCh, err := task.Wait(ctx) |
| 90 | if err != nil { |
| 91 | return fmt.Errorf("failed to get wait channel for task %#v: %w", task, err) |
| 92 | } |
| 93 | |
| 94 | // Setup goroutine to send stop event if container task finishes: |
| 95 | go func() { |
| 96 | <-waitCh |
| 97 | // Wait for logger to process remaining logs after container exit |
| 98 | if err = logging.WaitForLogger(dataStore, l[labels.Namespace], found.Container.ID()); err != nil { |
| 99 | log.G(ctx).WithError(err).Error("failed to wait for logger shutdown") |
no test coverage detected
searching dependent graphs…