github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/k8s/registry_test.go (about) 1 package k8s 2 3 import ( 4 "bytes" 5 "context" 6 "io" 7 "os" 8 goruntime "runtime" 9 "testing" 10 11 "github.com/tilt-dev/clusterid" 12 "github.com/tilt-dev/tilt/internal/container" 13 "github.com/tilt-dev/tilt/pkg/logger" 14 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 v1 "k8s.io/api/core/v1" 18 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 19 "k8s.io/client-go/kubernetes/fake" 20 "k8s.io/client-go/kubernetes/scheme" 21 ktesting "k8s.io/client-go/testing" 22 ) 23 24 func TestRegistryFoundMicrok8s(t *testing.T) { 25 // microk8s is linux-only 26 if goruntime.GOOS != "linux" { 27 t.SkipNow() 28 } 29 30 cs := &fake.Clientset{} 31 tracker := ktesting.NewObjectTracker(scheme.Scheme, scheme.Codecs.UniversalDecoder()) 32 cs.AddReactor("*", "*", ktesting.ObjectReaction(tracker)) 33 _ = tracker.Add(&v1.Service{ 34 ObjectMeta: metav1.ObjectMeta{ 35 Name: microk8sRegistryName, 36 Namespace: microk8sRegistryNamespace, 37 }, 38 Spec: v1.ServiceSpec{ 39 Ports: []v1.ServicePort{ 40 v1.ServicePort{NodePort: 32000}, 41 }, 42 }, 43 }) 44 45 core := cs.CoreV1() 46 registryAsync := newRegistryAsync(clusterid.ProductMicroK8s, core, NewNaiveRuntimeSource(container.RuntimeContainerd)) 47 48 registry := registryAsync.Registry(newLoggerCtx(os.Stdout)) 49 if assert.NotNil(t, registry, "Registry was nil") { 50 assert.Equal(t, "localhost:32000", registry.Host) 51 } 52 } 53 54 func TestRegistryFoundInTiltAnnotationsWithClusterHost(t *testing.T) { 55 cs := &fake.Clientset{} 56 tracker := ktesting.NewObjectTracker(scheme.Scheme, scheme.Codecs.UniversalDecoder()) 57 cs.AddReactor("*", "*", ktesting.ObjectReaction(tracker)) 58 _ = tracker.Add(&v1.Node{ 59 ObjectMeta: metav1.ObjectMeta{ 60 Name: "node1", 61 Annotations: map[string]string{ 62 tiltAnnotationRegistry: "localhost:5000", 63 tiltAnnotationRegistryFromCluster: "registry:5000", 64 }, 65 }, 66 }) 67 68 core := cs.CoreV1() 69 registryAsync := newRegistryAsync(clusterid.ProductKIND, core, NewNaiveRuntimeSource(container.RuntimeContainerd)) 70 71 registry := registryAsync.Registry(newLoggerCtx(os.Stdout)) 72 assert.Equal(t, "localhost:5000", registry.Host) 73 assert.Equal(t, "registry:5000", registry.HostFromContainerRuntime) 74 } 75 76 func TestRegistryFoundInKindAnnotations(t *testing.T) { 77 cs := &fake.Clientset{} 78 tracker := ktesting.NewObjectTracker(scheme.Scheme, scheme.Codecs.UniversalDecoder()) 79 cs.AddReactor("*", "*", ktesting.ObjectReaction(tracker)) 80 _ = tracker.Add(&v1.Node{ 81 ObjectMeta: metav1.ObjectMeta{ 82 Name: "node1", 83 Annotations: map[string]string{ 84 kindAnnotationRegistry: "localhost:5000", 85 }, 86 }, 87 }) 88 89 core := cs.CoreV1() 90 registryAsync := newRegistryAsync(clusterid.ProductKIND, core, NewNaiveRuntimeSource(container.RuntimeContainerd)) 91 92 registry := registryAsync.Registry(newLoggerCtx(os.Stdout)) 93 assert.Equal(t, "localhost:5000", registry.Host) 94 } 95 96 func TestLocalRegistryDiscoveryHelp(t *testing.T) { 97 cs := &fake.Clientset{} 98 tracker := ktesting.NewObjectTracker(scheme.Scheme, scheme.Codecs.UniversalDecoder()) 99 cs.AddReactor("*", "*", ktesting.ObjectReaction(tracker)) 100 err := addConfigMap(tracker, ` 101 apiVersion: v1 102 kind: ConfigMap 103 metadata: 104 name: local-registry-hosting 105 namespace: kube-public 106 data: 107 localRegistryHosting.v1: | 108 help: "https://fake-domain.tilt.dev/local-registry-help" 109 `) 110 require.NoError(t, err) 111 112 core := cs.CoreV1() 113 registryAsync := newRegistryAsync(clusterid.ProductKIND, core, NewNaiveRuntimeSource(container.RuntimeContainerd)) 114 115 out := bytes.NewBuffer(nil) 116 registry := registryAsync.Registry(newLoggerCtx(out)) 117 assert.Nil(t, registry) 118 assert.Contains(t, out.String(), "https://fake-domain.tilt.dev/local-registry-help") 119 } 120 121 func TestLocalRegistryDiscoveryHost(t *testing.T) { 122 cs := &fake.Clientset{} 123 tracker := ktesting.NewObjectTracker(scheme.Scheme, scheme.Codecs.UniversalDecoder()) 124 cs.AddReactor("*", "*", ktesting.ObjectReaction(tracker)) 125 err := addConfigMap(tracker, ` 126 apiVersion: v1 127 kind: ConfigMap 128 metadata: 129 name: local-registry-hosting 130 namespace: kube-public 131 data: 132 localRegistryHosting.v1: | 133 host: "localhost:5000" 134 hostFromContainerRuntime: "registry:5000" 135 help: "https://fake-domain.tilt.dev/local-registry-help" 136 `) 137 require.NoError(t, err) 138 139 core := cs.CoreV1() 140 registryAsync := newRegistryAsync(clusterid.ProductKIND, core, NewNaiveRuntimeSource(container.RuntimeContainerd)) 141 142 registry := registryAsync.Registry(newLoggerCtx(os.Stdout)) 143 assert.Equal(t, "localhost:5000", registry.Host) 144 assert.Equal(t, "registry:5000", registry.HostFromContainerRuntime) 145 } 146 147 func TestKINDWarning(t *testing.T) { 148 cs := &fake.Clientset{} 149 core := cs.CoreV1() 150 registryAsync := newRegistryAsync(clusterid.ProductKIND, core, NewNaiveRuntimeSource(container.RuntimeContainerd)) 151 152 out := bytes.NewBuffer(nil) 153 registry := registryAsync.Registry(newLoggerCtx(out)) 154 assert.Nil(t, registry) 155 assert.Contains(t, out.String(), "https://github.com/tilt-dev/kind-local") 156 } 157 158 func TestK3DNoWarning(t *testing.T) { 159 cs := &fake.Clientset{} 160 core := cs.CoreV1() 161 registryAsync := newRegistryAsync(clusterid.ProductK3D, core, NewNaiveRuntimeSource(container.RuntimeContainerd)) 162 163 out := bytes.NewBuffer(nil) 164 registry := registryAsync.Registry(newLoggerCtx(out)) 165 assert.Nil(t, registry) 166 assert.Equal(t, out.String(), "") 167 } 168 169 func TestRegistryFoundInLabelsWithLocalOnly(t *testing.T) { 170 cs := &fake.Clientset{} 171 tracker := ktesting.NewObjectTracker(scheme.Scheme, scheme.Codecs.UniversalDecoder()) 172 cs.AddReactor("*", "*", ktesting.ObjectReaction(tracker)) 173 _ = tracker.Add(&v1.Node{ 174 ObjectMeta: metav1.ObjectMeta{ 175 Name: "node1", 176 Annotations: map[string]string{ 177 tiltAnnotationRegistry: "localhost:5000", 178 }, 179 }, 180 }) 181 182 core := cs.CoreV1() 183 registryAsync := newRegistryAsync(clusterid.ProductKIND, core, NewNaiveRuntimeSource(container.RuntimeContainerd)) 184 185 registry := registryAsync.Registry(newLoggerCtx(os.Stdout)) 186 assert.Equal(t, "localhost:5000", registry.Host) 187 assert.Empty(t, registry.HostFromContainerRuntime) 188 } 189 190 func TestRegistryNotFound(t *testing.T) { 191 // microk8s is linux-only 192 if goruntime.GOOS != "linux" { 193 t.SkipNow() 194 } 195 196 cs := &fake.Clientset{} 197 tracker := ktesting.NewObjectTracker(scheme.Scheme, scheme.Codecs.UniversalDecoder()) 198 cs.AddReactor("*", "*", ktesting.ObjectReaction(tracker)) 199 200 core := cs.CoreV1() 201 registryAsync := newRegistryAsync(clusterid.ProductMicroK8s, core, NewNaiveRuntimeSource(container.RuntimeContainerd)) 202 203 out := bytes.NewBuffer(nil) 204 registry := registryAsync.Registry(newLoggerCtx(out)) 205 assert.Nil(t, registry) 206 assert.Contains(t, out.String(), "microk8s.enable registry") 207 } 208 209 func newLoggerCtx(w io.Writer) context.Context { 210 l := logger.NewLogger(logger.InfoLvl, w) 211 ctx := logger.WithLogger(context.Background(), l) 212 return ctx 213 } 214 215 func addConfigMap(tracker ktesting.ObjectTracker, configMap string) error { 216 obj, _, err := 217 scheme.Codecs.UniversalDeserializer().Decode([]byte(configMap), nil, nil) 218 if err != nil { 219 return err 220 } 221 return tracker.Add(obj) 222 }