diff --git a/.gitignore b/.gitignore index be253a1..f019bad 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ vendor/ go.work dist/ + +.vscode diff --git a/go.mod b/go.mod index 009ee4c..d56538e 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.19 require ( github.com/spf13/cobra v1.6.1 + github.com/stretchr/testify v1.8.0 k8s.io/api v0.26.0 k8s.io/apimachinery v0.26.0 k8s.io/cli-runtime v0.26.0 @@ -40,6 +41,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xlab/treeprint v1.1.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect diff --git a/go.sum b/go.sum index 96f3f29..c4ddf53 100644 --- a/go.sum +++ b/go.sum @@ -191,13 +191,16 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/main.go b/main.go index a871430..5539b9e 100644 --- a/main.go +++ b/main.go @@ -20,12 +20,12 @@ import ( ) const ( - karpenterLabel string = "karpenter.sh/provisioner-name" karpenterNodeFmtStr string = "(Karpenter) %s" - - customLabelEnvVar = "KUBE_NODEPOOLS_LABEL" + customLabelEnvVar string = "KUBE_NODEPOOLS_LABEL" ) +var karpenterLabels = []string{"karpenter.sh/provisioner-name", "karpenter.sh/nodepool"} + var ( noHeaders bool onlyName bool @@ -116,8 +116,10 @@ func findNodepool(node corev1.Node, label string) string { } // check for karpenter nodes - if np, ok := node.Labels[karpenterLabel]; ok { - return fmt.Sprintf(karpenterNodeFmtStr, np) + for _, label := range karpenterLabels { + if np, ok := node.Labels[label]; ok { + return fmt.Sprintf(karpenterNodeFmtStr, np) + } } for _, lbl := range providerNodepoolLabels { diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..9664de5 --- /dev/null +++ b/main_test.go @@ -0,0 +1,134 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestNodeCondition(t *testing.T) { + testTable := map[string]struct { + Node *corev1.Node + Expected string + }{ + "Basic Case": { + Node: &corev1.Node{ + Status: corev1.NodeStatus{ + Conditions: []corev1.NodeCondition{ + { + Type: corev1.NodeConditionType("Ready"), + Status: corev1.ConditionTrue, + }, + }, + }, + }, + Expected: "Ready", + }, + } + + for name, tc := range testTable { + t.Run(name, func(t *testing.T) { + actual := nodeCondition(*tc.Node) + assert.Equal(t, tc.Expected, actual, "failed") + }) + } +} + +func TestNodepoolLabels(t *testing.T) { + testTable := map[string]struct { + Node *corev1.Node + CustomLabel string + Expected string + }{ + "no matching label": { + Node: &corev1.Node{ + ObjectMeta: v1.ObjectMeta{ + Labels: map[string]string{ + "custom-label": "custom label", + }, + }, + }, + Expected: "-", + }, + "custom label": { + Node: &corev1.Node{ + ObjectMeta: v1.ObjectMeta{ + Labels: map[string]string{ + "custom-label": "custom label", + }, + }, + }, + CustomLabel: "custom-label", + Expected: "custom label", + }, + "AWS": { + Node: &corev1.Node{ + ObjectMeta: v1.ObjectMeta{ + Labels: map[string]string{ + "eks.amazonaws.com/nodegroup": "test AWS", + }, + }, + }, + Expected: "test AWS", + }, + "GCP": { + Node: &corev1.Node{ + ObjectMeta: v1.ObjectMeta{ + Labels: map[string]string{ + "cloud.google.com/gke-nodepool": "test GCP", + }, + }, + }, + Expected: "test GCP", + }, + "AKS": { + Node: &corev1.Node{ + ObjectMeta: v1.ObjectMeta{ + Labels: map[string]string{ + "kubernetes.azure.com/agentpool": "test AKS", + }, + }, + }, + Expected: "test AKS", + }, + "DigitalOcean": { + Node: &corev1.Node{ + ObjectMeta: v1.ObjectMeta{ + Labels: map[string]string{ + "doks.digitalocean.com/node-pool-id": "test DigitalOcean", + }, + }, + }, + Expected: "test DigitalOcean", + }, + "v1alpha5 API": { + Node: &corev1.Node{ + ObjectMeta: v1.ObjectMeta{ + Labels: map[string]string{ + "karpenter.sh/provisioner-name": "test v1alpha5", + }, + }, + }, + Expected: "(Karpenter) test v1alpha5", + }, + "v1beta1 API": { + Node: &corev1.Node{ + ObjectMeta: v1.ObjectMeta{ + Labels: map[string]string{ + "karpenter.sh/nodepool": "test v1beta1", + }, + }, + }, + Expected: "(Karpenter) test v1beta1", + }, + } + + for name, tc := range testTable { + t.Run(name, func(t *testing.T) { + actual := findNodepool(*tc.Node, tc.CustomLabel) + assert.Equal(t, tc.Expected, actual, "failed") + }) + } +}