github.com/grahambrereton-form3/tilt@v0.10.18/internal/k8s/label_test.go (about)

     1  package k8s
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"k8s.io/api/apps/v1beta2"
    10  
    11  	"github.com/windmilleng/tilt/internal/k8s/testyaml"
    12  	"github.com/windmilleng/tilt/pkg/model"
    13  )
    14  
    15  func TestInjectLabelPod(t *testing.T) {
    16  	entity := parseOneEntity(t, testyaml.LonelyPodYAML)
    17  	newEntity, err := InjectLabels(entity, []model.LabelPair{
    18  		{
    19  			Key:   "tier",
    20  			Value: "test",
    21  		},
    22  	})
    23  	if err != nil {
    24  		t.Fatal(err)
    25  	}
    26  
    27  	result, err := SerializeSpecYAML([]K8sEntity{newEntity})
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  
    32  	if !strings.Contains(result, fmt.Sprintf("tier: test")) {
    33  		t.Errorf("labels did not appear in serialized yaml: %s", result)
    34  	}
    35  }
    36  
    37  func TestInjectLabelDeployment(t *testing.T) {
    38  	entity := parseOneEntity(t, testyaml.SanchoYAML)
    39  	newEntity, err := InjectLabels(entity, []model.LabelPair{
    40  		{
    41  			Key:   "tier",
    42  			Value: "test",
    43  		},
    44  		{
    45  			Key:   "owner",
    46  			Value: "me",
    47  		},
    48  	})
    49  	if err != nil {
    50  		t.Fatal(err)
    51  	}
    52  
    53  	result, err := SerializeSpecYAML([]K8sEntity{newEntity})
    54  	if err != nil {
    55  		t.Fatal(err)
    56  	}
    57  
    58  	// We expect the Deployment, the Selector, and the PodTemplate to get the labels.
    59  	assert.Equal(t, 3, strings.Count(result, "tier: test"))
    60  	assert.Equal(t, 3, strings.Count(result, "owner: me"))
    61  }
    62  
    63  func TestInjectLabelDeploymentMakeSelectorMatchOnConflict(t *testing.T) {
    64  	entity := parseOneEntity(t, testyaml.SanchoYAML)
    65  	newEntity, err := InjectLabels(entity, []model.LabelPair{
    66  		{
    67  			Key:   "app",
    68  			Value: "panza",
    69  		},
    70  	})
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  
    75  	result, err := SerializeSpecYAML([]K8sEntity{newEntity})
    76  	if err != nil {
    77  		t.Fatal(err)
    78  	}
    79  
    80  	// We expect the Deployment, the Selector, and the PodTemplate to get the labels.
    81  	assert.Equal(t, 3, strings.Count(result, "app: panza"))
    82  	// we've replaced the "app: sancho" in the selector
    83  	assert.Equal(t, 0, strings.Count(result, "app: sancho"))
    84  }
    85  
    86  func TestInjectLabelDeploymentBeta1(t *testing.T) {
    87  	entity := parseOneEntity(t, testyaml.SanchoBeta1YAML)
    88  	newEntity, err := InjectLabels(entity, []model.LabelPair{
    89  		{
    90  			Key:   "owner",
    91  			Value: "me",
    92  		},
    93  	})
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  
    98  	result, err := SerializeSpecYAML([]K8sEntity{newEntity})
    99  	if err != nil {
   100  		t.Fatal(err)
   101  	}
   102  
   103  	assert.Equal(t, 3, strings.Count(result, "owner: me"))
   104  
   105  	// Assert that matchLabels were injected
   106  	assert.Contains(t, result, "matchLabels")
   107  	assert.Equal(t, 2, strings.Count(testyaml.SanchoBeta1YAML, "app: sancho"))
   108  	assert.Equal(t, 3, strings.Count(result, "app: sancho"))
   109  }
   110  
   111  func TestInjectLabelDeploymentBeta2(t *testing.T) {
   112  	entity := parseOneEntity(t, testyaml.SanchoBeta2YAML)
   113  	newEntity, err := InjectLabels(entity, []model.LabelPair{
   114  		{
   115  			Key:   "owner",
   116  			Value: "me",
   117  		},
   118  	})
   119  	if err != nil {
   120  		t.Fatal(err)
   121  	}
   122  
   123  	result, err := SerializeSpecYAML([]K8sEntity{newEntity})
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  
   128  	assert.Equal(t, 3, strings.Count(result, "owner: me"))
   129  
   130  	// Assert that matchLabels were injected
   131  	assert.Contains(t, result, "matchLabels")
   132  	assert.Equal(t, 2, strings.Count(testyaml.SanchoBeta1YAML, "app: sancho"))
   133  	assert.Equal(t, 3, strings.Count(result, "app: sancho"))
   134  }
   135  
   136  func TestInjectLabelExtDeploymentBeta1(t *testing.T) {
   137  	entity := parseOneEntity(t, testyaml.SanchoExtBeta1YAML)
   138  	newEntity, err := InjectLabels(entity, []model.LabelPair{
   139  		{
   140  			Key:   "owner",
   141  			Value: "me",
   142  		},
   143  	})
   144  	if err != nil {
   145  		t.Fatal(err)
   146  	}
   147  
   148  	result, err := SerializeSpecYAML([]K8sEntity{newEntity})
   149  	if err != nil {
   150  		t.Fatal(err)
   151  	}
   152  
   153  	assert.Equal(t, 3, strings.Count(result, "owner: me"))
   154  
   155  	// Assert that matchLabels were injected
   156  	assert.Contains(t, result, "matchLabels")
   157  	assert.Equal(t, 2, strings.Count(testyaml.SanchoBeta1YAML, "app: sancho"))
   158  	assert.Equal(t, 3, strings.Count(result, "app: sancho"))
   159  }
   160  
   161  func TestInjectStatefulSet(t *testing.T) {
   162  	entity := parseOneEntity(t, testyaml.RedisStatefulSetYAML)
   163  	newEntity, err := InjectLabels(entity, []model.LabelPair{
   164  		{
   165  			Key:   "tilt-runid",
   166  			Value: "deadbeef",
   167  		},
   168  	})
   169  	if err != nil {
   170  		t.Fatal(err)
   171  	}
   172  
   173  	podTmpl := newEntity.Obj.(*v1beta2.StatefulSet).Spec.Template
   174  	vcTmpl := newEntity.Obj.(*v1beta2.StatefulSet).Spec.VolumeClaimTemplates[0]
   175  
   176  	assert.Equal(t, "deadbeef", podTmpl.ObjectMeta.Labels["tilt-runid"])
   177  	assert.Equal(t, "", vcTmpl.ObjectMeta.Labels["tilt-runid"])
   178  
   179  	result, err := SerializeSpecYAML([]K8sEntity{newEntity})
   180  	if err != nil {
   181  		t.Fatal(err)
   182  	}
   183  
   184  	// Only inject twice: in the top-level metadata, the pod template, and the match selectors,
   185  	// not the volume claim template
   186  	assert.Equal(t, 3, strings.Count(result, "tilt-runid: deadbeef"))
   187  }
   188  
   189  func TestSelectorMatchesLabels(t *testing.T) {
   190  	entities, err := ParseYAMLFromString(testyaml.BlorgBackendYAML)
   191  	if err != nil {
   192  		t.Fatal(err)
   193  	}
   194  	if len(entities) != 2 {
   195  		t.Fatal("expected exactly two entities")
   196  	}
   197  	if entities[0].GVK().Kind != "Service" {
   198  		t.Fatal("expected first entity to be a Service")
   199  	}
   200  	if entities[1].GVK().Kind != "Deployment" {
   201  		t.Fatal("expected second entity to be a Deployment")
   202  	}
   203  
   204  	svc := entities[0]
   205  	dep := entities[1]
   206  
   207  	labels := map[string]string{
   208  		"app":         "blorg",
   209  		"owner":       "nick",
   210  		"environment": "devel",
   211  		"tier":        "backend",
   212  		"foo":         "bar", // an extra label on the pod shouldn't affect the match
   213  	}
   214  	assert.True(t, svc.SelectorMatchesLabels(labels))
   215  
   216  	assert.False(t, dep.SelectorMatchesLabels(labels), "kind Deployment does not support SelectorMatchesLabels")
   217  
   218  	labels["app"] = "not-blorg"
   219  	assert.False(t, svc.SelectorMatchesLabels(labels), "wrong value for an expected key")
   220  
   221  	delete(labels, "app")
   222  	assert.False(t, svc.SelectorMatchesLabels(labels), "expected key missing")
   223  }
   224  
   225  func TestMatchesMetadataLabels(t *testing.T) {
   226  	entities, err := ParseYAMLFromString(testyaml.DoggosServiceYaml)
   227  	if err != nil {
   228  		t.Fatal(err)
   229  	}
   230  	if len(entities) != 1 {
   231  		t.Fatal("expected exactly two entities")
   232  	}
   233  	e := entities[0]
   234  
   235  	exactMatch := map[string]string{
   236  		"app":          "doggos",
   237  		"whosAGoodBoy": "imAGoodBoy",
   238  	}
   239  	assertMatchesMetadataLabels(t, e, exactMatch, true, "same set of labels should match")
   240  
   241  	subset := map[string]string{
   242  		"app": "doggos",
   243  	}
   244  	assertMatchesMetadataLabels(t, e, subset, true, "subset of labels should match")
   245  
   246  	labelsWithExtra := map[string]string{
   247  		"app":           "doggos",
   248  		"whosAGoodBoy":  "imAGoodBoy",
   249  		"tooManyLabels": "yep",
   250  	}
   251  	assertMatchesMetadataLabels(t, e, labelsWithExtra, false, "extra key not in metadata")
   252  
   253  	wrongValForKey := map[string]string{
   254  		"app":          "doggos",
   255  		"whosAGoodBoy": "notMeWhoops",
   256  	}
   257  	assertMatchesMetadataLabels(t, e, wrongValForKey, false, "label with wrong val for key")
   258  }
   259  
   260  func assertMatchesMetadataLabels(t *testing.T, e K8sEntity, labels map[string]string, expected bool, msg string) {
   261  	match, err := e.MatchesMetadataLabels(labels)
   262  	if err != nil {
   263  		t.Errorf("error checking if entity %s matches labels %v: %v", e.Name(), labels, err)
   264  	}
   265  	assert.Equal(t, expected, match, "expected entity %s matches metadata labels %v --> %t (%s)",
   266  		e.Name(), labels, expected, msg)
   267  }
   268  func parseOneEntity(t *testing.T, yaml string) K8sEntity {
   269  	entities, err := ParseYAMLFromString(yaml)
   270  	if err != nil {
   271  		t.Fatal(err)
   272  	}
   273  
   274  	if len(entities) != 1 {
   275  		t.Fatalf("Unexpected entities: %+v", entities)
   276  	}
   277  	return entities[0]
   278  }