<commit_before>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2017 Red Hat, Inc.
 *
 */

package rest_test

import (
	"flag"
	"net/http"
	"net/http/httptest"

	"encoding/json"
	"fmt"
	"io/ioutil"

	"github.com/emicklei/go-restful"
	"github.com/ghodss/yaml"
	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/ghttp"
	"golang.org/x/net/context"
	k8sv1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/client-go/rest"

	"kubevirt.io/kubevirt/pkg/api/v1"
	"kubevirt.io/kubevirt/pkg/kubecli"
	"kubevirt.io/kubevirt/pkg/logging"
	rest2 "kubevirt.io/kubevirt/pkg/rest"
	. "kubevirt.io/kubevirt/pkg/testutils"
	. "kubevirt.io/kubevirt/pkg/virt-api/rest"
)

const vmResource = "virtualmachines"
const migrationResource = "migrations"
const vmName = "test-vm"

var _ = Describe("Kubeproxy", func() {
	flag.Parse()
	var apiserverMock *ghttp.Server
	var kubeproxy *httptest.Server
	vmGVR := schema.GroupVersionResource{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version, Resource: vmResource}
	migrationGVR := schema.GroupVersionResource{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version, Resource: migrationResource}
	ctx := context.Background()
	var restClient *rest.RESTClient
	var sourceVM *v1.VirtualMachine
	var sourceMigration *v1.Migration

	// Work around go-client bug
	expectedVM := v1.NewMinimalVM(vmName)
	expectedVM.TypeMeta.Kind = ""
	expectedVM.TypeMeta.APIVersion = ""

	expectedMigration := v1.NewMinimalMigration("testmigration", vmName)
	expectedMigration.TypeMeta.Kind = ""
	expectedMigration.TypeMeta.APIVersion = ""

	logging.DefaultLogger().SetIOWriter(GinkgoWriter)

	BeforeSuite(func() {
		apiserverMock = ghttp.NewServer()
		flag.Lookup("master").Value.Set(apiserverMock.URL())

		ws, err := GroupVersionProxyBase(ctx, v1.GroupVersion)
		Expect(err).ToNot(HaveOccurred())
		ws, err = GenericResourceProxy(ws, ctx, vmGVR, &v1.VirtualMachine{}, v1.VirtualMachineGroupVersionKind.Kind, &v1.VirtualMachineList{})
		Expect(err).ToNot(HaveOccurred())
		ws, err = GenericResourceProxy(ws, ctx, migrationGVR, &v1.Migration{}, "Migration", &v1.MigrationList{})
		Expect(err).ToNot(HaveOccurred())
		restful.Add(ws)

	})

	BeforeEach(func() {
		kubeproxy = httptest.NewServer(restful.DefaultContainer)
		var err error
		virtClient, err := kubecli.GetKubevirtClientFromFlags(kubeproxy.URL, "")
		if err != nil {
			Expect(err).ToNot(HaveOccurred())
		}
		restClient = virtClient.RestClient()
		sourceVM = v1.NewMinimalVM(vmName)
		sourceMigration = v1.NewMinimalMigration("testmigration", vmName)
		apiserverMock.Reset()
	})

	Context("To allow autodiscovery for kubectl", func() {
		It("should proxy /apis/kubevirt.io/v1alpha1/", func() {
			apiserverMock.AppendHandlers(
				ghttp.CombineHandlers(
					ghttp.VerifyRequest(http.MethodGet, "/apis/kubevirt.io/v1alpha1/"),
					ghttp.RespondWithJSONEncoded(http.StatusOK, sourceVM),
				),
			)
			result := restClient.Get().AbsPath("/apis/kubevirt.io/v1alpha1/").Do()
			Expect(result).To(HaveStatusCode(http.StatusOK))
			body, _ := result.Raw()
			var obj v1.VirtualMachine
			Expect(json.Unmarshal(body, &obj)).To(Succeed())
			Expect(&obj).To(Equal(expectedVM))
		})
	})

	Context("HTTP Operations on an existing VM in the apiserver", func() {
		It("POST should fail with 409", func() {
			apiserverMock.AppendHandlers(
				ghttp.CombineHandlers(
					ghttp.VerifyRequest(http.MethodPost, vmBasePath()),
					ghttp.VerifyJSONRepresenting(sourceVM),
					ghttp.RespondWithJSONEncoded(http.StatusConflict, struct{}{}),
				),
			)
			result := restClient.Post().Resource(vmResource).Namespace(k8sv1.NamespaceDefault).Body(sourceVM).Do()
			Expect(result).To(HaveStatusCode(http.StatusConflict))
		})
		It("Get with invalid VM name should fail with 400", func() {
			result := restClient.Get().Resource(vmResource).Namespace(k8sv1.NamespaceDefault).Name("UPerLetterIsInvalid").Do()
			Expect(result).To(HaveStatusCode(http.StatusNotFound))
		})
		table.DescribeTable("PUT should succeed", func(contentType string, accept string) {
			apiserverMock.AppendHandlers(
				ghttp.CombineHandlers(
					ghttp.VerifyRequest(http.MethodPut, vmPath(sourceVM)),
					ghttp.VerifyJSONRepresenting(sourceVM),
					ghttp.RespondWithJSONEncoded(http.StatusOK, sourceVM),
				),
			)
			result := restClient.Put().Resource(vmResource).Name(sourceVM.GetObjectMeta().GetName()).Namespace(k8sv1.NamespaceDefault).
				SetHeader("Content-Type", contentType).SetHeader("Accept", accept).Body(toBytesFromMimeType(sourceVM, contentType)).
				Do()
			Expect(result).To(HaveStatusCode(http.StatusOK))
			Expect(result).To(RepresentMimeType(accept))
			Expect(result).To(HaveBodyEqualTo(expectedVM))
		},
			table.Entry("sending JSON and receiving JSON", rest2.MIME_JSON, rest2.MIME_JSON),
			table.Entry("sending JSON and receiving YAML", rest2.MIME_JSON, rest2.MIME_YAML),
			table.Entry("sending YAML and receiving JSON", rest2.MIME_YAML, rest2.MIME_JSON),
			table.Entry("sending YAML and receiving YAML", rest2.MIME_YAML, rest2.MIME_YAML),
		)
		It("DELETE should succeed", func() {
			apiserverMock.AppendHandlers(
				ghttp.CombineHandlers(
					ghttp.VerifyRequest(http.MethodDelete, vmPath(sourceVM)),
					ghttp.RespondWithJSONEncoded(http.StatusOK, struct{}{}),
				),<commit_msg>Kubeproxy: fixing test for invalid request<commit_after>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2017 Red Hat, Inc.
 *
 */

package rest_test

import (
	"flag"
	"net/http"
	"net/http/httptest"

	"encoding/json"
	"fmt"
	"io/ioutil"

	"github.com/emicklei/go-restful"
	"github.com/ghodss/yaml"
	. "github.com/onsi/ginkgo"
	"github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/ghttp"
	"golang.org/x/net/context"
	k8sv1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/client-go/rest"

	"kubevirt.io/kubevirt/pkg/api/v1"
	"kubevirt.io/kubevirt/pkg/kubecli"
	"kubevirt.io/kubevirt/pkg/logging"
	rest2 "kubevirt.io/kubevirt/pkg/rest"
	. "kubevirt.io/kubevirt/pkg/testutils"
	. "kubevirt.io/kubevirt/pkg/virt-api/rest"
)

const vmResource = "virtualmachines"
const migrationResource = "migrations"
const vmName = "test-vm"

var _ = Describe("Kubeproxy", func() {
	flag.Parse()
	var apiserverMock *ghttp.Server
	var kubeproxy *httptest.Server
	vmGVR := schema.GroupVersionResource{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version, Resource: vmResource}
	migrationGVR := schema.GroupVersionResource{Group: v1.GroupVersion.Group, Version: v1.GroupVersion.Version, Resource: migrationResource}
	ctx := context.Background()
	var restClient *rest.RESTClient
	var sourceVM *v1.VirtualMachine
	var sourceMigration *v1.Migration

	// Work around go-client bug
	expectedVM := v1.NewMinimalVM(vmName)
	expectedVM.TypeMeta.Kind = ""
	expectedVM.TypeMeta.APIVersion = ""

	expectedMigration := v1.NewMinimalMigration("testmigration", vmName)
	expectedMigration.TypeMeta.Kind = ""
	expectedMigration.TypeMeta.APIVersion = ""

	logging.DefaultLogger().SetIOWriter(GinkgoWriter)

	BeforeSuite(func() {
		apiserverMock = ghttp.NewServer()
		flag.Lookup("master").Value.Set(apiserverMock.URL())

		ws, err := GroupVersionProxyBase(ctx, v1.GroupVersion)
		Expect(err).ToNot(HaveOccurred())
		ws, err = GenericResourceProxy(ws, ctx, vmGVR, &v1.VirtualMachine{}, v1.VirtualMachineGroupVersionKind.Kind, &v1.VirtualMachineList{})
		Expect(err).ToNot(HaveOccurred())
		ws, err = GenericResourceProxy(ws, ctx, migrationGVR, &v1.Migration{}, "Migration", &v1.MigrationList{})
		Expect(err).ToNot(HaveOccurred())
		restful.Add(ws)

	})

	BeforeEach(func() {
		kubeproxy = httptest.NewServer(restful.DefaultContainer)
		var err error
		virtClient, err := kubecli.GetKubevirtClientFromFlags(kubeproxy.URL, "")
		if err != nil {
			Expect(err).ToNot(HaveOccurred())
		}
		restClient = virtClient.RestClient()
		sourceVM = v1.NewMinimalVM(vmName)
		sourceMigration = v1.NewMinimalMigration("testmigration", vmName)
		apiserverMock.Reset()
	})

	Context("To allow autodiscovery for kubectl", func() {
		It("should proxy /apis/kubevirt.io/v1alpha1/", func() {
			apiserverMock.AppendHandlers(
				ghttp.CombineHandlers(
					ghttp.VerifyRequest(http.MethodGet, "/apis/kubevirt.io/v1alpha1/"),
					ghttp.RespondWithJSONEncoded(http.StatusOK, sourceVM),
				),
			)
			result := restClient.Get().AbsPath("/apis/kubevirt.io/v1alpha1/").Do()
			Expect(result).To(HaveStatusCode(http.StatusOK))
			body, _ := result.Raw()
			var obj v1.VirtualMachine
			Expect(json.Unmarshal(body, &obj)).To(Succeed())
			Expect(&obj).To(Equal(expectedVM))
		})
	})

	Context("HTTP Operations on an existing VM in the apiserver", func() {
		It("POST should fail with 409", func() {
			apiserverMock.AppendHandlers(
				ghttp.CombineHandlers(
					ghttp.VerifyRequest(http.MethodPost, vmBasePath()),
					ghttp.VerifyJSONRepresenting(sourceVM),
					ghttp.RespondWithJSONEncoded(http.StatusConflict, struct{}{}),
				),
			)
			result := restClient.Post().Resource(vmResource).Namespace(k8sv1.NamespaceDefault).Body(sourceVM).Do()
			Expect(result).To(HaveStatusCode(http.StatusConflict))
		})
		It("Get with invalid VM name should fail with 400", func() {
			result := restClient.Get().Resource(vmResource).Namespace(k8sv1.NamespaceDefault).Name("UPerLetterIsInvalid").Do()
			Expect(result).To(HaveStatusCode(http.StatusBadRequest))
		})
		table.DescribeTable("PUT should succeed", func(contentType string, accept string) {
			apiserverMock.AppendHandlers(
				ghttp.CombineHandlers(
					ghttp.VerifyRequest(http.MethodPut, vmPath(sourceVM)),
					ghttp.VerifyJSONRepresenting(sourceVM),
					ghttp.RespondWithJSONEncoded(http.StatusOK, sourceVM),
				),
			)
			result := restClient.Put().Resource(vmResource).Name(sourceVM.GetObjectMeta().GetName()).Namespace(k8sv1.NamespaceDefault).
				SetHeader("Content-Type", contentType).SetHeader("Accept", accept).Body(toBytesFromMimeType(sourceVM, contentType)).
				Do()
			Expect(result).To(HaveStatusCode(http.StatusOK))
			Expect(result).To(RepresentMimeType(accept))
			Expect(result).To(HaveBodyEqualTo(expectedVM))
		},
			table.Entry("sending JSON and receiving JSON", rest2.MIME_JSON, rest2.MIME_JSON),
			table.Entry("sending JSON and receiving YAML", rest2.MIME_JSON, rest2.MIME_YAML),
			table.Entry("sending YAML and receiving JSON", rest2.MIME_YAML, rest2.MIME_JSON),
			table.Entry("sending YAML and receiving YAML", rest2.MIME_YAML, rest2.MIME_YAML),
		)
		It("DELETE should succeed", func() {
			apiserverMock.AppendHandlers(
				ghttp.CombineHandlers(
					ghttp.VerifyRequest(http.MethodDelete, vmPath(sourceVM)),
					ghttp.RespondWithJSONEncoded(http.StatusOK, struct{}{}),
				),
{'fraction_non_alphanumeric': 0.13581879804910307, 'fraction_numerical': 0.010746466065966768, 'mean_word_length': 4.9596059113300495, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2214247', 'n_tokens_mistral': 4572, 'n_tokens_neox': 4223, 'n_words': 721}