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 }