2022-06-02 12:56:07 +03:00
|
|
|
package e2e
|
|
|
|
|
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the Apache License 2.0.
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2022-10-11 15:50:37 +03:00
|
|
|
"fmt"
|
2022-06-02 12:56:07 +03:00
|
|
|
"net/http"
|
|
|
|
"net/url"
|
2022-10-11 15:50:37 +03:00
|
|
|
"strings"
|
2022-06-02 12:56:07 +03:00
|
|
|
|
2022-06-15 03:10:42 +03:00
|
|
|
. "github.com/onsi/ginkgo/v2"
|
2022-06-02 12:56:07 +03:00
|
|
|
. "github.com/onsi/gomega"
|
|
|
|
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
)
|
|
|
|
|
|
|
|
var _ = Describe("[Admin API] Kubernetes get pod logs action", func() {
|
|
|
|
BeforeEach(skipIfNotInDevelopmentEnv)
|
|
|
|
|
|
|
|
const containerName = "e2e-test-container-name"
|
|
|
|
const podName = "e2e-test-pod-name"
|
|
|
|
|
|
|
|
When("in a standard openshift namespace", func() {
|
|
|
|
const namespace = "openshift-azure-operator"
|
|
|
|
|
2022-10-31 19:19:20 +03:00
|
|
|
It("must be able to get logs from a container of a pod", func(ctx context.Context) {
|
2022-06-02 12:56:07 +03:00
|
|
|
testGetPodLogsOK(ctx, containerName, podName, namespace)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
When("in a customer namespace", func() {
|
|
|
|
const namespace = "e2e-test-namespace"
|
|
|
|
|
2022-10-31 19:19:20 +03:00
|
|
|
It("must be not be able to get logs from customer workload namespaces", func(ctx context.Context) {
|
2022-06-02 12:56:07 +03:00
|
|
|
testGetPodLogsFromCustomerNamespaceForbidden(ctx, containerName, podName, namespace)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
// We will create a pod with known logs of its container and will compare the logs gotten through the kubernetes client and through the Admin API.
|
|
|
|
func testGetPodLogsOK(ctx context.Context, containerName, podName, namespace string) {
|
2022-10-11 15:50:37 +03:00
|
|
|
expectedLog := "mock-pod-logs"
|
|
|
|
|
|
|
|
By("creating a test pod in openshift-azure-operator namespace with some known logs")
|
|
|
|
pod := mockPod(containerName, podName, namespace, expectedLog)
|
2024-03-12 10:56:18 +03:00
|
|
|
CreateK8sObjectWithRetry(
|
2024-02-07 23:28:37 +03:00
|
|
|
ctx, clients.Kubernetes.CoreV1().Pods(namespace).Create, pod, metav1.CreateOptions{},
|
|
|
|
)
|
2022-10-11 15:50:37 +03:00
|
|
|
|
2022-06-02 12:56:07 +03:00
|
|
|
defer func() {
|
2022-10-11 15:50:37 +03:00
|
|
|
By("deleting the test pod")
|
2024-02-07 23:28:37 +03:00
|
|
|
DeleteK8sObjectWithRetry(
|
2024-03-12 10:56:18 +03:00
|
|
|
ctx, clients.Kubernetes.CoreV1().Pods(namespace).Delete, podName, metav1.DeleteOptions{},
|
2024-02-07 23:28:37 +03:00
|
|
|
)
|
2022-06-02 12:56:07 +03:00
|
|
|
}()
|
2022-10-11 15:50:37 +03:00
|
|
|
|
|
|
|
By("waiting for the pod to successfully terminate")
|
2022-11-15 15:18:14 +03:00
|
|
|
Eventually(func(g Gomega, ctx context.Context) {
|
2024-02-07 23:28:37 +03:00
|
|
|
pod = GetK8sObjectWithRetry(
|
2024-03-12 10:56:18 +03:00
|
|
|
ctx, clients.Kubernetes.CoreV1().Pods(namespace).Get, podName, metav1.GetOptions{},
|
2024-02-07 23:28:37 +03:00
|
|
|
)
|
2022-11-15 15:18:14 +03:00
|
|
|
g.Expect(pod.Status.Phase).To(Equal(corev1.PodSucceeded))
|
2023-10-15 00:52:39 +03:00
|
|
|
}).WithContext(ctx).WithTimeout(DefaultEventuallyTimeout).Should(Succeed())
|
2022-06-02 12:56:07 +03:00
|
|
|
|
2022-10-11 15:50:37 +03:00
|
|
|
By("requesting logs via RP admin API")
|
2022-06-02 12:56:07 +03:00
|
|
|
params := url.Values{
|
|
|
|
"container": []string{containerName},
|
|
|
|
"namespace": []string{namespace},
|
|
|
|
"podname": []string{podName},
|
|
|
|
}
|
|
|
|
var logs string
|
2023-02-14 18:43:58 +03:00
|
|
|
resp, err := adminRequest(ctx, http.MethodGet, "/admin"+clusterResourceID+"/kubernetespodlogs", params, true, nil, &logs)
|
2022-06-02 12:56:07 +03:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
|
|
|
|
2022-10-11 15:50:37 +03:00
|
|
|
By("verifying that logs received from RP match known logs")
|
|
|
|
Expect(strings.TrimRight(logs, "\n")).To(Equal(expectedLog))
|
2022-06-02 12:56:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func testGetPodLogsFromCustomerNamespaceForbidden(ctx context.Context, containerName, podName, namespace string) {
|
2022-10-11 15:50:37 +03:00
|
|
|
By("requesting logs via RP admin API")
|
2022-06-02 12:56:07 +03:00
|
|
|
params := url.Values{
|
|
|
|
"container": []string{containerName},
|
|
|
|
"namespace": []string{namespace},
|
|
|
|
"podname": []string{podName},
|
|
|
|
}
|
2022-10-11 15:50:37 +03:00
|
|
|
|
|
|
|
var logs string
|
2023-02-14 18:43:58 +03:00
|
|
|
resp, err := adminRequest(ctx, http.MethodGet, "/admin"+clusterResourceID+"/kubernetespodlogs", params, true, nil, logs)
|
2022-06-02 12:56:07 +03:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(resp.StatusCode).To(Equal(http.StatusForbidden))
|
2022-10-11 15:50:37 +03:00
|
|
|
|
|
|
|
By("verifying that we not receive any logs from RP")
|
|
|
|
Expect(strings.TrimRight(logs, "\n")).To(BeEmpty())
|
2022-06-02 12:56:07 +03:00
|
|
|
}
|
|
|
|
|
2022-10-11 15:50:37 +03:00
|
|
|
func mockPod(containerName, podName, namespace, fakeLog string) *corev1.Pod {
|
2022-06-02 12:56:07 +03:00
|
|
|
return &corev1.Pod{
|
|
|
|
TypeMeta: metav1.TypeMeta{
|
|
|
|
Kind: "Pod",
|
|
|
|
APIVersion: "v1",
|
|
|
|
},
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: podName,
|
|
|
|
Namespace: namespace,
|
|
|
|
},
|
|
|
|
Spec: corev1.PodSpec{
|
|
|
|
Containers: []corev1.Container{{
|
|
|
|
Name: containerName,
|
2023-09-13 03:33:31 +03:00
|
|
|
Image: "image-registry.openshift-image-registry.svc:5000/openshift/cli:latest",
|
2022-10-11 15:50:37 +03:00
|
|
|
Command: []string{"/bin/bash", "-c", fmt.Sprintf("echo %q", fakeLog)},
|
2022-06-02 12:56:07 +03:00
|
|
|
}},
|
|
|
|
RestartPolicy: "Never",
|
|
|
|
HostNetwork: true,
|
|
|
|
HostPID: true,
|
|
|
|
},
|
|
|
|
Status: corev1.PodStatus{},
|
|
|
|
}
|
|
|
|
}
|