SingleStream streams the cluster's pod logs and shunts them to a single io.Writer
(ctx context.Context, writer io.Writer)
| 169 | |
| 170 | // SingleStream streams the cluster's pod logs and shunts them to a single io.Writer |
| 171 | func (csr *ClusterWriter) SingleStream(ctx context.Context, writer io.Writer) error { |
| 172 | client := csr.getKubernetesClient() |
| 173 | streamSet := newActiveSet() |
| 174 | defer func() { |
| 175 | // try to cancel the streaming goroutines |
| 176 | ctx.Done() |
| 177 | }() |
| 178 | isFirstScan := true |
| 179 | |
| 180 | for { |
| 181 | var ( |
| 182 | podList *corev1.PodList |
| 183 | err error |
| 184 | ) |
| 185 | if isFirstScan || csr.Options.Follow { |
| 186 | podList, err = client.CoreV1().Pods(csr.getClusterNamespace()).List(ctx, metav1.ListOptions{ |
| 187 | LabelSelector: utils.ClusterLabelName + "=" + csr.getClusterName(), |
| 188 | }) |
| 189 | if err != nil { |
| 190 | return err |
| 191 | } |
| 192 | isFirstScan = false |
| 193 | } else { |
| 194 | streamSet.wait() |
| 195 | return nil |
| 196 | } |
| 197 | if len(podList.Items) == 0 && streamSet.isZero() { |
| 198 | log.Printf("no pods to log in namespace %s", csr.getClusterNamespace()) |
| 199 | return nil |
| 200 | } |
| 201 | |
| 202 | wrappedWriter := safeWriterFrom(writer) |
| 203 | for _, pod := range podList.Items { |
| 204 | for _, container := range pod.Status.ContainerStatuses { |
| 205 | if container.State.Running != nil { |
| 206 | streamName := fmt.Sprintf("%s-%s", pod.Name, container.Name) |
| 207 | if streamSet.has(streamName) { |
| 208 | continue |
| 209 | } |
| 210 | |
| 211 | streamSet.add(streamName) |
| 212 | go csr.streamInGoroutine( |
| 213 | ctx, |
| 214 | pod.Name, |
| 215 | container.Name, |
| 216 | client, |
| 217 | streamSet, |
| 218 | wrappedWriter, |
| 219 | ) |
| 220 | } |
| 221 | } |
| 222 | } |
| 223 | if !csr.Options.Follow && streamSet.isZero() { |
| 224 | return nil |
| 225 | } |
| 226 | |
| 227 | select { |
| 228 | case <-ctx.Done(): |
no test coverage detected