Skip to content

Commit

Permalink
Merge branch 'main' into required-components
Browse files Browse the repository at this point in the history
  • Loading branch information
Noxsios committed May 22, 2024
2 parents ece00d1 + b8dd1bb commit 7cc9973
Show file tree
Hide file tree
Showing 9 changed files with 531 additions and 129 deletions.
10 changes: 9 additions & 1 deletion .github/workflows/test-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,17 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Run coverage
run: go test -race -coverprofile=coverage.out -covermode=atomic

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # v4.4.1
with:
token: ${{ secrets.CODECOV_TOKEN }}

- name: Setup golang
uses: ./.github/actions/golang

- name: Run unit tests
run: make test-unit
run: make test-unit
101 changes: 101 additions & 0 deletions src/pkg/cluster/distro.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

// Package cluster contains Zarf-specific cluster management functions.
package cluster

import (
"regexp"

corev1 "k8s.io/api/core/v1"
)

// List of supported distros via distro detection.
const (
DistroIsUnknown = "unknown"
DistroIsK3s = "k3s"
DistroIsK3d = "k3d"
DistroIsKind = "kind"
DistroIsMicroK8s = "microk8s"
DistroIsEKS = "eks"
DistroIsEKSAnywhere = "eksanywhere"
DistroIsDockerDesktop = "dockerdesktop"
DistroIsGKE = "gke"
DistroIsAKS = "aks"
DistroIsRKE2 = "rke2"
DistroIsTKG = "tkg"
)

// DetectDistro returns the matching distro or unknown if not found.
func detectDistro(node corev1.Node, namespaces []corev1.Namespace) string {
kindNodeRegex := regexp.MustCompile(`^kind://`)
k3dNodeRegex := regexp.MustCompile(`^k3s://k3d-`)
eksNodeRegex := regexp.MustCompile(`^aws:///`)
gkeNodeRegex := regexp.MustCompile(`^gce://`)
aksNodeRegex := regexp.MustCompile(`^azure:///subscriptions`)
rke2Regex := regexp.MustCompile(`^rancher/rancher-agent:v2`)
tkgRegex := regexp.MustCompile(`^projects\.registry\.vmware\.com/tkg/tanzu_core/`)

// Regex explanation: https://regex101.com/r/TIUQVe/1
// https://github.com/rancher/k3d/blob/v5.2.2/cmd/node/nodeCreate.go#L187
if k3dNodeRegex.MatchString(node.Spec.ProviderID) {
return DistroIsK3d
}

// Regex explanation: https://regex101.com/r/le7PRB/1
// https://github.com/kubernetes-sigs/kind/pull/1805
if kindNodeRegex.MatchString(node.Spec.ProviderID) {
return DistroIsKind
}

// https://github.com/kubernetes/cloud-provider-aws/blob/454ed784c33b974c873c7d762f9d30e7c4caf935/pkg/providers/v2/instances.go#L234
if eksNodeRegex.MatchString(node.Spec.ProviderID) {
return DistroIsEKS
}

if gkeNodeRegex.MatchString(node.Spec.ProviderID) {
return DistroIsGKE
}

// https://github.com/kubernetes/kubernetes/blob/v1.23.4/staging/src/k8s.io/legacy-cloud-providers/azure/azure_wrap.go#L46
if aksNodeRegex.MatchString(node.Spec.ProviderID) {
return DistroIsAKS
}

labels := node.GetLabels()
for k, v := range labels {
// kubectl get nodes --selector node.kubernetes.io/instance-type=k3s for K3s
if k == "node.kubernetes.io/instance-type" && v == "k3s" {
return DistroIsK3s
}
// kubectl get nodes --selector microk8s.io/cluster=true for MicroK8s
if k == "microk8s.io/cluster" && v == "true" {
return DistroIsMicroK8s
}
}

if node.GetName() == "docker-desktop" {
return DistroIsDockerDesktop
}

// TODO: Find a new detection method, by default the amount of images in the node status is limited.
for _, images := range node.Status.Images {
for _, image := range images.Names {
if rke2Regex.MatchString(image) {
return DistroIsRKE2
}
if tkgRegex.MatchString(image) {
return DistroIsTKG
}
}
}

// kubectl get ns eksa-system for EKS Anywhere
for _, namespace := range namespaces {
if namespace.Name == "eksa-system" {
return DistroIsEKSAnywhere
}
}

return DistroIsUnknown
}
181 changes: 181 additions & 0 deletions src/pkg/cluster/distro_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

// Package cluster contains Zarf-specific cluster management functions.
package cluster

