package pod
import (
"context"
"fmt"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
type LogResult struct {
Namespace string
PodName string
ContainerName string
Log string
}
func GetLogsByPod(ctx context.Context, client kubernetes.Interface, namespace, podName, containerName string) (*LogResult, error) {
if client == nil {
return nil, fmt.Errorf("kubernetes client is nil")
}
if podName == "" {
return nil, fmt.Errorf("pod name is required")
}
if containerName == "" {
return nil, fmt.Errorf("container name is required")
}
pod, err := client.CoreV1().Pods(namespace).Get(ctx, podName, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("failed to get pod %s/%s: %w", namespace, podName, err)
}
containerName, err = checkontainerByName(pod, containerName)
if err != nil {
return nil, err
}
res, err := collectPodLog(ctx, client, pod, containerName)
if err != nil {
return nil, err
}
return &res, nil
}
func GetLogsByPodLabel(ctx context.Context, client kubernetes.Interface, namespace, labelSelector, containerName string) ([]LogResult, error) {
if client == nil {
return nil, fmt.Errorf("kubernetes client is nil")
}
if containerName == "" {
return nil, fmt.Errorf("container name is required")
}
pods, err := client.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{LabelSelector: labelSelector})
if err != nil {
return nil, fmt.Errorf("list pods in namespace %s: %w", namespace, err)
}
if len(pods.Items) == 0 {
return nil, fmt.Errorf("no matched pod found")
}
results := make([]LogResult, 0, len(pods.Items))
for i := range pods.Items {
pod := &pods.Items[i]
logRes, err := collectPodLog(ctx, client, pod, containerName)
if err != nil {
return nil, err
}
results = append(results, logRes)
}
return results, nil
}
func collectPodLog(ctx context.Context, client kubernetes.Interface, pod *corev1.Pod, containerName string) (LogResult, error) {
cName, err := checkontainerByName(pod, containerName)
if err != nil {
return LogResult{}, err
}
req := client.CoreV1().Pods(pod.Namespace).GetLogs(pod.Name, &corev1.PodLogOptions{
Container: cName,
})
raw, err := req.Do(ctx).Raw()
if err != nil {
return LogResult{}, fmt.Errorf("get log for pod %s/%s: %w", pod.Namespace, pod.Name, err)
}
return LogResult{
ContainerName: containerName,
PodName: pod.Name,
Namespace: pod.Namespace,
Log: string(raw),
}, nil
}
func checkontainerByName(pod *corev1.Pod, containerName string) (string, error) {
if pod == nil {
return "", fmt.Errorf("pod is nil")
}
if len(pod.Spec.Containers) == 0 {
return "", fmt.Errorf("pod %s/%s has no containers", pod.Namespace, pod.Name)
}
if containerName == "" {
return "", fmt.Errorf("container name is not provided")
}
for _, c := range pod.Spec.Containers {
if c.Name == containerName {
return c.Name, nil
}
}
return "", fmt.Errorf("container %s not found in pod %s/%s", containerName, pod.Namespace, pod.Name)
}