<commit_before>package driver

import (
	"context"
	"fmt"
	"net"
	"os"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/pkg/errors"
	libcalicoErrors "github.com/projectcalico/libcalico-go/lib/errors"

	dockerClient "github.com/docker/docker/client"
	"github.com/docker/go-plugins-helpers/network"
	"github.com/projectcalico/libcalico-go/lib/api"
	datastoreClient "github.com/projectcalico/libcalico-go/lib/client"
	caliconet "github.com/projectcalico/libcalico-go/lib/net"

	logutils "github.com/projectcalico/libnetwork-plugin/utils/log"
	mathutils "github.com/projectcalico/libnetwork-plugin/utils/math"
	"github.com/projectcalico/libnetwork-plugin/utils/netns"
	osutils "github.com/projectcalico/libnetwork-plugin/utils/os"
)

const DOCKER_LABEL_PREFIX = "org.projectcalico.label."
const LABEL_POLL_TIMEOUT_ENVKEY = "CALICO_LIBNETWORK_LABEL_POLL_TIMEOUT"
const CREATE_PROFILES_ENVKEY = "CALICO_LIBNETWORK_CREATE_PROFILES"
const LABEL_ENDPOINTS_ENVKEY = "CALICO_LIBNETWORK_LABEL_ENDPOINTS"

// NetworkDriver is the Calico network driver representation.
// Must be used with Calico IPAM and supports IPv4 only.
type NetworkDriver struct {
	client         *datastoreClient.Client
	containerName  string
	orchestratorID string
	fixedMac       string

	ifPrefix string

	DummyIPV4Nexthop string

	labelPollTimeout time.Duration

	createProfiles bool
	labelEndpoints bool
}

func NewNetworkDriver(client *datastoreClient.Client) network.Driver {
	driver := NetworkDriver{
		client: client,

		// The MAC address of the interface in the container is arbitrary, for
		// simplicity, use a fixed MAC unless overridden by user.
		fixedMac: "EE:EE:EE:EE:EE:EE",

		// Orchestrator and container IDs used in our endpoint identification. These
		// are fixed for libnetwork.  Unique endpoint identification is provided by
		// hostname and endpoint ID.
		containerName:  "libnetwork",
		orchestratorID: "libnetwork",

		ifPrefix:         IFPrefix,
		DummyIPV4Nexthop: "169.254.1.1",

		// default: enabled, disable by setting env key to false (case insensitive)
		createProfiles: !strings.EqualFold(os.Getenv(CREATE_PROFILES_ENVKEY), "false"),

		// default: disabled, enable by setting env key to true (case insensitive)
		labelEndpoints: strings.EqualFold(os.Getenv(LABEL_ENDPOINTS_ENVKEY), "true"),
	}

	if !driver.createProfiles {
		log.Info("Feature disabled: no Calico profiles will be created per network")
	}
	if driver.labelEndpoints {
		log.Info("Feature enabled: Calico workloadendpoints will be labelled with Docker labels")
		driver.labelPollTimeout = getLabelPollTimeout()
	}
	return driver
}

func (d NetworkDriver) GetCapabilities() (*network.CapabilitiesResponse, error) {
	resp := network.CapabilitiesResponse{Scope: "global"}
	logutils.JSONMessage("GetCapabilities response", resp)
	return &resp, nil
}

// AllocateNetwork is used for swarm-mode support in remote plugins, which
// Calico's libnetwork-plugin doesn't currently support.
func (d NetworkDriver) AllocateNetwork(request *network.AllocateNetworkRequest) (*network.AllocateNetworkResponse, error) {
	var resp network.AllocateNetworkResponse
	logutils.JSONMessage("AllocateNetwork response", resp)
	return &resp, nil
}

// FreeNetwork is used for swarm-mode support in remote plugins, which
// Calico's libnetwork-plugin doesn't currently support.
func (d NetworkDriver) FreeNetwork(request *network.FreeNetworkRequest) error {
	logutils.JSONMessage("FreeNetwork request", request)
	return nil
}

