<commit_before>// Copyright (c) 2018-2020 Tigera, Inc. All rights reserved.
//
// 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 main_windows_test

import (
	"context"
	"encoding/json"
	"fmt"
	"math/rand"
	"net"
	"os"
	"strings"
	"time"

	"github.com/projectcalico/cni-plugin/pkg/dataplane/windows"

	"github.com/Microsoft/hcsshim"
	"github.com/containernetworking/cni/pkg/types/current"
	"github.com/projectcalico/cni-plugin/internal/pkg/testutils"
	"github.com/projectcalico/cni-plugin/internal/pkg/utils"
	"github.com/projectcalico/cni-plugin/pkg/k8s"
	"github.com/projectcalico/cni-plugin/pkg/types"
	api "github.com/projectcalico/libcalico-go/lib/apis/v3"
	k8sconversion "github.com/projectcalico/libcalico-go/lib/backend/k8s/conversion"
	client "github.com/projectcalico/libcalico-go/lib/clientv3"
	"github.com/projectcalico/libcalico-go/lib/logutils"
	"github.com/projectcalico/libcalico-go/lib/names"
	"github.com/projectcalico/libcalico-go/lib/numorstring"
	"github.com/projectcalico/libcalico-go/lib/options"
	log "github.com/sirupsen/logrus"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

func ensureNamespace(clientset *kubernetes.Clientset, name string) {
	ns := &v1.Namespace{
		ObjectMeta: metav1.ObjectMeta{Name: name},
	}
	_, err := clientset.CoreV1().Namespaces().Create(context.Background(), ns, metav1.CreateOptions{})
	if errors.IsAlreadyExists(err) {
		return
	}
	Expect(err).NotTo(HaveOccurred())
}

func deleteNamespace(clientset *kubernetes.Clientset, name string) {
	err := clientset.CoreV1().Namespaces().Delete(context.Background(), name, metav1.DeleteOptions{})
	if err != nil {
		panic(err)
	}
}

func updateIPAMStrictAffinity(calicoClient client.Interface, enabled bool) {
	// Currently only Linux host is able to update IPAMConfig.
	// Use os override to fake a linux host.
	ctx := context.WithValue(context.Background(), "windowsHost", "linux")
	ipamConfig, err := calicoClient.IPAM().GetIPAMConfig(ctx)
	Expect(err).NotTo(HaveOccurred())

	ipamConfig.StrictAffinity = enabled

	err = calicoClient.IPAM().SetIPAMConfig(ctx, *ipamConfig)
	Expect(err).NotTo(HaveOccurred())
}

var _ = Describe("Kubernetes CNI tests", func() {
	var hostname string
	networkName := "calico-fv"
	var ctx context.Context
	var calicoClient client.Interface
	var err error
	BeforeSuite(func() {
		log.Infof("CONTAINER_RUNTIME=%v", os.Getenv("CONTAINER_RUNTIME"))

		//Clean-up Networks if left over in previous run
		hnsNetworkList, _ := hcsshim.HNSListNetworkRequest("GET", "", "")
		log.WithField("hnsNetworkList: ", hnsNetworkList).Infof("List of Network")
		for _, network := range hnsNetworkList {
			if strings.Contains(network.Name, networkName) {
				log.Infof("Removing network %s ", network.Name)
				_, err := network.Delete()
				Expect(err).NotTo(HaveOccurred())
			}
		}
		// Create a random seed
		rand.Seed(time.Now().UTC().UnixNano())
		log.SetFormatter(&logutils.Formatter{})
		log.AddHook(&logutils.ContextHook{})
		log.SetOutput(GinkgoWriter)
		log.SetLevel(log.InfoLevel)
		hostname, _ = names.Hostname()
		ctx = context.Background()
		calicoClient, err = client.NewFromEnv()
		if err != nil {
			panic(err)
		}
	})

	BeforeEach(func() {
		testutils.WipeDatastore()

		if os.Getenv("DATASTORE_TYPE") != "kubernetes" {
			// Since we're not running the startup script, we need to create a Calico Node, as required by our
			// IPAM plugin.
			caliNode := api.NewNode()
			caliNode.Name = hostname
			caliNode, err := calicoClient.Nodes().Create(context.Background(), caliNode, options.SetOptions{})
			Expect(err).NotTo(HaveOccurred(), "Failed to create Calico Node resource")
		}

		// Force StrictAffinity to be true, otherwise no IP allocation is possible.
		updateIPAMStrictAffinity(calicoClient, true)
	})

	logConf := types.NetConf{
		LogLevel: "info",
	}
	utils.ConfigureLogging(logConf)
	cniVersion := os.Getenv("CNI_SPEC_VERSION")

	Context("l2bridge network::using host-local IPAM", func() {
		var nsName, name string
		var clientset *kubernetes.Clientset
		netconf := fmt.Sprintf(`<commit_msg>Retry calico client retrieval on failure in windows test<commit_after>// Copyright (c) 2018-2021 Tigera, Inc. All rights reserved.
//
// 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 main_windows_test

import (
	"context"
	"encoding/json"
	"fmt"
	"math/rand"
	"net"
	"os"
	"strings"
	"time"

	"github.com/projectcalico/cni-plugin/pkg/dataplane/windows"

	"github.com/Microsoft/hcsshim"
	"github.com/containernetworking/cni/pkg/types/current"
	"github.com/projectcalico/cni-plugin/internal/pkg/testutils"
	"github.com/projectcalico/cni-plugin/internal/pkg/utils"
	"github.com/projectcalico/cni-plugin/pkg/k8s"
	"github.com/projectcalico/cni-plugin/pkg/types"
	api "github.com/projectcalico/libcalico-go/lib/apis/v3"
	k8sconversion "github.com/projectcalico/libcalico-go/lib/backend/k8s/conversion"
	client "github.com/projectcalico/libcalico-go/lib/clientv3"
	"github.com/projectcalico/libcalico-go/lib/logutils"
	"github.com/projectcalico/libcalico-go/lib/names"
	"github.com/projectcalico/libcalico-go/lib/numorstring"
	"github.com/projectcalico/libcalico-go/lib/options"
	log "github.com/sirupsen/logrus"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

func ensureNamespace(clientset *kubernetes.Clientset, name string) {
	ns := &v1.Namespace{
		ObjectMeta: metav1.ObjectMeta{Name: name},
	}
	_, err := clientset.CoreV1().Namespaces().Create(context.Background(), ns, metav1.CreateOptions{})
	if errors.IsAlreadyExists(err) {
		return
	}
	Expect(err).NotTo(HaveOccurred())
}

func deleteNamespace(clientset *kubernetes.Clientset, name string) {
	err := clientset.CoreV1().Namespaces().Delete(context.Background(), name, metav1.DeleteOptions{})
	if err != nil {
		panic(err)
	}
}

func updateIPAMStrictAffinity(calicoClient client.Interface, enabled bool) {
	// Currently only Linux host is able to update IPAMConfig.
	// Use os override to fake a linux host.
	ctx := context.WithValue(context.Background(), "windowsHost", "linux")
	ipamConfig, err := calicoClient.IPAM().GetIPAMConfig(ctx)
	Expect(err).NotTo(HaveOccurred())

	ipamConfig.StrictAffinity = enabled

	err = calicoClient.IPAM().SetIPAMConfig(ctx, *ipamConfig)
	Expect(err).NotTo(HaveOccurred())
}

var _ = Describe("Kubernetes CNI tests", func() {
	var hostname string
	networkName := "calico-fv"
	var ctx context.Context
	var calicoClient client.Interface
	var err error
	BeforeSuite(func() {
		log.Infof("CONTAINER_RUNTIME=%v", os.Getenv("CONTAINER_RUNTIME"))

		//Clean-up Networks if left over in previous run
		hnsNetworkList, _ := hcsshim.HNSListNetworkRequest("GET", "", "")
		log.WithField("hnsNetworkList: ", hnsNetworkList).Infof("List of Network")
		for _, network := range hnsNetworkList {
			if strings.Contains(network.Name, networkName) {
				log.Infof("Removing network %s ", network.Name)
				_, err := network.Delete()
				Expect(err).NotTo(HaveOccurred())
			}
		}
		// Create a random seed
		rand.Seed(time.Now().UTC().UnixNano())
		log.SetFormatter(&logutils.Formatter{})
		log.AddHook(&logutils.ContextHook{})
		log.SetOutput(GinkgoWriter)
		log.SetLevel(log.InfoLevel)
		hostname, _ = names.Hostname()
		ctx = context.Background()
		for i := 1; i <= 3; i++ {
			calicoClient, err = client.NewFromEnv()
			if err != nil {
				log.WithError(err).Errorf("Failed to create calico client (attempt %d)", i)
				continue
			}
			break
		}
		if err != nil {
			panic(err)
		}
	})

	BeforeEach(func() {
		testutils.WipeDatastore()

		if os.Getenv("DATASTORE_TYPE") != "kubernetes" {
			// Since we're not running the startup script, we need to create a Calico Node, as required by our
			// IPAM plugin.
			caliNode := api.NewNode()
			caliNode.Name = hostname
			caliNode, err := calicoClient.Nodes().Create(context.Background(), caliNode, options.SetOptions{})
			Expect(err).NotTo(HaveOccurred(), "Failed to create Calico Node resource")
		}

		// Force StrictAffinity to be true, otherwise no IP allocation is possible.
		updateIPAMStrictAffinity(calicoClient, true)
	})

	logConf := types.NetConf{
		LogLevel: "info",
	}
	utils.ConfigureLogging(logConf)
	cniVersion := os.Getenv("CNI_SPEC_VERSION")

	Context("l2bridge network::using host-local IPAM", func() {
		var nsName, name string
		var clientset *kubernetes.Clientset
		netconf := fmt.Sprintf(`
{'fraction_non_alphanumeric': 0.13556851311953352, 'fraction_numerical': 0.0068721366097459395, 'mean_word_length': 4.4979965655409275, 'pattern_counts': {'":': 0, '<': 4, '<?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': '3420505', 'n_tokens_mistral': 3498, 'n_tokens_neox': 3298, 'n_words': 700}