From 4895aeef3759251369e75de87cffa3df7d166911 Mon Sep 17 00:00:00 2001 From: nikhiljindal Date: Thu, 23 Feb 2017 16:28:10 -0800 Subject: [PATCH] Adding an integration test for testing 202 status code from apiserver --- test/integration/apiserver/apiserver_test.go | 158 +++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 test/integration/apiserver/apiserver_test.go diff --git a/test/integration/apiserver/apiserver_test.go b/test/integration/apiserver/apiserver_test.go new file mode 100644 index 00000000000..065e12e796a --- /dev/null +++ b/test/integration/apiserver/apiserver_test.go @@ -0,0 +1,158 @@ +// +build integration,!no-etcd + +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apiserver + +import ( + "bytes" + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" + + "github.com/golang/glog" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + restclient "k8s.io/client-go/rest" + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/testapi" + "k8s.io/kubernetes/pkg/api/v1" + "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" + "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" + "k8s.io/kubernetes/test/integration/framework" +) + +func setup(t *testing.T) (*httptest.Server, clientset.Interface) { + masterConfig := framework.NewIntegrationTestMasterConfig() + masterConfig.EnableCoreControllers = false + _, s := framework.RunAMaster(masterConfig) + + clientSet, err := clientset.NewForConfig(&restclient.Config{Host: s.URL}) + if err != nil { + t.Fatalf("Error in create clientset: %v", err) + } + return s, clientSet +} + +func verifyStatusCode(t *testing.T, verb, URL, body string, expectedStatusCode int) { + // We dont use the typed Go client to send this request to be able to verify the response status code. + bodyBytes := bytes.NewReader([]byte(body)) + req, err := http.NewRequest(verb, URL, bodyBytes) + if err != nil { + t.Fatalf("unexpected error: %v in sending req with verb: %s, URL: %s and body: %s", err, verb, URL, body) + } + transport := http.DefaultTransport + glog.Infof("Sending request: %v", req) + resp, err := transport.RoundTrip(req) + if err != nil { + t.Fatalf("unexpected error: %v in req: %v", err, req) + } + defer resp.Body.Close() + b, _ := ioutil.ReadAll(resp.Body) + if resp.StatusCode != expectedStatusCode { + t.Errorf("Expected status %v, but got %v", expectedStatusCode, resp.StatusCode) + t.Errorf("Body: %v", string(b)) + } +} + +func path(resource, namespace, name string) string { + return testapi.Extensions.ResourcePath(resource, namespace, name) +} + +func newRS(namespace string) *v1beta1.ReplicaSet { + return &v1beta1.ReplicaSet{ + TypeMeta: metav1.TypeMeta{ + Kind: "ReplicaSet", + APIVersion: "extensions/v1beta1", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + GenerateName: "apiserver-test", + }, + Spec: v1beta1.ReplicaSetSpec{ + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{"name": "test"}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "fake-name", + Image: "fakeimage", + }, + }, + }, + }, + }, + } +} + +var cascDel string = ` +{ + "kind": "DeleteOptions", + "apiVersion": "` + api.Registry.GroupOrDie(api.GroupName).GroupVersion.String() + `", + "orphanDependents": false +} +` + +// Tests that the apiserver returns 202 status code as expected. +func Test202StatusCode(t *testing.T) { + s, clientSet := setup(t) + defer s.Close() + + ns := framework.CreateTestingNamespace("status-code", s, t) + defer framework.DeleteTestingNamespace(ns, s, t) + + rsClient := clientSet.Extensions().ReplicaSets(ns.Name) + + // 1. Create the resource without any finalizer and then delete it without setting DeleteOptions. + // Verify that server returns 200 in this case. + rs, err := rsClient.Create(newRS(ns.Name)) + if err != nil { + t.Fatalf("Failed to create rs: %v", err) + } + verifyStatusCode(t, "DELETE", s.URL+path("replicasets", ns.Name, rs.Name), "", 200) + + // 2. Create the resource with a finalizer so that the resource is not immediately deleted and then delete it without setting DeleteOptions. + // Verify that the apiserver still returns 200 since DeleteOptions.OrphanDependents is not set. + rs = newRS(ns.Name) + rs.ObjectMeta.Finalizers = []string{"kube.io/dummy-finalizer"} + rs, err = rsClient.Create(rs) + if err != nil { + t.Fatalf("Failed to create rs: %v", err) + } + verifyStatusCode(t, "DELETE", s.URL+path("replicasets", ns.Name, rs.Name), "", 200) + + // 3. Create the resource and then delete it with DeleteOptions.OrphanDependents=false. + // Verify that the server still returns 200 since the resource is immediately deleted. + rs = newRS(ns.Name) + rs, err = rsClient.Create(rs) + if err != nil { + t.Fatalf("Failed to create rs: %v", err) + } + verifyStatusCode(t, "DELETE", s.URL+path("replicasets", ns.Name, rs.Name), cascDel, 200) + + // 4. Create the resource with a finalizer so that the resource is not immediately deleted and then delete it with DeleteOptions.OrphanDependents=false. + // Verify that the server returns 202 in this case. + rs = newRS(ns.Name) + rs.ObjectMeta.Finalizers = []string{"kube.io/dummy-finalizer"} + rs, err = rsClient.Create(rs) + if err != nil { + t.Fatalf("Failed to create rs: %v", err) + } + verifyStatusCode(t, "DELETE", s.URL+path("replicasets", ns.Name, rs.Name), cascDel, 202) +}