func (d NetworkDriver) CreateNetwork(request *network.CreateNetworkRequest) error {
	logutils.JSONMessage("CreateNetwork", request)

	// Reject all options (--internal, --enable_ipv6, etc)
	for k, v := range request.Options {
		optionSet := false
		flagName := k
		flagValue := fmt.Sprintf("%s", v)
		multipleFlags := false
		switch v := v.(type) {
		case bool:
			// if v == true then optionSet = true
			optionSet = v
			flagName = "--" + strings.TrimPrefix(k, "com.docker.network.")
			flagValue = ""
			break
		case map[string]interface{}:
			optionSet = len(v) != 0
			flagName = ""
			numFlags := 0
			for mk, _ := range v {
				flagName = flagName + "" + mk + ", "
				numFlags++
			}
			multipleFlags = numFlags > 1
			flagName = strings.TrimSuffix(flagName, ", ")
			flagValue = ""
			break
		default:
			// for unknown case let optionSet = true
			optionSet = true
		}
		if optionSet {<commit_msg>When reporting errors sort flags for consistency.<commit_after>package driver

import (
	"context"
	"fmt"
	"net"
	"os"
	"sort"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/pkg/errors"
	libcalicoErrors "github.com/projectcalico/libcalico-go/lib/errors"

	dockerClient "github.com/docker/docker/client"
	"github.com/docker/go-plugins-helpers/network"
	"github.com/projectcalico/libcalico-go/lib/api"
	datastoreClient "github.com/projectcalico/libcalico-go/lib/client"
	caliconet "github.com/projectcalico/libcalico-go/lib/net"

	logutils "github.com/projectcalico/libnetwork-plugin/utils/log"
	mathutils "github.com/projectcalico/libnetwork-plugin/utils/math"
	"github.com/projectcalico/libnetwork-plugin/utils/netns"
	osutils "github.com/projectcalico/libnetwork-plugin/utils/os"
)

const DOCKER_LABEL_PREFIX = "org.projectcalico.label."
const LABEL_POLL_TIMEOUT_ENVKEY = "CALICO_LIBNETWORK_LABEL_POLL_TIMEOUT"
const CREATE_PROFILES_ENVKEY = "CALICO_LIBNETWORK_CREATE_PROFILES"
const LABEL_ENDPOINTS_ENVKEY = "CALICO_LIBNETWORK_LABEL_ENDPOINTS"

// NetworkDriver is the Calico network driver representation.
// Must be used with Calico IPAM and supports IPv4 only.
type NetworkDriver struct {
	client         *datastoreClient.Client
	containerName  string
	orchestratorID string
	fixedMac       string

	ifPrefix string

	DummyIPV4Nexthop string

	labelPollTimeout time.Duration

	createProfiles bool
	labelEndpoints bool
}

func NewNetworkDriver(client *datastoreClient.Client) network.Driver {
	driver := NetworkDriver{
		client: client,

		// The MAC address of the interface in the container is arbitrary, for
		// simplicity, use a fixed MAC unless overridden by user.
		fixedMac: "EE:EE:EE:EE:EE:EE",

		// Orchestrator and container IDs used in our endpoint identification. These
		// are fixed for libnetwork.  Unique endpoint identification is provided by
		// hostname and endpoint ID.
		containerName:  "libnetwork",
		orchestratorID: "libnetwork",

		ifPrefix:         IFPrefix,
		DummyIPV4Nexthop: "169.254.1.1",

		// default: enabled, disable by setting env key to false (case insensitive)
		createProfiles: !strings.EqualFold(os.Getenv(CREATE_PROFILES_ENVKEY), "false"),

		// default: disabled, enable by setting env key to true (case insensitive)
		labelEndpoints: strings.EqualFold(os.Getenv(LABEL_ENDPOINTS_ENVKEY), "true"),
	}

	if !driver.createProfiles {
		log.Info("Feature disabled: no Calico profiles will be created per network")
	}
	if driver.labelEndpoints {
		log.Info("Feature enabled: Calico workloadendpoints will be labelled with Docker labels")
		driver.labelPollTimeout = getLabelPollTimeout()
	}
	return driver
}

func (d NetworkDriver) GetCapabilities() (*network.CapabilitiesResponse, error) {
	resp := network.CapabilitiesResponse{Scope: "global"}
	logutils.JSONMessage("GetCapabilities response", resp)
	return &resp, nil
}

// AllocateNetwork is used for swarm-mode support in remote plugins, which
// Calico's libnetwork-plugin doesn't currently support.
func (d NetworkDriver) AllocateNetwork(request *network.AllocateNetworkRequest) (*network.AllocateNetworkResponse, error) {
	var resp network.AllocateNetworkResponse
	logutils.JSONMessage("AllocateNetwork response", resp)
	return &resp, nil
}

// FreeNetwork is used for swarm-mode support in remote plugins, which
// Calico's libnetwork-plugin doesn't currently support.
func (d NetworkDriver) FreeNetwork(request *network.FreeNetworkRequest) error {
	logutils.JSONMessage("FreeNetwork request", request)
	return nil
}

func (d NetworkDriver) CreateNetwork(request *network.CreateNetworkRequest) error {
	logutils.JSONMessage("CreateNetwork", request)

	// Reject all options (--internal, --enable_ipv6, etc)
	for k, v := range request.Options {
		optionSet := false
		flagName := k
		flagValue := fmt.Sprintf("%s", v)
		multipleFlags := false
		switch v := v.(type) {
		case bool:
			// if v == true then optionSet = true
			optionSet = v
			flagName = "--" + strings.TrimPrefix(k, "com.docker.network.")
			flagValue = ""
			break
		case map[string]interface{}:
			optionSet = len(v) != 0
			flagName = ""
			numFlags := 0
			// Sort flags for consistent error reporting
			flags := []string{}
			for flag := range v {
				flags = append(flags, flag)
			}
			sort.Strings(flags)

			for _, flag := range flags {
				flagName = flagName + flag + ", "
				numFlags++
			}
			multipleFlags = numFlags > 1
			flagName = strings.TrimSuffix(flagName, ", ")
			flagValue = ""
			break
		default:
			// for unknown case let optionSet = true
			optionSet = true
		}
		if optionSet {
{'fraction_non_alphanumeric': 0.10271533496550189, 'fraction_numerical': 0.0033385265969285557, 'mean_word_length': 4.510116492949111, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, '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': '3360895', 'n_tokens_mistral': 3040, 'n_tokens_neox': 2815, 'n_words': 723}