import (
"testing"

"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestDetectDistro(t *testing.T) {
t.Parallel()

tests := []struct {
distro string
node corev1.Node
namespaces []corev1.Namespace
}{
{
distro: DistroIsUnknown,
node: corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"foo": "bar",
},
},
Spec: corev1.NodeSpec{
ProviderID: "hello world",
},
},
namespaces: []corev1.Namespace{
{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
},
},
},
},
{
distro: DistroIsK3s,
node: corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"node.kubernetes.io/instance-type": "k3s",
},
},
},
},
{
distro: DistroIsK3d,
node: corev1.Node{
Spec: corev1.NodeSpec{
ProviderID: "k3s://k3d-k3s-default-server-0",
},
},
},
{
distro: DistroIsKind,
node: corev1.Node{
Spec: corev1.NodeSpec{
ProviderID: "kind://docker/kind/kind-control-plane",
},
},
},
{
distro: DistroIsMicroK8s,
node: corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"microk8s.io/cluster": "true",
},
},
},
},
{
distro: DistroIsEKS,
node: corev1.Node{
Spec: corev1.NodeSpec{
ProviderID: "aws:////i-112bac41a19da1819",
},
},
},
{
distro: DistroIsEKSAnywhere,
namespaces: []corev1.Namespace{
{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "eksa-system",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "baz",
},
},
},
},
{
distro: DistroIsDockerDesktop,
node: corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "docker-desktop",
},
},
},
{
distro: DistroIsGKE,
node: corev1.Node{
Spec: corev1.NodeSpec{
ProviderID: "gce://kthw-239419/us-central1-f/gk3-autopilot-cluster-1-pool-2-e87e560a-7gvw",
},
},
},
{
distro: DistroIsAKS,
node: corev1.Node{
Spec: corev1.NodeSpec{
ProviderID: "azure:///subscriptions/9107f2fb-e486-a434-a948-52e2929b6f18/resourceGroups/MC_rg_capz-managed-aks_eastus/providers/Microsoft.Compute/virtualMachineScaleSets/aks-agentpool0-10226072-vmss/virtualMachines/0",
},
},
},
{
distro: DistroIsRKE2,
node: corev1.Node{
Status: corev1.NodeStatus{
Images: []corev1.ContainerImage{
{
Names: []string{"docker.io/library/ubuntu:latest"},
},
{
Names: []string{"rancher/rancher-agent:v2"},
},
},
},
},
},
{
distro: DistroIsTKG,
node: corev1.Node{
Status: corev1.NodeStatus{
Images: []corev1.ContainerImage{
{
Names: []string{"docker.io/library/ubuntu:latest"},
},
{
Names: []string{"projects.registry.vmware.com/tkg/tanzu_core/"},
},
},
},
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.distro, func(t *testing.T) {
t.Parallel()

distro := detectDistro(tt.node, tt.namespaces)
require.Equal(t, tt.distro, distro)
})
}
}
23 changes: 15 additions & 8 deletions src/pkg/cluster/injector.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (c *Cluster) StartInjectionMadness(ctx context.Context, tmpDir string, imag
}

spinner.Updatef("Creating the injector configmap")
if err = c.createInjectorConfigmap(ctx, tmp.InjectionBinary); err != nil {
if err = c.createInjectorConfigMap(ctx, tmp.InjectionBinary); err != nil {
spinner.Fatalf(err, "Unable to create the injector configmap")
}

Expand All @@ -90,7 +90,7 @@ func (c *Cluster) StartInjectionMadness(ctx context.Context, tmpDir string, imag
}

spinner.Updatef("Loading the seed registry configmaps")
if payloadConfigmaps, sha256sum, err = c.createPayloadConfigmaps(ctx, tmp.SeedImagesDir, tmp.InjectorPayloadTarGz, spinner); err != nil {
if payloadConfigmaps, sha256sum, err = c.createPayloadConfigMaps(ctx, tmp.SeedImagesDir, tmp.InjectorPayloadTarGz, spinner); err != nil {
spinner.Fatalf(err, "Unable to generate the injector payload configmaps")
}

Expand Down Expand Up @@ -197,7 +197,7 @@ func (c *Cluster) loadSeedImages(imagesDir, seedImagesDir string, injectorSeedSr
return seedImages, nil
}

func (c *Cluster) createPayloadConfigmaps(ctx context.Context, seedImagesDir, tarPath string, spinner *message.Spinner) ([]string, string, error) {
func (c *Cluster) createPayloadConfigMaps(ctx context.Context, seedImagesDir, tarPath string, spinner *message.Spinner) ([]string, string, error) {
var configMaps []string

// Chunk size has to accommodate base64 encoding & etcd 1MB limit
Expand Down Expand Up @@ -285,7 +285,7 @@ func (c *Cluster) injectorIsReady(ctx context.Context, seedImages []transform.Im
return true
}

func (c *Cluster) createInjectorConfigmap(ctx context.Context, binaryPath string) error {
func (c *Cluster) createInjectorConfigMap(ctx context.Context, binaryPath string) error {
var err error
configData := make(map[string][]byte)

Expand Down Expand Up @@ -473,10 +473,8 @@ func (c *Cluster) getImagesAndNodesForInjection(ctx context.Context) (imageNodeM
continue
}

for _, taint := range nodeDetails.Spec.Taints {
if taint.Effect == corev1.TaintEffectNoSchedule || taint.Effect == corev1.TaintEffectNoExecute {
continue
}
if hasBlockingTaints(nodeDetails.Spec.Taints) {
continue
}

for _, container := range pod.Spec.InitContainers {
Expand All @@ -499,3 +497,12 @@ func (c *Cluster) getImagesAndNodesForInjection(ctx context.Context) (imageNodeM
}
}
}

func hasBlockingTaints(taints []corev1.Taint) bool {
for _, taint := range taints {
if taint.Effect == corev1.TaintEffectNoSchedule || taint.Effect == corev1.TaintEffectNoExecute {
return true
}
}
return false
}
Loading

0 comments on commit 7cc9973

Please sign in to comment.