k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/apis/extensions/v1beta1/defaults_test.go (about) 1 /* 2 Copyright 2015 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package v1beta1_test 18 19 import ( 20 "math" 21 "reflect" 22 "testing" 23 24 extensionsv1beta1 "k8s.io/api/extensions/v1beta1" 25 26 v1 "k8s.io/api/core/v1" 27 apiequality "k8s.io/apimachinery/pkg/api/equality" 28 "k8s.io/apimachinery/pkg/api/resource" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 "k8s.io/apimachinery/pkg/runtime" 31 "k8s.io/apimachinery/pkg/util/intstr" 32 "k8s.io/kubernetes/pkg/api/legacyscheme" 33 _ "k8s.io/kubernetes/pkg/apis/core/install" 34 _ "k8s.io/kubernetes/pkg/apis/extensions/install" 35 . "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" 36 utilpointer "k8s.io/utils/pointer" 37 ) 38 39 func TestSetDefaultDaemonSetSpec(t *testing.T) { 40 defaultLabels := map[string]string{"foo": "bar"} 41 period := int64(v1.DefaultTerminationGracePeriodSeconds) 42 defaultTemplate := v1.PodTemplateSpec{ 43 Spec: v1.PodSpec{ 44 DNSPolicy: v1.DNSClusterFirst, 45 RestartPolicy: v1.RestartPolicyAlways, 46 SecurityContext: &v1.PodSecurityContext{}, 47 TerminationGracePeriodSeconds: &period, 48 SchedulerName: v1.DefaultSchedulerName, 49 }, 50 ObjectMeta: metav1.ObjectMeta{ 51 Labels: defaultLabels, 52 }, 53 } 54 templateNoLabel := v1.PodTemplateSpec{ 55 Spec: v1.PodSpec{ 56 DNSPolicy: v1.DNSClusterFirst, 57 RestartPolicy: v1.RestartPolicyAlways, 58 SecurityContext: &v1.PodSecurityContext{}, 59 TerminationGracePeriodSeconds: &period, 60 SchedulerName: v1.DefaultSchedulerName, 61 }, 62 } 63 tests := []struct { 64 original *extensionsv1beta1.DaemonSet 65 expected *extensionsv1beta1.DaemonSet 66 }{ 67 { // Labels change/defaulting test. 68 original: &extensionsv1beta1.DaemonSet{ 69 Spec: extensionsv1beta1.DaemonSetSpec{ 70 Template: defaultTemplate, 71 }, 72 }, 73 expected: &extensionsv1beta1.DaemonSet{ 74 ObjectMeta: metav1.ObjectMeta{ 75 Labels: defaultLabels, 76 }, 77 Spec: extensionsv1beta1.DaemonSetSpec{ 78 Selector: &metav1.LabelSelector{ 79 MatchLabels: defaultLabels, 80 }, 81 Template: defaultTemplate, 82 UpdateStrategy: extensionsv1beta1.DaemonSetUpdateStrategy{ 83 Type: extensionsv1beta1.OnDeleteDaemonSetStrategyType, 84 }, 85 RevisionHistoryLimit: utilpointer.Int32(10), 86 }, 87 }, 88 }, 89 { // Labels change/defaulting test. 90 original: &extensionsv1beta1.DaemonSet{ 91 ObjectMeta: metav1.ObjectMeta{ 92 Labels: map[string]string{ 93 "bar": "foo", 94 }, 95 }, 96 Spec: extensionsv1beta1.DaemonSetSpec{ 97 Template: defaultTemplate, 98 RevisionHistoryLimit: utilpointer.Int32(1), 99 }, 100 }, 101 expected: &extensionsv1beta1.DaemonSet{ 102 ObjectMeta: metav1.ObjectMeta{ 103 Labels: map[string]string{ 104 "bar": "foo", 105 }, 106 }, 107 Spec: extensionsv1beta1.DaemonSetSpec{ 108 Selector: &metav1.LabelSelector{ 109 MatchLabels: defaultLabels, 110 }, 111 Template: defaultTemplate, 112 UpdateStrategy: extensionsv1beta1.DaemonSetUpdateStrategy{ 113 Type: extensionsv1beta1.OnDeleteDaemonSetStrategyType, 114 }, 115 RevisionHistoryLimit: utilpointer.Int32(1), 116 }, 117 }, 118 }, 119 { // Update strategy. 120 original: &extensionsv1beta1.DaemonSet{}, 121 expected: &extensionsv1beta1.DaemonSet{ 122 Spec: extensionsv1beta1.DaemonSetSpec{ 123 Template: templateNoLabel, 124 UpdateStrategy: extensionsv1beta1.DaemonSetUpdateStrategy{ 125 Type: extensionsv1beta1.OnDeleteDaemonSetStrategyType, 126 }, 127 RevisionHistoryLimit: utilpointer.Int32(10), 128 }, 129 }, 130 }, 131 { // Custom unique label key. 132 original: &extensionsv1beta1.DaemonSet{ 133 Spec: extensionsv1beta1.DaemonSetSpec{}, 134 }, 135 expected: &extensionsv1beta1.DaemonSet{ 136 Spec: extensionsv1beta1.DaemonSetSpec{ 137 Template: templateNoLabel, 138 UpdateStrategy: extensionsv1beta1.DaemonSetUpdateStrategy{ 139 Type: extensionsv1beta1.OnDeleteDaemonSetStrategyType, 140 }, 141 RevisionHistoryLimit: utilpointer.Int32(10), 142 }, 143 }, 144 }, 145 } 146 147 for i, test := range tests { 148 original := test.original 149 expected := test.expected 150 obj2 := roundTrip(t, runtime.Object(original)) 151 got, ok := obj2.(*extensionsv1beta1.DaemonSet) 152 if !ok { 153 t.Errorf("(%d) unexpected object: %v", i, got) 154 t.FailNow() 155 } 156 if !apiequality.Semantic.DeepEqual(got.Spec, expected.Spec) { 157 t.Errorf("(%d) got different than expected\ngot:\n\t%+v\nexpected:\n\t%+v", i, got.Spec, expected.Spec) 158 } 159 } 160 } 161 162 func TestSetDefaultDeployment(t *testing.T) { 163 defaultIntOrString := intstr.FromInt32(1) 164 differentIntOrString := intstr.FromInt32(5) 165 period := int64(v1.DefaultTerminationGracePeriodSeconds) 166 defaultTemplate := v1.PodTemplateSpec{ 167 Spec: v1.PodSpec{ 168 DNSPolicy: v1.DNSClusterFirst, 169 RestartPolicy: v1.RestartPolicyAlways, 170 SecurityContext: &v1.PodSecurityContext{}, 171 TerminationGracePeriodSeconds: &period, 172 SchedulerName: v1.DefaultSchedulerName, 173 }, 174 } 175 tests := []struct { 176 original *extensionsv1beta1.Deployment 177 expected *extensionsv1beta1.Deployment 178 }{ 179 { 180 original: &extensionsv1beta1.Deployment{}, 181 expected: &extensionsv1beta1.Deployment{ 182 Spec: extensionsv1beta1.DeploymentSpec{ 183 Replicas: utilpointer.Int32(1), 184 Strategy: extensionsv1beta1.DeploymentStrategy{ 185 Type: extensionsv1beta1.RollingUpdateDeploymentStrategyType, 186 RollingUpdate: &extensionsv1beta1.RollingUpdateDeployment{ 187 MaxSurge: &defaultIntOrString, 188 MaxUnavailable: &defaultIntOrString, 189 }, 190 }, 191 Template: defaultTemplate, 192 ProgressDeadlineSeconds: utilpointer.Int32(math.MaxInt32), 193 RevisionHistoryLimit: utilpointer.Int32(math.MaxInt32), 194 }, 195 }, 196 }, 197 { 198 original: &extensionsv1beta1.Deployment{ 199 Spec: extensionsv1beta1.DeploymentSpec{ 200 Replicas: utilpointer.Int32(5), 201 Strategy: extensionsv1beta1.DeploymentStrategy{ 202 RollingUpdate: &extensionsv1beta1.RollingUpdateDeployment{ 203 MaxSurge: &differentIntOrString, 204 }, 205 }, 206 }, 207 }, 208 expected: &extensionsv1beta1.Deployment{ 209 Spec: extensionsv1beta1.DeploymentSpec{ 210 Replicas: utilpointer.Int32(5), 211 Strategy: extensionsv1beta1.DeploymentStrategy{ 212 Type: extensionsv1beta1.RollingUpdateDeploymentStrategyType, 213 RollingUpdate: &extensionsv1beta1.RollingUpdateDeployment{ 214 MaxSurge: &differentIntOrString, 215 MaxUnavailable: &defaultIntOrString, 216 }, 217 }, 218 Template: defaultTemplate, 219 ProgressDeadlineSeconds: utilpointer.Int32(math.MaxInt32), 220 RevisionHistoryLimit: utilpointer.Int32(math.MaxInt32), 221 }, 222 }, 223 }, 224 { 225 original: &extensionsv1beta1.Deployment{ 226 Spec: extensionsv1beta1.DeploymentSpec{ 227 Replicas: utilpointer.Int32(3), 228 Strategy: extensionsv1beta1.DeploymentStrategy{ 229 Type: extensionsv1beta1.RollingUpdateDeploymentStrategyType, 230 RollingUpdate: nil, 231 }, 232 }, 233 }, 234 expected: &extensionsv1beta1.Deployment{ 235 Spec: extensionsv1beta1.DeploymentSpec{ 236 Replicas: utilpointer.Int32(3), 237 Strategy: extensionsv1beta1.DeploymentStrategy{ 238 Type: extensionsv1beta1.RollingUpdateDeploymentStrategyType, 239 RollingUpdate: &extensionsv1beta1.RollingUpdateDeployment{ 240 MaxSurge: &defaultIntOrString, 241 MaxUnavailable: &defaultIntOrString, 242 }, 243 }, 244 Template: defaultTemplate, 245 ProgressDeadlineSeconds: utilpointer.Int32(math.MaxInt32), 246 RevisionHistoryLimit: utilpointer.Int32(math.MaxInt32), 247 }, 248 }, 249 }, 250 { 251 original: &extensionsv1beta1.Deployment{ 252 Spec: extensionsv1beta1.DeploymentSpec{ 253 Replicas: utilpointer.Int32(5), 254 Strategy: extensionsv1beta1.DeploymentStrategy{ 255 Type: extensionsv1beta1.RecreateDeploymentStrategyType, 256 }, 257 }, 258 }, 259 expected: &extensionsv1beta1.Deployment{ 260 Spec: extensionsv1beta1.DeploymentSpec{ 261 Replicas: utilpointer.Int32(5), 262 Strategy: extensionsv1beta1.DeploymentStrategy{ 263 Type: extensionsv1beta1.RecreateDeploymentStrategyType, 264 }, 265 Template: defaultTemplate, 266 ProgressDeadlineSeconds: utilpointer.Int32(math.MaxInt32), 267 RevisionHistoryLimit: utilpointer.Int32(math.MaxInt32), 268 }, 269 }, 270 }, 271 { 272 original: &extensionsv1beta1.Deployment{ 273 Spec: extensionsv1beta1.DeploymentSpec{ 274 Replicas: utilpointer.Int32(5), 275 Strategy: extensionsv1beta1.DeploymentStrategy{ 276 Type: extensionsv1beta1.RecreateDeploymentStrategyType, 277 }, 278 ProgressDeadlineSeconds: utilpointer.Int32(30), 279 }, 280 }, 281 expected: &extensionsv1beta1.Deployment{ 282 Spec: extensionsv1beta1.DeploymentSpec{ 283 Replicas: utilpointer.Int32(5), 284 Strategy: extensionsv1beta1.DeploymentStrategy{ 285 Type: extensionsv1beta1.RecreateDeploymentStrategyType, 286 }, 287 Template: defaultTemplate, 288 ProgressDeadlineSeconds: utilpointer.Int32(30), 289 RevisionHistoryLimit: utilpointer.Int32(math.MaxInt32), 290 }, 291 }, 292 }, 293 } 294 295 for _, test := range tests { 296 original := test.original 297 expected := test.expected 298 obj2 := roundTrip(t, runtime.Object(original)) 299 got, ok := obj2.(*extensionsv1beta1.Deployment) 300 if !ok { 301 t.Errorf("unexpected object: %v", got) 302 t.FailNow() 303 } 304 if !apiequality.Semantic.DeepEqual(got.Spec, expected.Spec) { 305 t.Errorf("object mismatch!\nexpected:\n\t%+v\ngot:\n\t%+v", got.Spec, expected.Spec) 306 } 307 } 308 } 309 310 func TestSetDefaultReplicaSet(t *testing.T) { 311 tests := []struct { 312 rs *extensionsv1beta1.ReplicaSet 313 expectLabels bool 314 expectSelector bool 315 }{ 316 { 317 rs: &extensionsv1beta1.ReplicaSet{ 318 Spec: extensionsv1beta1.ReplicaSetSpec{ 319 Template: v1.PodTemplateSpec{ 320 ObjectMeta: metav1.ObjectMeta{ 321 Labels: map[string]string{ 322 "foo": "bar", 323 }, 324 }, 325 }, 326 }, 327 }, 328 expectLabels: true, 329 expectSelector: true, 330 }, 331 { 332 rs: &extensionsv1beta1.ReplicaSet{ 333 ObjectMeta: metav1.ObjectMeta{ 334 Labels: map[string]string{ 335 "bar": "foo", 336 }, 337 }, 338 Spec: extensionsv1beta1.ReplicaSetSpec{ 339 Template: v1.PodTemplateSpec{ 340 ObjectMeta: metav1.ObjectMeta{ 341 Labels: map[string]string{ 342 "foo": "bar", 343 }, 344 }, 345 }, 346 }, 347 }, 348 expectLabels: false, 349 expectSelector: true, 350 }, 351 { 352 rs: &extensionsv1beta1.ReplicaSet{ 353 ObjectMeta: metav1.ObjectMeta{ 354 Labels: map[string]string{ 355 "bar": "foo", 356 }, 357 }, 358 Spec: extensionsv1beta1.ReplicaSetSpec{ 359 Selector: &metav1.LabelSelector{ 360 MatchLabels: map[string]string{ 361 "some": "other", 362 }, 363 }, 364 Template: v1.PodTemplateSpec{ 365 ObjectMeta: metav1.ObjectMeta{ 366 Labels: map[string]string{ 367 "foo": "bar", 368 }, 369 }, 370 }, 371 }, 372 }, 373 expectLabels: false, 374 expectSelector: false, 375 }, 376 { 377 rs: &extensionsv1beta1.ReplicaSet{ 378 Spec: extensionsv1beta1.ReplicaSetSpec{ 379 Selector: &metav1.LabelSelector{ 380 MatchLabels: map[string]string{ 381 "some": "other", 382 }, 383 }, 384 Template: v1.PodTemplateSpec{ 385 ObjectMeta: metav1.ObjectMeta{ 386 Labels: map[string]string{ 387 "foo": "bar", 388 }, 389 }, 390 }, 391 }, 392 }, 393 expectLabels: true, 394 expectSelector: false, 395 }, 396 } 397 398 for _, test := range tests { 399 rs := test.rs 400 obj2 := roundTrip(t, runtime.Object(rs)) 401 rs2, ok := obj2.(*extensionsv1beta1.ReplicaSet) 402 if !ok { 403 t.Errorf("unexpected object: %v", rs2) 404 t.FailNow() 405 } 406 if test.expectSelector != reflect.DeepEqual(rs2.Spec.Selector.MatchLabels, rs2.Spec.Template.Labels) { 407 if test.expectSelector { 408 t.Errorf("expected: %v, got: %v", rs2.Spec.Template.Labels, rs2.Spec.Selector) 409 } else { 410 t.Errorf("unexpected equality: %v", rs.Spec.Selector) 411 } 412 } 413 if test.expectLabels != reflect.DeepEqual(rs2.Labels, rs2.Spec.Template.Labels) { 414 if test.expectLabels { 415 t.Errorf("expected: %v, got: %v", rs2.Spec.Template.Labels, rs2.Labels) 416 } else { 417 t.Errorf("unexpected equality: %v", rs.Labels) 418 } 419 } 420 } 421 } 422 423 func TestSetDefaultReplicaSetReplicas(t *testing.T) { 424 tests := []struct { 425 rs extensionsv1beta1.ReplicaSet 426 expectReplicas int32 427 }{ 428 { 429 rs: extensionsv1beta1.ReplicaSet{ 430 Spec: extensionsv1beta1.ReplicaSetSpec{ 431 Template: v1.PodTemplateSpec{ 432 ObjectMeta: metav1.ObjectMeta{ 433 Labels: map[string]string{ 434 "foo": "bar", 435 }, 436 }, 437 }, 438 }, 439 }, 440 expectReplicas: 1, 441 }, 442 { 443 rs: extensionsv1beta1.ReplicaSet{ 444 Spec: extensionsv1beta1.ReplicaSetSpec{ 445 Replicas: utilpointer.Int32(0), 446 Template: v1.PodTemplateSpec{ 447 ObjectMeta: metav1.ObjectMeta{ 448 Labels: map[string]string{ 449 "foo": "bar", 450 }, 451 }, 452 }, 453 }, 454 }, 455 expectReplicas: 0, 456 }, 457 { 458 rs: extensionsv1beta1.ReplicaSet{ 459 Spec: extensionsv1beta1.ReplicaSetSpec{ 460 Replicas: utilpointer.Int32(3), 461 Template: v1.PodTemplateSpec{ 462 ObjectMeta: metav1.ObjectMeta{ 463 Labels: map[string]string{ 464 "foo": "bar", 465 }, 466 }, 467 }, 468 }, 469 }, 470 expectReplicas: 3, 471 }, 472 } 473 474 for _, test := range tests { 475 rs := &test.rs 476 obj2 := roundTrip(t, runtime.Object(rs)) 477 rs2, ok := obj2.(*extensionsv1beta1.ReplicaSet) 478 if !ok { 479 t.Errorf("unexpected object: %v", rs2) 480 t.FailNow() 481 } 482 if rs2.Spec.Replicas == nil { 483 t.Errorf("unexpected nil Replicas") 484 } else if test.expectReplicas != *rs2.Spec.Replicas { 485 t.Errorf("expected: %d replicas, got: %d", test.expectReplicas, *rs2.Spec.Replicas) 486 } 487 } 488 } 489 490 func TestDefaultRequestIsNotSetForReplicaSet(t *testing.T) { 491 s := v1.PodSpec{} 492 s.Containers = []v1.Container{ 493 { 494 Resources: v1.ResourceRequirements{ 495 Limits: v1.ResourceList{ 496 v1.ResourceCPU: resource.MustParse("100m"), 497 }, 498 }, 499 }, 500 } 501 rs := &extensionsv1beta1.ReplicaSet{ 502 Spec: extensionsv1beta1.ReplicaSetSpec{ 503 Replicas: utilpointer.Int32(3), 504 Template: v1.PodTemplateSpec{ 505 ObjectMeta: metav1.ObjectMeta{ 506 Labels: map[string]string{ 507 "foo": "bar", 508 }, 509 }, 510 Spec: s, 511 }, 512 }, 513 } 514 output := roundTrip(t, runtime.Object(rs)) 515 rs2 := output.(*extensionsv1beta1.ReplicaSet) 516 defaultRequest := rs2.Spec.Template.Spec.Containers[0].Resources.Requests 517 requestValue := defaultRequest[v1.ResourceCPU] 518 if requestValue.String() != "0" { 519 t.Errorf("Expected 0 request value, got: %s", requestValue.String()) 520 } 521 } 522 523 func TestSetDefaultNetworkPolicy(t *testing.T) { 524 tests := []struct { 525 original *extensionsv1beta1.NetworkPolicy 526 expected *extensionsv1beta1.NetworkPolicy 527 }{ 528 { // Empty NetworkPolicy should be set to PolicyTypes Ingress 529 original: &extensionsv1beta1.NetworkPolicy{ 530 Spec: extensionsv1beta1.NetworkPolicySpec{ 531 PodSelector: metav1.LabelSelector{ 532 MatchLabels: map[string]string{"a": "b"}, 533 }, 534 }, 535 }, 536 expected: &extensionsv1beta1.NetworkPolicy{ 537 Spec: extensionsv1beta1.NetworkPolicySpec{ 538 PodSelector: metav1.LabelSelector{ 539 MatchLabels: map[string]string{"a": "b"}, 540 }, 541 PolicyTypes: []extensionsv1beta1.PolicyType{extensionsv1beta1.PolicyTypeIngress}, 542 }, 543 }, 544 }, 545 { // Empty Ingress NetworkPolicy should be set to PolicyTypes Ingress 546 original: &extensionsv1beta1.NetworkPolicy{ 547 Spec: extensionsv1beta1.NetworkPolicySpec{ 548 PodSelector: metav1.LabelSelector{ 549 MatchLabels: map[string]string{"a": "b"}, 550 }, 551 Ingress: []extensionsv1beta1.NetworkPolicyIngressRule{}, 552 }, 553 }, 554 expected: &extensionsv1beta1.NetworkPolicy{ 555 Spec: extensionsv1beta1.NetworkPolicySpec{ 556 PodSelector: metav1.LabelSelector{ 557 MatchLabels: map[string]string{"a": "b"}, 558 }, 559 Ingress: []extensionsv1beta1.NetworkPolicyIngressRule{}, 560 PolicyTypes: []extensionsv1beta1.PolicyType{extensionsv1beta1.PolicyTypeIngress}, 561 }, 562 }, 563 }, 564 { // Defined Ingress and Egress should be set to Ingress,Egress 565 original: &extensionsv1beta1.NetworkPolicy{ 566 Spec: extensionsv1beta1.NetworkPolicySpec{ 567 PodSelector: metav1.LabelSelector{ 568 MatchLabels: map[string]string{"a": "b"}, 569 }, 570 Ingress: []extensionsv1beta1.NetworkPolicyIngressRule{ 571 { 572 From: []extensionsv1beta1.NetworkPolicyPeer{ 573 { 574 PodSelector: &metav1.LabelSelector{ 575 MatchLabels: map[string]string{"c": "d"}, 576 }, 577 NamespaceSelector: &metav1.LabelSelector{ 578 MatchLabels: map[string]string{"c": "d"}, 579 }, 580 }, 581 }, 582 }, 583 }, 584 Egress: []extensionsv1beta1.NetworkPolicyEgressRule{ 585 { 586 To: []extensionsv1beta1.NetworkPolicyPeer{ 587 { 588 NamespaceSelector: &metav1.LabelSelector{ 589 MatchLabels: map[string]string{"c": "d"}, 590 }, 591 }, 592 }, 593 }, 594 }, 595 }, 596 }, 597 expected: &extensionsv1beta1.NetworkPolicy{ 598 Spec: extensionsv1beta1.NetworkPolicySpec{ 599 PodSelector: metav1.LabelSelector{ 600 MatchLabels: map[string]string{"a": "b"}, 601 }, 602 Ingress: []extensionsv1beta1.NetworkPolicyIngressRule{ 603 { 604 From: []extensionsv1beta1.NetworkPolicyPeer{ 605 { 606 PodSelector: &metav1.LabelSelector{ 607 MatchLabels: map[string]string{"c": "d"}, 608 }, 609 NamespaceSelector: &metav1.LabelSelector{ 610 MatchLabels: map[string]string{"c": "d"}, 611 }, 612 }, 613 }, 614 }, 615 }, 616 Egress: []extensionsv1beta1.NetworkPolicyEgressRule{ 617 { 618 To: []extensionsv1beta1.NetworkPolicyPeer{ 619 { 620 NamespaceSelector: &metav1.LabelSelector{ 621 MatchLabels: map[string]string{"c": "d"}, 622 }, 623 }, 624 }, 625 }, 626 }, 627 PolicyTypes: []extensionsv1beta1.PolicyType{extensionsv1beta1.PolicyTypeIngress, extensionsv1beta1.PolicyTypeEgress}, 628 }, 629 }, 630 }, 631 { // Egress only with unset PolicyTypes should be set to Ingress, Egress 632 original: &extensionsv1beta1.NetworkPolicy{ 633 Spec: extensionsv1beta1.NetworkPolicySpec{ 634 PodSelector: metav1.LabelSelector{ 635 MatchLabels: map[string]string{"a": "b"}, 636 }, 637 Egress: []extensionsv1beta1.NetworkPolicyEgressRule{ 638 { 639 To: []extensionsv1beta1.NetworkPolicyPeer{ 640 { 641 NamespaceSelector: &metav1.LabelSelector{ 642 MatchLabels: map[string]string{"c": "d"}, 643 }, 644 }, 645 }, 646 }, 647 }, 648 }, 649 }, 650 expected: &extensionsv1beta1.NetworkPolicy{ 651 Spec: extensionsv1beta1.NetworkPolicySpec{ 652 PodSelector: metav1.LabelSelector{ 653 MatchLabels: map[string]string{"a": "b"}, 654 }, 655 Egress: []extensionsv1beta1.NetworkPolicyEgressRule{ 656 { 657 To: []extensionsv1beta1.NetworkPolicyPeer{ 658 { 659 NamespaceSelector: &metav1.LabelSelector{ 660 MatchLabels: map[string]string{"c": "d"}, 661 }, 662 }, 663 }, 664 }, 665 }, 666 PolicyTypes: []extensionsv1beta1.PolicyType{extensionsv1beta1.PolicyTypeIngress, extensionsv1beta1.PolicyTypeEgress}, 667 }, 668 }, 669 }, 670 { // Egress only with PolicyTypes set to Egress should be set to only Egress 671 original: &extensionsv1beta1.NetworkPolicy{ 672 Spec: extensionsv1beta1.NetworkPolicySpec{ 673 PodSelector: metav1.LabelSelector{ 674 MatchLabels: map[string]string{"a": "b"}, 675 }, 676 Egress: []extensionsv1beta1.NetworkPolicyEgressRule{ 677 { 678 To: []extensionsv1beta1.NetworkPolicyPeer{ 679 { 680 NamespaceSelector: &metav1.LabelSelector{ 681 MatchLabels: map[string]string{"Egress": "only"}, 682 }, 683 }, 684 }, 685 }, 686 }, 687 PolicyTypes: []extensionsv1beta1.PolicyType{extensionsv1beta1.PolicyTypeEgress}, 688 }, 689 }, 690 expected: &extensionsv1beta1.NetworkPolicy{ 691 Spec: extensionsv1beta1.NetworkPolicySpec{ 692 PodSelector: metav1.LabelSelector{ 693 MatchLabels: map[string]string{"a": "b"}, 694 }, 695 Egress: []extensionsv1beta1.NetworkPolicyEgressRule{ 696 { 697 To: []extensionsv1beta1.NetworkPolicyPeer{ 698 { 699 NamespaceSelector: &metav1.LabelSelector{ 700 MatchLabels: map[string]string{"Egress": "only"}, 701 }, 702 }, 703 }, 704 }, 705 }, 706 PolicyTypes: []extensionsv1beta1.PolicyType{extensionsv1beta1.PolicyTypeEgress}, 707 }, 708 }, 709 }, 710 } 711 712 for i, test := range tests { 713 original := test.original 714 expected := test.expected 715 obj2 := roundTrip(t, runtime.Object(original)) 716 got, ok := obj2.(*extensionsv1beta1.NetworkPolicy) 717 if !ok { 718 t.Errorf("(%d) unexpected object: %v", i, got) 719 t.FailNow() 720 } 721 if !apiequality.Semantic.DeepEqual(got.Spec, expected.Spec) { 722 t.Errorf("(%d) got different than expected\ngot:\n\t%+v\nexpected:\n\t%+v", i, got.Spec, expected.Spec) 723 } 724 } 725 } 726 727 func roundTrip(t *testing.T, obj runtime.Object) runtime.Object { 728 data, err := runtime.Encode(legacyscheme.Codecs.LegacyCodec(SchemeGroupVersion), obj) 729 if err != nil { 730 t.Errorf("%v\n %#v", err, obj) 731 return nil 732 } 733 obj2, err := runtime.Decode(legacyscheme.Codecs.UniversalDecoder(), data) 734 if err != nil { 735 t.Errorf("%v\nData: %s\nSource: %#v", err, string(data), obj) 736 return nil 737 } 738 obj3 := reflect.New(reflect.TypeOf(obj).Elem()).Interface().(runtime.Object) 739 err = legacyscheme.Scheme.Convert(obj2, obj3, nil) 740 if err != nil { 741 t.Errorf("%v\nSource: %#v", err, obj2) 742 return nil 743 } 744 return obj3 745 }