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  }