From 1c9349326d63c6f982b77e47d9f966e379a6d9d8 Mon Sep 17 00:00:00 2001 From: Philip Laine Date: Tue, 28 May 2024 14:18:47 +0200 Subject: [PATCH] refactor: remove use of k8s info and nodes --- src/internal/packager/helm/chart.go | 4 +- src/pkg/cluster/common.go | 2 +- src/pkg/cluster/injector.go | 2 +- src/pkg/cluster/tunnel.go | 5 ++- src/pkg/k8s/common.go | 21 ++++------- src/pkg/k8s/info.go | 57 ----------------------------- src/pkg/k8s/nodes.go | 23 ------------ src/pkg/k8s/pods.go | 13 ++++--- src/pkg/k8s/tunnel.go | 7 +++- src/pkg/packager/common.go | 30 ++++++++++----- 10 files changed, 50 insertions(+), 114 deletions(-) delete mode 100644 src/pkg/k8s/info.go delete mode 100644 src/pkg/k8s/nodes.go diff --git a/src/internal/packager/helm/chart.go b/src/internal/packager/helm/chart.go index 9252bf40d4..b145953173 100644 --- a/src/internal/packager/helm/chart.go +++ b/src/internal/packager/helm/chart.go @@ -370,12 +370,12 @@ func (h *Helm) loadChartData() (*chart.Chart, chartutil.Values, error) { func (h *Helm) migrateDeprecatedAPIs(latestRelease *release.Release) error { // Get the Kubernetes version from the current cluster - kubeVersion, err := h.cluster.GetServerVersion() + kubeVersion, err := h.cluster.Clientset.Discovery().ServerVersion() if err != nil { return err } - kubeGitVersion, err := semver.NewVersion(kubeVersion) + kubeGitVersion, err := semver.NewVersion(kubeVersion.String()) if err != nil { return err } diff --git a/src/pkg/cluster/common.go b/src/pkg/cluster/common.go index e0a295cd3c..02b6f1da78 100644 --- a/src/pkg/cluster/common.go +++ b/src/pkg/cluster/common.go @@ -56,7 +56,7 @@ func NewCluster() (*Cluster, error) { } // Dogsled the version output. We just want to ensure no errors were returned to validate cluster connection. - _, err = c.GetServerVersion() + _, err = c.Clientset.Discovery().ServerVersion() if err != nil { return nil, err } diff --git a/src/pkg/cluster/injector.go b/src/pkg/cluster/injector.go index 008df3915a..3412553d29 100644 --- a/src/pkg/cluster/injector.go +++ b/src/pkg/cluster/injector.go @@ -514,7 +514,7 @@ func (c *Cluster) getImagesAndNodesForInjection(ctx context.Context) (imageNodeM for _, pod := range pods.Items { nodeName := pod.Spec.NodeName - nodeDetails, err := c.GetNode(ctx, nodeName) + nodeDetails, err := c.Clientset.CoreV1().Nodes().Get(ctx, nodeName, metav1.GetOptions{}) if err != nil { return nil, fmt.Errorf("unable to get the node %q: %w", nodeName, err) } diff --git a/src/pkg/cluster/tunnel.go b/src/pkg/cluster/tunnel.go index 424881b2fc..122a57abf4 100644 --- a/src/pkg/cluster/tunnel.go +++ b/src/pkg/cluster/tunnel.go @@ -218,7 +218,10 @@ func (c *Cluster) checkForZarfConnectLabel(ctx context.Context, name string) (Tu zt.remotePort = svc.Spec.Ports[0].TargetPort.IntValue() // if targetPort == 0, look for Port (which is required) if zt.remotePort == 0 { - zt.remotePort = c.FindPodContainerPort(ctx, svc) + zt.remotePort, err = c.FindPodContainerPort(ctx, svc) + if err != nil { + return TunnelInfo{}, err + } } // Add the url suffix too. diff --git a/src/pkg/k8s/common.go b/src/pkg/k8s/common.go index 66434f3caa..9041775825 100644 --- a/src/pkg/k8s/common.go +++ b/src/pkg/k8s/common.go @@ -9,11 +9,11 @@ import ( "fmt" "time" - v1 "k8s.io/api/core/v1" - "k8s.io/klog/v2" - "github.com/go-logr/logr/funcr" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" + "k8s.io/klog/v2" // Include the cloud auth plugins _ "k8s.io/client-go/plugin/pkg/client/auth" @@ -48,12 +48,6 @@ func New(logger Log) (*K8s, error) { // WaitForHealthyCluster checks for an available K8s cluster every second until timeout. func (k *K8s) WaitForHealthyCluster(ctx context.Context) error { - var ( - err error - nodes *v1.NodeList - pods *v1.PodList - ) - const waitDuration = 1 * time.Second timer := time.NewTimer(0) @@ -77,15 +71,16 @@ func (k *K8s) WaitForHealthyCluster(ctx context.Context) error { } // Make sure there is at least one running Node - nodes, err = k.GetNodes(ctx) - if err != nil || len(nodes.Items) < 1 { + nodeList, err := k.Clientset.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) + if err != nil || len(nodeList.Items) < 1 { k.Log("No nodes reporting healthy yet: %v\n", err) timer.Reset(waitDuration) continue } // Get the cluster pod list - if pods, err = k.GetAllPods(ctx); err != nil { + pods, err := k.GetAllPods(ctx) + if err != nil { k.Log("Could not get the pod list: %w", err) timer.Reset(waitDuration) continue @@ -93,7 +88,7 @@ func (k *K8s) WaitForHealthyCluster(ctx context.Context) error { // Check that at least one pod is in the 'succeeded' or 'running' state for _, pod := range pods.Items { - if pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodRunning { + if pod.Status.Phase == corev1.PodSucceeded || pod.Status.Phase == corev1.PodRunning { return nil } } diff --git a/src/pkg/k8s/info.go b/src/pkg/k8s/info.go deleted file mode 100644 index 1a19a837e1..0000000000 --- a/src/pkg/k8s/info.go +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2021-Present The Zarf Authors - -// Package k8s provides a client for interacting with a Kubernetes cluster. -package k8s - -import ( - "context" - "errors" - "fmt" - "strings" -) - -// GetArchitectures returns the cluster system architectures if found. -func (k *K8s) GetArchitectures(ctx context.Context) ([]string, error) { - nodes, err := k.GetNodes(ctx) - if err != nil { - return nil, err - } - - if len(nodes.Items) == 0 { - return nil, errors.New("could not identify node architecture") - } - - archMap := map[string]bool{} - - for _, node := range nodes.Items { - archMap[node.Status.NodeInfo.Architecture] = true - } - - architectures := []string{} - - for arch := range archMap { - architectures = append(architectures, arch) - } - - return architectures, nil -} - -// GetServerVersion retrieves and returns the k8s revision. -func (k *K8s) GetServerVersion() (version string, err error) { - versionInfo, err := k.Clientset.Discovery().ServerVersion() - if err != nil { - return "", fmt.Errorf("unable to get Kubernetes version from the cluster : %w", err) - } - - return versionInfo.String(), nil -} - -// MakeLabels is a helper to format a map of label key and value pairs into a single string for use as a selector. -func MakeLabels(labels map[string]string) string { - var out []string - for key, value := range labels { - out = append(out, fmt.Sprintf("%s=%s", key, value)) - } - return strings.Join(out, ",") -} diff --git a/src/pkg/k8s/nodes.go b/src/pkg/k8s/nodes.go deleted file mode 100644 index 134c00b140..0000000000 --- a/src/pkg/k8s/nodes.go +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2021-Present The Zarf Authors - -// Package k8s provides a client for interacting with a Kubernetes cluster. -package k8s - -import ( - "context" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// GetNodes returns a list of nodes from the k8s cluster. -func (k *K8s) GetNodes(ctx context.Context) (*corev1.NodeList, error) { - metaOptions := metav1.ListOptions{} - return k.Clientset.CoreV1().Nodes().List(ctx, metaOptions) -} - -// GetNode returns a node from the k8s cluster. -func (k *K8s) GetNode(ctx context.Context, nodeName string) (*corev1.Node, error) { - return k.Clientset.CoreV1().Nodes().Get(ctx, nodeName, metav1.GetOptions{}) -} diff --git a/src/pkg/k8s/pods.go b/src/pkg/k8s/pods.go index be9c72bec4..cbdc77161b 100644 --- a/src/pkg/k8s/pods.go +++ b/src/pkg/k8s/pods.go @@ -178,13 +178,16 @@ func (k *K8s) WaitForPodsAndContainers(ctx context.Context, target PodLookup, in // FindPodContainerPort will find a pod's container port from a service and return it. // // Returns 0 if no port is found. -func (k *K8s) FindPodContainerPort(ctx context.Context, svc corev1.Service) int { - selectorLabelsOfPods := MakeLabels(svc.Spec.Selector) +func (k *K8s) FindPodContainerPort(ctx context.Context, svc corev1.Service) (int, error) { + selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{MatchLabels: svc.Spec.Selector}) + if err != nil { + return 0, err + } pods := k.WaitForPodsAndContainers( ctx, PodLookup{ Namespace: svc.Namespace, - Selector: selectorLabelsOfPods, + Selector: selector.String(), }, nil, ) @@ -194,11 +197,11 @@ func (k *K8s) FindPodContainerPort(ctx context.Context, svc corev1.Service) int for _, container := range pod.Spec.Containers { for _, port := range container.Ports { if port.Name == svc.Spec.Ports[0].TargetPort.String() { - return int(port.ContainerPort) + return int(port.ContainerPort), nil } } } } - return 0 + return 0, nil } diff --git a/src/pkg/k8s/tunnel.go b/src/pkg/k8s/tunnel.go index df49ac667a..7b890d2e20 100644 --- a/src/pkg/k8s/tunnel.go +++ b/src/pkg/k8s/tunnel.go @@ -254,13 +254,16 @@ func (tunnel *Tunnel) getAttachablePodForService(ctx context.Context) (string, e if err != nil { return "", fmt.Errorf("unable to find the service: %w", err) } - selectorLabelsOfPods := MakeLabels(service.Spec.Selector) + selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{MatchLabels: service.Spec.Selector}) + if err != nil { + return "", err + } servicePods := tunnel.kube.WaitForPodsAndContainers( ctx, PodLookup{ Namespace: tunnel.namespace, - Selector: selectorLabelsOfPods, + Selector: selector.String(), }, nil, ) diff --git a/src/pkg/packager/common.go b/src/pkg/packager/common.go index f432b8d423..938167e52c 100644 --- a/src/pkg/packager/common.go +++ b/src/pkg/packager/common.go @@ -9,23 +9,23 @@ import ( "errors" "fmt" "os" - "strings" - "slices" + "strings" "github.com/Masterminds/semver/v3" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/defenseunicorns/zarf/src/config" "github.com/defenseunicorns/zarf/src/config/lang" "github.com/defenseunicorns/zarf/src/internal/packager/template" "github.com/defenseunicorns/zarf/src/pkg/cluster" - "github.com/defenseunicorns/zarf/src/pkg/variables" - "github.com/defenseunicorns/zarf/src/types" - - "github.com/defenseunicorns/zarf/src/config" "github.com/defenseunicorns/zarf/src/pkg/layout" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/packager/deprecated" "github.com/defenseunicorns/zarf/src/pkg/packager/sources" "github.com/defenseunicorns/zarf/src/pkg/utils" + "github.com/defenseunicorns/zarf/src/pkg/variables" + "github.com/defenseunicorns/zarf/src/types" ) // Packager is the main struct for managing packages. @@ -227,14 +227,26 @@ func (p *Packager) validatePackageArchitecture(ctx context.Context) error { return nil } - clusterArchitectures, err := p.cluster.GetArchitectures(ctx) + // Get node architectures + nodeList, err := p.cluster.Clientset.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) if err != nil { return lang.ErrUnableToCheckArch } + if len(nodeList.Items) == 0 { + return lang.ErrUnableToCheckArch + } + archMap := map[string]bool{} + for _, node := range nodeList.Items { + archMap[node.Status.NodeInfo.Architecture] = true + } + architectures := []string{} + for arch := range archMap { + architectures = append(architectures, arch) + } // Check if the package architecture and the cluster architecture are the same. - if !slices.Contains(clusterArchitectures, p.cfg.Pkg.Metadata.Architecture) { - return fmt.Errorf(lang.CmdPackageDeployValidateArchitectureErr, p.cfg.Pkg.Metadata.Architecture, strings.Join(clusterArchitectures, ", ")) + if !slices.Contains(architectures, p.cfg.Pkg.Metadata.Architecture) { + return fmt.Errorf(lang.CmdPackageDeployValidateArchitectureErr, p.cfg.Pkg.Metadata.Architecture, strings.Join(architectures, ", ")) } return nil