package kube import ( "context" "io" "time" //nolint:staticcheck // ST1001 . "github.com/onsi/ginkgo/v2" //nolint:staticcheck // ST1001 . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" "sigs.k8s.io/controller-runtime/pkg/client" ) type Pod struct { client client.Client clientset kubernetes.Interface config *Config selector map[string]string } func (p *Pod) WaitingForRunningPod(ctx context.Context) { By("Waiting for the pod " + labels.Set(p.selector).String() + " to be 'Running'") Eventually(func(g Gomega) { // short per-attempt timeout to avoid hanging calls while Eventually polls attemptCtx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() var pods corev1.PodList listOpts := []client.ListOption{ client.InNamespace(p.config.Namespace), client.MatchingLabels(p.selector), } g.Expect(p.client.List(attemptCtx, &pods, listOpts...)).To(Succeed()) g.Expect(pods.Items).NotTo(BeEmpty(), "no pods found with selector %q", labels.Set(p.selector).String()) foundRunning := false for _, p := range pods.Items { if p.Status.Phase == corev1.PodRunning { foundRunning = true break } } g.Expect(foundRunning).To(BeTrue(), "pod not Running yet") }, p.config.TestConfig.Timeout, p.config.TestConfig.Interval).Should(Succeed()) } func (p *Pod) GetPodLogs(ctx context.Context) string { // First find the pod by label selector var pods corev1.PodList listOpts := []client.ListOption{ client.InNamespace(p.config.Namespace), client.MatchingLabels(p.selector), } err := p.client.List(ctx, &pods, listOpts...) Expect(err).NotTo(HaveOccurred()) Expect(pods.Items).NotTo(BeEmpty(), "no pods found with selector %q", labels.Set(p.selector).String()) // Find a running pod to get logs from var pod *corev1.Pod for i := range pods.Items { if pods.Items[i].Status.Phase == corev1.PodRunning { pod = &pods.Items[i] break } } Expect(pod).NotTo(BeNil(), "no running pod found with selector %q", labels.Set(p.selector).String()) podName := pod.Name // Get logs using the Kubernetes clientset req := p.clientset.CoreV1().Pods(p.config.Namespace).GetLogs(podName, &corev1.PodLogOptions{}) stream, err := req.Stream(context.TODO()) Expect(err).NotTo(HaveOccurred(), "failed to stream logs for pod %s", podName) defer stream.Close() // Read all logs from the stream logs, err := io.ReadAll(stream) Expect(err).NotTo(HaveOccurred(), "failed to read logs for pod %s", podName) return string(logs) } func (p *Pod) VerifyWebhookInjection(ctx context.Context) { By("Verifying webhook injection for pod with selector " + labels.Set(p.selector).String()) Eventually(func(g Gomega) { // short per-attempt timeout to avoid hanging calls while Eventually polls attemptCtx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() // First find the pod by label selector var pods corev1.PodList listOpts := []client.ListOption{ client.InNamespace(p.config.Namespace), client.MatchingLabels(p.selector), } g.Expect(p.client.List(attemptCtx, &pods, listOpts...)).To(Succeed()) g.Expect(pods.Items).NotTo(BeEmpty(), "no pods found with selector %q", labels.Set(p.selector).String()) // Find a running pod to verify webhook injection var pod *corev1.Pod for i := range pods.Items { if pods.Items[i].Status.Phase == corev1.PodRunning { pod = &pods.Items[i] break } } g.Expect(pod).NotTo(BeNil(), "no running pod found with selector %q", labels.Set(p.selector).String()) // Check injection status annotation g.Expect(pod.Annotations).To(HaveKey("operator.1password.io/status")) g.Expect(pod.Annotations["operator.1password.io/status"]).To(Equal("injected")) // Check command was modified to use op run if len(pod.Spec.Containers) > 0 { container := pod.Spec.Containers[0] g.Expect(container.Command).To(HaveLen(4)) g.Expect(container.Command[0]).To(Equal("/op/bin/op")) g.Expect(container.Command[1]).To(Equal("run")) g.Expect(container.Command[2]).To(Equal("--")) } // Check init container was added g.Expect(pod.Spec.InitContainers).To(HaveLen(1)) g.Expect(pod.Spec.InitContainers[0].Name).To(Equal("copy-op-bin")) // Check volume mount was added g.Expect(pod.Spec.Containers[0].VolumeMounts).To(ContainElement(HaveField("Name", "op-bin"))) }, p.config.TestConfig.Timeout, p.config.TestConfig.Interval).Should(Succeed()) } func (p *Pod) VerifySecretsInjected(ctx context.Context) { By("Verifying secrets are injected and concealed in pod with selector " + labels.Set(p.selector).String()) Eventually(func(g Gomega) { // short per-attempt timeout to avoid hanging calls while Eventually polls attemptCtx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() logs := p.GetPodLogs(attemptCtx) // Check that secrets are concealed in the application logs g.Expect(logs).To(ContainSubstring("SECRET: ''")) }, p.config.TestConfig.Timeout, p.config.TestConfig.Interval).Should(Succeed()) }