Repository: kubernetes/kubernetes
File: test/integration/servicecidr/allocator_test.go (Go)

Code before:
			}

			// Make another service. It will fail because we're out of cluster IPs
			if _, err := client.CoreV1().Services(metav1.NamespaceDefault).Create(context.TODO(), svc(8), metav1.CreateOptions{}); err != nil {
				if !strings.Contains(err.Error(), "range is full") {
					t.Errorf("unexpected error text: %v", err)
				}
			} else {
				svcs, err := client.CoreV1().Services(metav1.NamespaceAll).List(context.TODO(), metav1.ListOptions{})
				if err != nil {
					t.Fatalf("unexpected success, and error getting the services: %v", err)
				}
				allIPs := []string{}
				for _, s := range svcs.Items {
					allIPs = append(allIPs, s.Spec.ClusterIP)
				}
				t.Fatalf("unexpected creation success. The following IPs exist: %#v. It should only be possible to allocate 2 IP addresses in this cluster.\n\n%#v", allIPs, svcs)
			}

			// Delete the first service.
			if err := client.CoreV1().Services(metav1.NamespaceDefault).Delete(context.TODO(), svc(1).ObjectMeta.Name, metav1.DeleteOptions{}); err != nil {
				t.Fatalf("got unexpected error: %v", err)
			}

			// This time creating the second service should work.
			if _, err := client.CoreV1().Services(metav1.NamespaceDefault).Create(context.TODO(), svc(8), metav1.CreateOptions{}); err != nil {
				t.Fatalf("got unexpected error: %v", err)
			}
		})
	}
}

func TestServiceAllocIPAddressLargeCIDR(t *testing.T) {
	// Create an IPv6 single stack control-plane with a large range
	serviceCIDR := "2001:db8::/64"
	tCtx := ktesting.Init(t)
	etcdOptions := framework.SharedEtcd()
	apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
	s1 := kubeapiservertesting.StartTestServerOrDie(t,
		apiServerOptions,
		[]string{
			"--service-cluster-ip-range=" + serviceCIDR,
			"--advertise-address=2001:db8::10",
			"--disable-admission-plugins=ServiceAccount",
		},
		etcdOptions)
	defer s1.TearDownFn()

	client, err := clientset.NewForConfig(s1.ClientConfig)
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)

Review comment (suggestion):
/lgtm
though the comment would be clearer as

```suggestion
			// This time creating the second service should work, assume a maximum of 2 seconds for the
			// deletion to be propagated to the ipallocator's informer so it can allocate the IP again.
```

Code after:
			}

			// Make another service. It will fail because we're out of cluster IPs
			if _, err := client.CoreV1().Services(metav1.NamespaceDefault).Create(context.TODO(), svc(8), metav1.CreateOptions{}); err != nil {
				if !strings.Contains(err.Error(), "range is full") {
					t.Errorf("unexpected error text: %v", err)
				}
			} else {
				svcs, err := client.CoreV1().Services(metav1.NamespaceAll).List(context.TODO(), metav1.ListOptions{})
				if err != nil {
					t.Fatalf("unexpected success, and error getting the services: %v", err)
				}
				allIPs := []string{}
				for _, s := range svcs.Items {
					allIPs = append(allIPs, s.Spec.ClusterIP)
				}
				t.Fatalf("unexpected creation success. The following IPs exist: %#v. It should only be possible to allocate 2 IP addresses in this cluster.\n\n%#v", allIPs, svcs)
			}

			// Delete the first service.
			if err := client.CoreV1().Services(metav1.NamespaceDefault).Delete(context.TODO(), svc(1).ObjectMeta.Name, metav1.DeleteOptions{}); err != nil {
				t.Fatalf("got unexpected error: %v", err)
			}

			// The ipallocator has an informer, and it needs to wait for the deletion to be propagated before it can allocate the IP again.
			// This time creating the second service should work, assume a maximum of 2 seconds for the informer to catch up.
			err = wait.PollUntilContextTimeout(context.Background(), 250*time.Millisecond, 2*time.Second, true, func(ctx context.Context) (bool, error) {
				_, err := client.CoreV1().Services(metav1.NamespaceDefault).Create(ctx, svc(8), metav1.CreateOptions{})
				return err == nil, nil
			})
			if err != nil {
				t.Fatalf("unexpected creation failure: %v", err)
			}
		})
	}
}

func TestServiceAllocIPAddressLargeCIDR(t *testing.T) {
	// Create an IPv6 single stack control-plane with a large range
	serviceCIDR := "2001:db8::/64"
	tCtx := ktesting.Init(t)
	etcdOptions := framework.SharedEtcd()
	apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
	s1 := kubeapiservertesting.StartTestServerOrDie(t,
		apiServerOptions,
		[]string{
			"--service-cluster-ip-range=" + serviceCIDR,
			"--advertise-address=2001:db8::10",
			"--disable-admission-plugins=ServiceAccount",
		},
		etcdOptions)