Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add tests that update services while gate is off #96012

Merged
merged 1 commit into from Oct 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions test/integration/dualstack/BUILD
Expand Up @@ -12,13 +12,15 @@ go_test(
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/rest:go_default_library",
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
"//test/integration/framework:go_default_library",
"//vendor/github.com/evanphx/json-patch:go_default_library",
"//vendor/k8s.io/utils/net:go_default_library",
],
)
Expand Down
128 changes: 128 additions & 0 deletions test/integration/dualstack/dualstack_test.go
Expand Up @@ -18,16 +18,21 @@ package dualstack

import (
"context"
"encoding/json"
"fmt"
"net"
"reflect"
"strings"
"testing"
"time"

jsonpatch "github.com/evanphx/json-patch"

v1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"

"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/wait"

Expand Down Expand Up @@ -1305,6 +1310,129 @@ func TestPreferDualStack(t *testing.T) {
}
}

type labelsForMergePatch struct {
Labels map[string]string `json:"lables,omitempty"`
}

// tests an update service while dualstack flag is off
func TestServiceUpdate(t *testing.T) {
// Create an IPv4 single stack control-plane
serviceCIDR := "10.0.0.0/16"
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, false)()

cfg := framework.NewIntegrationTestMasterConfig()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should capture this seeming-boilerplate into a function

_, cidr, err := net.ParseCIDR(serviceCIDR)
if err != nil {
t.Fatalf("bad cidr: %v", err)
}
cfg.ExtraConfig.ServiceIPRange = *cidr
_, s, closeFn := framework.RunAMaster(cfg)
defer closeFn()

client := clientset.NewForConfigOrDie(&restclient.Config{Host: s.URL})

// Wait until the default "kubernetes" service is created.
if err = wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
_, err := client.CoreV1().Services(metav1.NamespaceDefault).Get(context.TODO(), "kubernetes", metav1.GetOptions{})
if err != nil && !apierrors.IsNotFound(err) {
return false, err
}
return !apierrors.IsNotFound(err), nil
}); err != nil {
t.Fatalf("creating kubernetes service timed out")
}

serviceName := "test-service"
svc := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: serviceName,
},
Spec: v1.ServiceSpec{
Type: v1.ServiceTypeClusterIP,
Ports: []v1.ServicePort{
{
Port: 443,
TargetPort: intstr.FromInt(443),
},
},
},
}

// create the service
_, err = client.CoreV1().Services(metav1.NamespaceDefault).Create(context.TODO(), svc, metav1.CreateOptions{})
// if no error was expected validate the service otherwise return
if err != nil {
t.Errorf("unexpected error creating service:%v", err)
return
}

svc, err = client.CoreV1().Services(metav1.NamespaceDefault).Get(context.TODO(), svc.Name, metav1.GetOptions{})
if err != nil {
t.Errorf("Unexpected error to get the service %s %v", svc.Name, err)
}

// update using put
svc.Labels = map[string]string{"x": "y"}
_, err = client.CoreV1().Services(metav1.NamespaceDefault).Update(context.TODO(), svc, metav1.UpdateOptions{})
if err != nil {
t.Errorf("Unexpected error updating the service %s %v", svc.Name, err)
}

_, err = client.CoreV1().Services(metav1.NamespaceDefault).Get(context.TODO(), svc.Name, metav1.GetOptions{})
if err != nil {
t.Fatalf("Unexpected error to get the service %s %v", svc.Name, err)
}

// update using StrategicMergePatchType
labels := labelsForMergePatch{
Labels: map[string]string{"foo": "bar"},
}

patchBytes, err := json.Marshal(&labels)
if err != nil {
t.Fatalf("failed to json.Marshal labels: %v", err)
}

_, err = client.CoreV1().Services(metav1.NamespaceDefault).Patch(context.TODO(), svc.Name, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{})
if err != nil {
t.Fatalf("unexpected error patching service using strategic merge patch. %v", err)
}

current, err := client.CoreV1().Services(metav1.NamespaceDefault).Get(context.TODO(), svc.Name, metav1.GetOptions{})
if err != nil {
t.Fatalf("Unexpected error to get the service %s %v", svc.Name, err)
}

// update using json patch
toUpdate := current.DeepCopy()
currentJSON, err := json.Marshal(current)
if err != nil {
t.Fatalf("unexpected error marshal current service. %v", err)
}
toUpdate.Labels = map[string]string{"alpha": "bravo"}
toUpdateJSON, err := json.Marshal(toUpdate)
if err != nil {
t.Fatalf("unexpected error marshal toupdate service. %v", err)
}

patchBytes, err = jsonpatch.CreateMergePatch(currentJSON, toUpdateJSON)
if err != nil {
t.Fatalf("unexpected error creating json patch. %v", err)
}

_, err = client.CoreV1().Services(metav1.NamespaceDefault).Patch(context.TODO(), svc.Name, types.MergePatchType, patchBytes, metav1.PatchOptions{})
if err != nil {
t.Fatalf("unexpected error patching service using merge patch. %v", err)
}

// validate the service was created correctly if it was not expected to fail
_, err = client.CoreV1().Services(metav1.NamespaceDefault).Get(context.TODO(), svc.Name, metav1.GetOptions{})
if err != nil {
t.Fatalf("Unexpected error to get the service %s %v", svc.Name, err)
}

}

// validateServiceAndClusterIPFamily checks that the service has the expected IPFamilies
func validateServiceAndClusterIPFamily(svc *v1.Service, expectedIPFamilies []v1.IPFamily) error {
// create a slice for the errors
Expand Down