Skip to content

Commit 24d0962

Browse files
committed
openshift: add functions for getting pod logs
Signed-off-by: Caleb Xu <caxu@redhat.com>
1 parent 0785116 commit 24d0962

File tree

4 files changed

+126
-7
lines changed

4 files changed

+126
-7
lines changed

internal/openshift/openshift.go

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package openshift
22

33
import (
4+
"bytes"
45
"context"
56
"fmt"
7+
"io"
68
"maps"
79

810
"github.com/go-logr/logr"
@@ -18,19 +20,22 @@ import (
1820
apierrors "k8s.io/apimachinery/pkg/api/errors"
1921
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2022
apiruntime "k8s.io/apimachinery/pkg/runtime"
23+
"k8s.io/client-go/kubernetes"
2124
crclient "sigs.k8s.io/controller-runtime/pkg/client"
2225
)
2326

2427
type openshiftClient struct {
25-
Client crclient.Client
28+
Client crclient.Client
29+
K8sInterface kubernetes.Interface
2630
}
2731

2832
// NewClient provides a wrapper around the passed in client in
2933
// order to present convenience functions for each of the object
3034
// types that are interacted with.
31-
func NewClient(client crclient.Client) Client {
35+
func NewClient(client crclient.Client, k8sInterface kubernetes.Interface) Client {
3236
var osclient Client = &openshiftClient{
33-
Client: client,
37+
Client: client,
38+
K8sInterface: k8sInterface,
3439
}
3540
return osclient
3641
}
@@ -546,3 +551,82 @@ func (oe *openshiftClient) GetDeploymentPods(ctx context.Context, name string, n
546551

547552
return podList.Items, nil
548553
}
554+
555+
// GetPod can return an ErrNotFound
556+
func (oe *openshiftClient) GetPod(ctx context.Context, name string, namespace string) (*corev1.Pod, error) {
557+
logger := logr.FromContextOrDiscard(ctx)
558+
559+
logger.V(log.TRC).Info("fetching pod", "namespace", namespace, "name", name)
560+
pod := corev1.Pod{}
561+
err := oe.Client.Get(ctx, crclient.ObjectKey{
562+
Name: name,
563+
Namespace: namespace,
564+
}, &pod)
565+
if apierrors.IsNotFound(err) {
566+
return nil, fmt.Errorf("could not retrieve pod: %s/%s: %w: %v", namespace, name, ErrNotFound, err)
567+
}
568+
if err != nil {
569+
return nil, fmt.Errorf("could not retrieve pod: %s/%s: %v", namespace, name, err)
570+
}
571+
return &pod, nil
572+
}
573+
574+
func (oe *openshiftClient) getContainerLogs(ctx context.Context, namespace string, pod string, container string) (*bytes.Buffer, error) {
575+
podLogOpts := corev1.PodLogOptions{
576+
Container: container,
577+
}
578+
req := oe.K8sInterface.CoreV1().Pods(namespace).GetLogs(pod, &podLogOpts)
579+
logs, err := req.Stream(ctx)
580+
if err != nil {
581+
return nil, fmt.Errorf("failed to open log stream: %s/%s/%s: %v", namespace, pod, container, err)
582+
}
583+
defer logs.Close()
584+
buf := new(bytes.Buffer)
585+
_, err = io.Copy(buf, logs)
586+
if err != nil {
587+
return nil, fmt.Errorf("failed to copy log stream: %s/%s/%s: %v", namespace, pod, container, err)
588+
}
589+
590+
return buf, nil
591+
}
592+
593+
// GetPodLogs can return an ErrNotFound
594+
func (oe *openshiftClient) GetPodLogs(ctx context.Context, name string, namespace string) (map[string]*bytes.Buffer, error) {
595+
logger := logr.FromContextOrDiscard(ctx)
596+
597+
pod, err := oe.GetPod(ctx, name, namespace)
598+
if err != nil {
599+
return nil, err
600+
}
601+
602+
results := map[string]*bytes.Buffer{}
603+
604+
for _, container := range pod.Spec.InitContainers {
605+
buf, err := oe.getContainerLogs(ctx, namespace, name, container.Name)
606+
if err != nil {
607+
logger.V(log.TRC).Info("failed to get pod logs", "error", err)
608+
continue
609+
}
610+
results[container.Name] = buf
611+
}
612+
613+
for _, container := range pod.Spec.Containers {
614+
buf, err := oe.getContainerLogs(ctx, namespace, name, container.Name)
615+
if err != nil {
616+
logger.V(log.TRC).Info("failed to get pod logs", "error", err)
617+
continue
618+
}
619+
results[container.Name] = buf
620+
}
621+
622+
for _, container := range pod.Spec.EphemeralContainers {
623+
buf, err := oe.getContainerLogs(ctx, namespace, name, container.Name)
624+
if err != nil {
625+
logger.V(log.TRC).Info("failed to get pod logs", "error", err)
626+
continue
627+
}
628+
results[container.Name] = buf
629+
}
630+
631+
return results, nil
632+
}

internal/openshift/openshift_test.go

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import (
1212
corev1 "k8s.io/api/core/v1"
1313
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1414
apiruntime "k8s.io/apimachinery/pkg/runtime"
15-
"sigs.k8s.io/controller-runtime/pkg/client/fake"
15+
fakecg "k8s.io/client-go/kubernetes/fake"
16+
fakecr "sigs.k8s.io/controller-runtime/pkg/client/fake"
1617
)
1718

1819
var _ = Describe("OpenShift Engine", func() {
@@ -152,12 +153,13 @@ var _ = Describe("OpenShift Engine", func() {
152153
scheme := apiruntime.NewScheme()
153154
Expect(AddSchemes(scheme)).To(Succeed())
154155
Expect(appsv1.AddToScheme(scheme)).To(Succeed())
155-
cl := fake.NewClientBuilder().
156+
cl := fakecr.NewClientBuilder().
156157
WithScheme(scheme).
157158
WithObjects(&csv, &deployment1, &deployment2, &deployment3).
158159
WithLists(&pods, &isList).
159160
Build()
160-
oc = NewClient(cl)
161+
cls := fakecg.NewClientset()
162+
oc = NewClient(cl, cls)
161163
})
162164
Context("Namespaces", func() {
163165
It("should exercise Namespaces", func() {
@@ -439,4 +441,24 @@ var _ = Describe("OpenShift Engine", func() {
439441
Expect(pods).To(BeNil())
440442
})
441443
})
444+
Context("Pods", func() {
445+
It("should get a Pod", func() {
446+
pod, err := oc.GetPod(context.TODO(), "pod1", "testns")
447+
Expect(err).ToNot(HaveOccurred())
448+
Expect(pod).ToNot(BeNil())
449+
})
450+
It("should error if Pod doesn't exist", func() {
451+
pod, err := oc.GetPod(context.TODO(), "pod3", "badns")
452+
Expect(err).To(HaveOccurred())
453+
Expect(err).To(MatchError(ErrNotFound))
454+
Expect(pod).To(BeNil())
455+
})
456+
It("should get Pod logs", func() {
457+
logs, err := oc.GetPodLogs(context.TODO(), "pod1", "testns")
458+
Expect(err).ToNot(HaveOccurred())
459+
Expect(len(logs)).To(Equal(2))
460+
Expect(logs["cont1"].String()).To(Equal("fake logs"))
461+
Expect(logs["cont2"].String()).To(Equal("fake logs"))
462+
})
463+
})
442464
})

internal/openshift/types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package openshift
22

33
import (
4+
"bytes"
45
"context"
56

67
operatorsv1 "github.com/operator-framework/api/pkg/operators/v1"
@@ -59,4 +60,6 @@ type Client interface {
5960
DeleteRoleBinding(ctx context.Context, name string, namespace string) error
6061
GetDeployment(ctx context.Context, name string, namespace string) (*appsv1.Deployment, error)
6162
GetDeploymentPods(ctx context.Context, name string, namespace string) ([]corev1.Pod, error)
63+
GetPod(ctx context.Context, name string, namespace string) (*corev1.Pod, error)
64+
GetPodLogs(ctx context.Context, name string, namespace string) (map[string]*bytes.Buffer, error)
6265
}

internal/policy/operator/deployable_by_olm.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
apiruntime "k8s.io/apimachinery/pkg/runtime"
3131
"k8s.io/apimachinery/pkg/runtime/schema"
3232
"k8s.io/apimachinery/pkg/util/validation"
33+
"k8s.io/client-go/kubernetes"
3334
ctrl "sigs.k8s.io/controller-runtime"
3435
crclient "sigs.k8s.io/controller-runtime/pkg/client"
3536
)
@@ -61,6 +62,7 @@ type DeployableByOlmCheck struct {
6162

6263
openshiftClient openshift.Client
6364
client crclient.Client
65+
k8sClientset kubernetes.Interface
6466
csvReady bool
6567
validImages bool
6668
csvTimeout time.Duration
@@ -96,12 +98,20 @@ func (p *DeployableByOlmCheck) initClient() error {
9698
}
9799

98100
p.client = client
101+
102+
k8sClientset, err := kubernetes.NewForConfig(kubeconfig)
103+
if err != nil {
104+
return fmt.Errorf("could not get k8s clientset: %w", err)
105+
}
106+
107+
p.k8sClientset = k8sClientset
108+
99109
return nil
100110
}
101111

102112
func (p *DeployableByOlmCheck) initOpenShiftEngine() {
103113
if p.openshiftClient == nil {
104-
p.openshiftClient = openshift.NewClient(p.client)
114+
p.openshiftClient = openshift.NewClient(p.client, p.k8sClientset)
105115
}
106116
}
107117

0 commit comments

Comments
 (0)