github.com/tilt-dev/tilt@v0.36.0/internal/store/k8sconv/resource_test.go (about)

     1  package k8sconv
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/google/uuid"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    12  
    13  	"github.com/tilt-dev/tilt/internal/k8s"
    14  	"github.com/tilt-dev/tilt/internal/k8s/testyaml"
    15  	"github.com/tilt-dev/tilt/pkg/apis/core/v1alpha1"
    16  )
    17  
    18  func TestFilteredPodByAncestorUID(t *testing.T) {
    19  	applyStatus := newDeploymentApplyStatus()
    20  
    21  	podA := v1alpha1.Pod{Name: "pod-1", Namespace: "default"}
    22  	podB := v1alpha1.Pod{Name: "pod-1", Namespace: "default", AncestorUID: "328372c6-a93a-460a-9bc7-eff90c69f5ce"}
    23  	podC := v1alpha1.Pod{Name: "pod-1", Namespace: "default", AncestorUID: "328372c6-a93a-460a-9bc7-cab"}
    24  	discovery := newDiscovery([]v1alpha1.Pod{podA, podB, podC})
    25  	res, err := NewKubernetesResource(discovery, applyStatus)
    26  	require.NoError(t, err)
    27  	assert.Equal(t, []v1alpha1.Pod{podA, podB}, res.FilteredPods)
    28  }
    29  
    30  func TestFilteredPodByPodTemplateHash(t *testing.T) {
    31  	applyStatus := newDeploymentApplyStatus()
    32  
    33  	podA := v1alpha1.Pod{Name: "pod-1", Namespace: "default"}
    34  	podB := v1alpha1.Pod{Name: "pod-1", Namespace: "default", PodTemplateSpecHash: "9e6121753dfe0fbb65ed"}
    35  	podC := v1alpha1.Pod{Name: "pod-1", Namespace: "default", PodTemplateSpecHash: "328372c6-a93a-460a-9bc7-cab"}
    36  	discovery := newDiscovery([]v1alpha1.Pod{podA, podB, podC})
    37  	res, err := NewKubernetesResource(discovery, applyStatus)
    38  	require.NoError(t, err)
    39  	assert.Equal(t, []v1alpha1.Pod{podA, podB}, res.FilteredPods)
    40  }
    41  
    42  func TestFilteredPodByOwner(t *testing.T) {
    43  	time1 := metav1.Time{Time: time.Now().Add(-time.Hour)}
    44  	time2 := metav1.Time{Time: time.Now().Add(-time.Minute)}
    45  
    46  	ownerA := &v1alpha1.PodOwner{
    47  		Name:              "rs-rev-1",
    48  		Kind:              "ReplicaSet",
    49  		CreationTimestamp: time1,
    50  	}
    51  	ownerB := &v1alpha1.PodOwner{
    52  		Name:              "rs-rev-2",
    53  		Kind:              "ReplicaSet",
    54  		CreationTimestamp: time2,
    55  	}
    56  	ownerC := &v1alpha1.PodOwner{
    57  		Name:              "alt-rs",
    58  		Kind:              "ReplicaSet",
    59  		CreationTimestamp: time1,
    60  	}
    61  	podA := v1alpha1.Pod{Name: "pod-1", Owner: ownerA, AncestorUID: "dep-1"}
    62  	podB := v1alpha1.Pod{Name: "pod-2", Owner: ownerA, AncestorUID: "dep-1"}
    63  	podAlt := v1alpha1.Pod{Name: "pod-alt", Owner: ownerC, AncestorUID: "alt-server"}
    64  	podC := v1alpha1.Pod{Name: "pod-3", Owner: ownerB, AncestorUID: "dep-1"}
    65  
    66  	filter := func(pods ...v1alpha1.Pod) []v1alpha1.Pod {
    67  		discovery := newDiscovery(pods)
    68  		res, err := NewKubernetesResource(discovery, nil)
    69  		require.NoError(t, err)
    70  		return res.FilteredPods
    71  	}
    72  
    73  	assert.Equal(t, []v1alpha1.Pod{podA, podB}, filter(podA, podB))
    74  	assert.Equal(t, []v1alpha1.Pod{podA, podAlt}, filter(podA, podAlt))
    75  
    76  	// Ensure that if one deployment has a new replicaset,
    77  	// the pods from the old replicaset are filtered out.
    78  	assert.Equal(t, []v1alpha1.Pod{podC}, filter(podA, podB, podC))
    79  	assert.Equal(t, []v1alpha1.Pod{podC}, filter(podC, podB, podA))
    80  
    81  	// Ensure that if we have pods coming from multiple deployments,
    82  	// we keep pods from all deployments.
    83  	assert.Equal(t, []v1alpha1.Pod{podAlt, podC}, filter(podAlt, podC, podB, podA))
    84  }
    85  
    86  func TestFilterPodsHanldesJobSets(t *testing.T) {
    87  	time1 := metav1.Time{Time: time.Now().Add(-time.Hour)}
    88  	time2 := metav1.Time{Time: time.Now().Add(-time.Minute)}
    89  
    90  	ownerA := &v1alpha1.PodOwner{
    91  		Name:              "job-1",
    92  		Kind:              "Job",
    93  		CreationTimestamp: time1,
    94  	}
    95  	ownerB := &v1alpha1.PodOwner{
    96  		Name:              "job-2",
    97  		Kind:              "Job",
    98  		CreationTimestamp: time2,
    99  	}
   100  	podA := v1alpha1.Pod{Name: "pod-1", Owner: ownerA, AncestorUID: "js-1"}
   101  	podB := v1alpha1.Pod{Name: "pod-2", Owner: ownerB, AncestorUID: "js-1"}
   102  
   103  	filter := func(pods ...v1alpha1.Pod) []v1alpha1.Pod {
   104  		discovery := newDiscovery(pods)
   105  		res, err := NewKubernetesResource(discovery, nil)
   106  		require.NoError(t, err)
   107  		return res.FilteredPods
   108  	}
   109  
   110  	// Ensure that if one JobSet has two Jobs,
   111  	// all pods are preserved.
   112  	assert.Equal(t, []v1alpha1.Pod{podA, podB}, filter(podA, podB))
   113  }
   114  
   115  func TestNewKubernetesApplyFilter_Sorted(t *testing.T) {
   116  	forDeploy, err := k8s.ParseYAMLFromString(testyaml.OutOfOrderYaml)
   117  	require.NoError(t, err, "Invalid test YAML")
   118  	for i := range forDeploy {
   119  		forDeploy[i].SetUID(uuid.New().String())
   120  	}
   121  	resultYAML, err := k8s.SerializeSpecYAML(forDeploy)
   122  	require.NoError(t, err, "Failed to re-serialize test YAML")
   123  	// sanity check to ensure serialization isn't changing the sort
   124  	require.Less(t, strings.Index(resultYAML, "Job"), strings.Index(resultYAML, "PersistentVolumeClaim"),
   125  		"Order in re-serialized YAML was not preserved")
   126  
   127  	applyFilter, err := NewKubernetesApplyFilter(resultYAML)
   128  	require.NoError(t, err, "Failed to create KubernetesApplyFilter")
   129  	require.NotNil(t, applyFilter, "KubernetesApplyFilter was nil")
   130  
   131  	var actualKinds []string
   132  	for _, ref := range applyFilter.DeployedRefs {
   133  		actualKinds = append(actualKinds, ref.Kind)
   134  	}
   135  
   136  	expectedKindOrder := []string{"PersistentVolume", "PersistentVolumeClaim", "ConfigMap", "Service", "StatefulSet", "Job", "Pod"}
   137  	assert.Equal(t, expectedKindOrder, actualKinds)
   138  }
   139  
   140  func newDeploymentApplyStatus() *v1alpha1.KubernetesApplyStatus {
   141  	return &v1alpha1.KubernetesApplyStatus{
   142  		ResultYAML: `
   143  apiVersion: apps/v1
   144  kind: Deployment
   145  metadata:
   146    name: tilt-site
   147    namespace: default
   148    resourceVersion: "41313"
   149    uid: 328372c6-a93a-460a-9bc7-eff90c69f5ce
   150  spec:
   151    selector:
   152      matchLabels:
   153        app: tilt-site
   154    template:
   155      metadata:
   156        creationTimestamp: null
   157        labels:
   158          app: tilt-site
   159          app.kubernetes.io/managed-by: tilt
   160          tilt.dev/pod-template-hash: 9e6121753dfe0fbb65ed
   161      spec:
   162        containers:
   163        - image: localhost:5005/tilt-site:tilt-bb6b20cd3041242e
   164          name: tilt-site
   165  `,
   166  	}
   167  }
   168  
   169  func newDiscovery(pods []v1alpha1.Pod) *v1alpha1.KubernetesDiscovery {
   170  	return &v1alpha1.KubernetesDiscovery{
   171  		Status: v1alpha1.KubernetesDiscoveryStatus{
   172  			Pods: pods,
   173  		},
   174  	}
   175  }