(ctx context.Context, dockerCli command.Cli, opts *logsOptions)
| 71 | } |
| 72 | |
| 73 | func runLogs(ctx context.Context, dockerCli command.Cli, opts *logsOptions) error { //nolint:gocyclo |
| 74 | apiClient := dockerCli.Client() |
| 75 | |
| 76 | var ( |
| 77 | maxLength = 1 |
| 78 | responseBody io.ReadCloser |
| 79 | tty bool |
| 80 | ) |
| 81 | |
| 82 | service, err := apiClient.ServiceInspect(ctx, opts.target, client.ServiceInspectOptions{}) |
| 83 | if err != nil { |
| 84 | // if it's any error other than service not found, it's Real |
| 85 | if !errdefs.IsNotFound(err) { |
| 86 | return err |
| 87 | } |
| 88 | res, err := apiClient.TaskInspect(ctx, opts.target, client.TaskInspectOptions{}) |
| 89 | if err != nil { |
| 90 | if errdefs.IsNotFound(err) { |
| 91 | // if the task isn't found, rewrite the error to be clear |
| 92 | // that we looked for services AND tasks and found none |
| 93 | err = fmt.Errorf("no such task or service: %v", opts.target) |
| 94 | } |
| 95 | return err |
| 96 | } |
| 97 | |
| 98 | tty = res.Task.Spec.ContainerSpec.TTY |
| 99 | maxLength = getMaxLength(res.Task.Slot) |
| 100 | |
| 101 | // we can't prettify tty logs. tell the user that this is the case. |
| 102 | // this is why we assign the logs function to a variable and delay calling |
| 103 | // it. we want to check this before we make the call and checking twice in |
| 104 | // each branch is even sloppier than this CLI disaster already is |
| 105 | if tty && !opts.raw { |
| 106 | return errors.New("tty service logs only supported with --raw") |
| 107 | } |
| 108 | |
| 109 | // now get the logs |
| 110 | responseBody, err = apiClient.TaskLogs(ctx, opts.target, client.TaskLogsOptions{ |
| 111 | ShowStdout: true, |
| 112 | ShowStderr: true, |
| 113 | Since: opts.since, |
| 114 | Timestamps: opts.timestamps, |
| 115 | Follow: opts.follow, |
| 116 | Tail: opts.tail, |
| 117 | // get the details if we request it OR if we're not doing raw mode |
| 118 | // (we need them for the context to pretty print) |
| 119 | Details: opts.details || !opts.raw, |
| 120 | }) |
| 121 | if err != nil { |
| 122 | return err |
| 123 | } |
| 124 | defer responseBody.Close() |
| 125 | } else { |
| 126 | tty = service.Service.Spec.TaskTemplate.ContainerSpec.TTY |
| 127 | if service.Service.Spec.Mode.Replicated != nil && service.Service.Spec.Mode.Replicated.Replicas != nil { |
| 128 | // if replicas are initialized, figure out if we need to pad them |
| 129 | replicas := *service.Service.Spec.Mode.Replicated.Replicas |
| 130 | maxLength = getMaxLength(int(replicas)) |
no test coverage detected
searching dependent graphs…