mirror of https://github.com/k3s-io/k3s
wrapper ipvs API as util
parent
dcefbaefec
commit
09a853257f
|
@ -27,6 +27,7 @@ filegroup(
|
||||||
"//pkg/util/io:all-srcs",
|
"//pkg/util/io:all-srcs",
|
||||||
"//pkg/util/ipconfig:all-srcs",
|
"//pkg/util/ipconfig:all-srcs",
|
||||||
"//pkg/util/iptables:all-srcs",
|
"//pkg/util/iptables:all-srcs",
|
||||||
|
"//pkg/util/ipvs:all-srcs",
|
||||||
"//pkg/util/keymutex:all-srcs",
|
"//pkg/util/keymutex:all-srcs",
|
||||||
"//pkg/util/labels:all-srcs",
|
"//pkg/util/labels:all-srcs",
|
||||||
"//pkg/util/limitwriter:all-srcs",
|
"//pkg/util/limitwriter:all-srcs",
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
licenses(["notice"])
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@io_bazel_rules_go//go:def.bzl",
|
||||||
|
"go_library",
|
||||||
|
"go_test",
|
||||||
|
)
|
||||||
|
|
||||||
|
go_test(
|
||||||
|
name = "go_default_test",
|
||||||
|
srcs = [
|
||||||
|
"ipvs_test.go",
|
||||||
|
] + select({
|
||||||
|
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||||
|
"ipvs_linux_test.go",
|
||||||
|
],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
library = ":go_default_library",
|
||||||
|
tags = ["automanaged"],
|
||||||
|
deps = select({
|
||||||
|
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||||
|
"//vendor/github.com/docker/libnetwork/ipvs:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||||
|
],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"ipvs.go",
|
||||||
|
"ipvs_unsupported.go",
|
||||||
|
] + select({
|
||||||
|
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||||
|
"ipvs_linux.go",
|
||||||
|
],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
deps = [
|
||||||
|
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||||
|
] + select({
|
||||||
|
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||||
|
"//vendor/github.com/docker/libnetwork/ipvs:go_default_library",
|
||||||
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
|
],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [
|
||||||
|
":package-srcs",
|
||||||
|
"//pkg/util/ipvs/testing:all-srcs",
|
||||||
|
],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
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 ipvs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Interface is an injectable interface for running ipvs commands. Implementations must be goroutine-safe.
|
||||||
|
type Interface interface {
|
||||||
|
// Flush clears all virtual servers in system. return occurred error immediately.
|
||||||
|
Flush() error
|
||||||
|
// EnsureVirtualServerAddressBind checks if virtual server's address is bound to dummy interface and, if not, binds it. If the address is already bound, return true.
|
||||||
|
EnsureVirtualServerAddressBind(serv *VirtualServer, dev string) (exist bool, err error)
|
||||||
|
// UnbindVirtualServerAddress checks if virtual server's address is bound to dummy interface and, if so, unbinds it.
|
||||||
|
UnbindVirtualServerAddress(serv *VirtualServer, dev string) error
|
||||||
|
// AddVirtualServer creates the specified virtual server.
|
||||||
|
AddVirtualServer(*VirtualServer) error
|
||||||
|
// UpdateVirtualServer updates an already existing virtual server. If the virtual server does not exist, return error.
|
||||||
|
UpdateVirtualServer(*VirtualServer) error
|
||||||
|
// DeleteVirtualServer deletes the specified virtual server. If the virtual server does not exist, return error.
|
||||||
|
DeleteVirtualServer(*VirtualServer) error
|
||||||
|
// Given a partial virtual server, GetVirtualServer will return the specified virtual server information in the system.
|
||||||
|
GetVirtualServer(*VirtualServer) (*VirtualServer, error)
|
||||||
|
// GetVirtualServers lists all virtual servers in the system.
|
||||||
|
GetVirtualServers() ([]*VirtualServer, error)
|
||||||
|
// AddRealServer creates the specified real server for the specified virtual server.
|
||||||
|
AddRealServer(*VirtualServer, *RealServer) error
|
||||||
|
// GetRealServers returns all real servers for the specified virtual server.
|
||||||
|
GetRealServers(*VirtualServer) ([]*RealServer, error)
|
||||||
|
// DeleteRealServer deletes the specified real server from the specified virtual server.
|
||||||
|
DeleteRealServer(*VirtualServer, *RealServer) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// VirtualServer is an user-oriented definition of an IPVS virtual server in its entirety.
|
||||||
|
type VirtualServer struct {
|
||||||
|
Address net.IP
|
||||||
|
Protocol string
|
||||||
|
Port uint16
|
||||||
|
Scheduler string
|
||||||
|
Flags ServiceFlags
|
||||||
|
Timeout uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServiceFlags is used to specify session affinity, ip hash etc.
|
||||||
|
type ServiceFlags uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
// FlagPersistent specify IPVS service session affinity
|
||||||
|
FlagPersistent = 0x1
|
||||||
|
)
|
||||||
|
|
||||||
|
// Equal check the equality of virtual server.
|
||||||
|
// We don't use struct == since it doesn't work because of slice.
|
||||||
|
func (svc *VirtualServer) Equal(other *VirtualServer) bool {
|
||||||
|
return svc.Address.Equal(other.Address) &&
|
||||||
|
svc.Protocol == other.Protocol &&
|
||||||
|
svc.Port == other.Port &&
|
||||||
|
svc.Scheduler == other.Scheduler &&
|
||||||
|
svc.Flags == other.Flags &&
|
||||||
|
svc.Timeout == other.Timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
func (svc *VirtualServer) String() string {
|
||||||
|
return net.JoinHostPort(svc.Address.String(), strconv.Itoa(int(svc.Port))) + "/" + svc.Protocol
|
||||||
|
}
|
||||||
|
|
||||||
|
// RealServer is an user-oriented definition of an IPVS real server in its entirety.
|
||||||
|
type RealServer struct {
|
||||||
|
Address net.IP
|
||||||
|
Port uint16
|
||||||
|
Weight int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dest *RealServer) String() string {
|
||||||
|
return net.JoinHostPort(dest.Address.String(), strconv.Itoa(int(dest.Port)))
|
||||||
|
}
|
|
@ -0,0 +1,302 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 ipvs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/docker/libnetwork/ipvs"
|
||||||
|
"github.com/golang/glog"
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
const cmdIP = "ip"
|
||||||
|
|
||||||
|
// runner implements Interface.
|
||||||
|
type runner struct {
|
||||||
|
exec utilexec.Interface
|
||||||
|
ipvsHandle *ipvs.Handle
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new Interface which will call ipvs APIs.
|
||||||
|
func New(exec utilexec.Interface) Interface {
|
||||||
|
ihandle, err := ipvs.New("")
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("IPVS interface can't be initialized, error: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &runner{
|
||||||
|
exec: exec,
|
||||||
|
ipvsHandle: ihandle,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnsureVirtualServerAddressBind is part of Interface.
|
||||||
|
func (runner *runner) EnsureVirtualServerAddressBind(vs *VirtualServer, dummyDev string) (exist bool, err error) {
|
||||||
|
addr := vs.Address.String() + "/32"
|
||||||
|
args := []string{"addr", "add", addr, "dev", dummyDev}
|
||||||
|
out, err := runner.exec.Command(cmdIP, args...).CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
// "exit status 2" will be returned if the address is already bound to dummy device
|
||||||
|
if ee, ok := err.(utilexec.ExitError); ok {
|
||||||
|
if ee.Exited() && ee.ExitStatus() == 2 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("error bind address: %s to dummy interface: %s, err: %v: %s", vs.Address.String(), dummyDev, err, out)
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnbindVirtualServerAddress is part of Interface.
|
||||||
|
func (runner *runner) UnbindVirtualServerAddress(vs *VirtualServer, dummyDev string) error {
|
||||||
|
addr := vs.Address.String() + "/32"
|
||||||
|
args := []string{"addr", "del", addr, "dev", dummyDev}
|
||||||
|
out, err := runner.exec.Command(cmdIP, args...).CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error unbind address: %s from dummy interface: %s, err: %v: %s", vs.Address.String(), dummyDev, err, out)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddVirtualServer is part of Interface.
|
||||||
|
func (runner *runner) AddVirtualServer(vs *VirtualServer) error {
|
||||||
|
eSvc, err := toBackendService(vs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return runner.ipvsHandle.NewService(eSvc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateVirtualServer is part of Interface.
|
||||||
|
func (runner *runner) UpdateVirtualServer(vs *VirtualServer) error {
|
||||||
|
bSvc, err := toBackendService(vs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return runner.ipvsHandle.UpdateService(bSvc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteVirtualServer is part of Interface.
|
||||||
|
func (runner *runner) DeleteVirtualServer(vs *VirtualServer) error {
|
||||||
|
bSvc, err := toBackendService(vs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return runner.ipvsHandle.DelService(bSvc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVirtualServer is part of Interface.
|
||||||
|
func (runner *runner) GetVirtualServer(vs *VirtualServer) (*VirtualServer, error) {
|
||||||
|
bSvc, err := toBackendService(vs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ipvsService, err := runner.ipvsHandle.GetService(bSvc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
virtualServer, err := toVirtualServer(ipvsService)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return virtualServer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVirtualServers is part of Interface.
|
||||||
|
func (runner *runner) GetVirtualServers() ([]*VirtualServer, error) {
|
||||||
|
ipvsServices, err := runner.ipvsHandle.GetServices()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
vss := make([]*VirtualServer, 0)
|
||||||
|
for _, ipvsService := range ipvsServices {
|
||||||
|
vs, err := toVirtualServer(ipvsService)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
vss = append(vss, vs)
|
||||||
|
}
|
||||||
|
return vss, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush is part of Interface. Currently we delete IPVS services one by one
|
||||||
|
func (runner *runner) Flush() error {
|
||||||
|
vss, err := runner.GetVirtualServers()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, vs := range vss {
|
||||||
|
err := runner.DeleteVirtualServer(vs)
|
||||||
|
// TODO: aggregate errors?
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRealServer is part of Interface.
|
||||||
|
func (runner *runner) AddRealServer(vs *VirtualServer, rs *RealServer) error {
|
||||||
|
bSvc, err := toBackendService(vs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
bDst, err := toBackendDestination(rs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return runner.ipvsHandle.NewDestination(bSvc, bDst)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRealServer is part of Interface.
|
||||||
|
func (runner *runner) DeleteRealServer(vs *VirtualServer, rs *RealServer) error {
|
||||||
|
bSvc, err := toBackendService(vs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
bDst, err := toBackendDestination(rs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return runner.ipvsHandle.DelDestination(bSvc, bDst)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRealServers is part of Interface.
|
||||||
|
func (runner *runner) GetRealServers(vs *VirtualServer) ([]*RealServer, error) {
|
||||||
|
bSvc, err := toBackendService(vs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bDestinations, err := runner.ipvsHandle.GetDestinations(bSvc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
realServers := make([]*RealServer, 0)
|
||||||
|
for _, dest := range bDestinations {
|
||||||
|
dst, err := toRealServer(dest)
|
||||||
|
// TODO: aggregate errors?
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
realServers = append(realServers, dst)
|
||||||
|
}
|
||||||
|
return realServers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toVirtualServer converts an IPVS service representation to the equivalent virtual server structure.
|
||||||
|
func toVirtualServer(svc *ipvs.Service) (*VirtualServer, error) {
|
||||||
|
if svc == nil {
|
||||||
|
return nil, errors.New("ipvs svc should not be empty")
|
||||||
|
}
|
||||||
|
vs := &VirtualServer{
|
||||||
|
Address: svc.Address,
|
||||||
|
Port: svc.Port,
|
||||||
|
Scheduler: svc.SchedName,
|
||||||
|
Protocol: protocolNumbeToString(ProtoType(svc.Protocol)),
|
||||||
|
Flags: ServiceFlags(svc.Flags),
|
||||||
|
Timeout: svc.Timeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
if vs.Address == nil {
|
||||||
|
if svc.AddressFamily == syscall.AF_INET {
|
||||||
|
vs.Address = net.IPv4zero
|
||||||
|
} else {
|
||||||
|
vs.Address = net.IPv6zero
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toRealServer converts an IPVS destination representation to the equivalent real server structure.
|
||||||
|
func toRealServer(dst *ipvs.Destination) (*RealServer, error) {
|
||||||
|
if dst == nil {
|
||||||
|
return nil, errors.New("ipvs destination should not be empty")
|
||||||
|
}
|
||||||
|
return &RealServer{
|
||||||
|
Address: dst.Address,
|
||||||
|
Port: dst.Port,
|
||||||
|
Weight: dst.Weight,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toBackendService converts an IPVS real server representation to the equivalent "backend" service structure.
|
||||||
|
func toBackendService(vs *VirtualServer) (*ipvs.Service, error) {
|
||||||
|
if vs == nil {
|
||||||
|
return nil, errors.New("virtual server should not be empty")
|
||||||
|
}
|
||||||
|
bakSvc := &ipvs.Service{
|
||||||
|
Address: vs.Address,
|
||||||
|
Protocol: stringToProtocolNumber(vs.Protocol),
|
||||||
|
Port: vs.Port,
|
||||||
|
SchedName: vs.Scheduler,
|
||||||
|
Flags: uint32(vs.Flags),
|
||||||
|
Timeout: vs.Timeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip4 := vs.Address.To4(); ip4 != nil {
|
||||||
|
bakSvc.AddressFamily = syscall.AF_INET
|
||||||
|
bakSvc.Netmask = 0xffffffff
|
||||||
|
} else {
|
||||||
|
bakSvc.AddressFamily = syscall.AF_INET6
|
||||||
|
bakSvc.Netmask = 128
|
||||||
|
}
|
||||||
|
return bakSvc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// toBackendDestination converts an IPVS real server representation to the equivalent "backend" destination structure.
|
||||||
|
func toBackendDestination(rs *RealServer) (*ipvs.Destination, error) {
|
||||||
|
if rs == nil {
|
||||||
|
return nil, errors.New("real server should not be empty")
|
||||||
|
}
|
||||||
|
return &ipvs.Destination{
|
||||||
|
Address: rs.Address,
|
||||||
|
Port: rs.Port,
|
||||||
|
Weight: rs.Weight,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// stringToProtocolNumber returns the protocol value for the given name
|
||||||
|
func stringToProtocolNumber(protocol string) uint16 {
|
||||||
|
switch strings.ToLower(protocol) {
|
||||||
|
case "tcp":
|
||||||
|
return uint16(syscall.IPPROTO_TCP)
|
||||||
|
case "udp":
|
||||||
|
return uint16(syscall.IPPROTO_UDP)
|
||||||
|
}
|
||||||
|
return uint16(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// protocolNumbeToString returns the name for the given protocol value.
|
||||||
|
func protocolNumbeToString(proto ProtoType) string {
|
||||||
|
switch proto {
|
||||||
|
case syscall.IPPROTO_TCP:
|
||||||
|
return "TCP"
|
||||||
|
case syscall.IPPROTO_UDP:
|
||||||
|
return "UDP"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProtoType is IPVS service protocol type
|
||||||
|
type ProtoType uint16
|
|
@ -0,0 +1,448 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 ipvs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"syscall"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/utils/exec"
|
||||||
|
fakeexec "k8s.io/utils/exec/testing"
|
||||||
|
|
||||||
|
"github.com/docker/libnetwork/ipvs"
|
||||||
|
)
|
||||||
|
|
||||||
|
const dummyDevice = "kube-ipvs0"
|
||||||
|
|
||||||
|
func TestEnsureVirtualServerAddressBind(t *testing.T) {
|
||||||
|
vs := &VirtualServer{
|
||||||
|
Address: net.ParseIP("10.20.30.40"),
|
||||||
|
Port: uint16(1234),
|
||||||
|
Protocol: string("TCP"),
|
||||||
|
}
|
||||||
|
fcmd := fakeexec.FakeCmd{
|
||||||
|
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
|
||||||
|
// Success.
|
||||||
|
func() ([]byte, error) { return []byte{}, nil },
|
||||||
|
// Exists.
|
||||||
|
func() ([]byte, error) { return nil, &fakeexec.FakeExitError{Status: 2} },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fexec := fakeexec.FakeExec{
|
||||||
|
CommandScript: []fakeexec.FakeCommandAction{
|
||||||
|
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||||
|
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
runner := New(&fexec)
|
||||||
|
// Success.
|
||||||
|
exists, err := runner.EnsureVirtualServerAddressBind(vs, dummyDevice)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expected success, got %v", err)
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
t.Errorf("expected exists = false")
|
||||||
|
}
|
||||||
|
if fcmd.CombinedOutputCalls != 1 {
|
||||||
|
t.Errorf("expected 1 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
|
||||||
|
}
|
||||||
|
if !sets.NewString(fcmd.CombinedOutputLog[0]...).HasAll("ip", "addr", "add", "10.20.30.40/32", "dev", "kube-ipvs0") {
|
||||||
|
t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0])
|
||||||
|
}
|
||||||
|
// Exists.
|
||||||
|
exists, err = runner.EnsureVirtualServerAddressBind(vs, dummyDevice)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expected success, got %v", err)
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
t.Errorf("expected exists = true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnbindVirtualServerAddress(t *testing.T) {
|
||||||
|
svc := &VirtualServer{
|
||||||
|
Address: net.ParseIP("10.20.30.41"),
|
||||||
|
Port: uint16(80),
|
||||||
|
Protocol: string("TCP"),
|
||||||
|
}
|
||||||
|
fcmd := fakeexec.FakeCmd{
|
||||||
|
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
|
||||||
|
// Success.
|
||||||
|
func() ([]byte, error) { return []byte{}, nil },
|
||||||
|
// Failure.
|
||||||
|
func() ([]byte, error) { return nil, &fakeexec.FakeExitError{Status: 2} },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fexec := fakeexec.FakeExec{
|
||||||
|
CommandScript: []fakeexec.FakeCommandAction{
|
||||||
|
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||||
|
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
runner := New(&fexec)
|
||||||
|
// Success.
|
||||||
|
err := runner.UnbindVirtualServerAddress(svc, dummyDevice)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("expected success, got %v", err)
|
||||||
|
}
|
||||||
|
if fcmd.CombinedOutputCalls != 1 {
|
||||||
|
t.Errorf("expected 1 CombinedOutput() calls, got %d", fcmd.CombinedOutputCalls)
|
||||||
|
}
|
||||||
|
if !sets.NewString(fcmd.CombinedOutputLog[0]...).HasAll("ip", "addr", "del", "10.20.30.41/32", "dev", "kube-ipvs0") {
|
||||||
|
t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0])
|
||||||
|
}
|
||||||
|
// Failure.
|
||||||
|
err = runner.UnbindVirtualServerAddress(svc, dummyDevice)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_toFrontendService(t *testing.T) {
|
||||||
|
Tests := []struct {
|
||||||
|
ipvsService ipvs.Service
|
||||||
|
virtualServer VirtualServer
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
ipvs.Service{
|
||||||
|
Protocol: syscall.IPPROTO_TCP,
|
||||||
|
Port: 80,
|
||||||
|
FWMark: 0,
|
||||||
|
SchedName: "",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
Netmask: 0xffffffff,
|
||||||
|
AddressFamily: syscall.AF_INET,
|
||||||
|
Address: nil,
|
||||||
|
PEName: "",
|
||||||
|
},
|
||||||
|
VirtualServer{
|
||||||
|
Address: net.ParseIP("0.0.0.0"),
|
||||||
|
Protocol: "TCP",
|
||||||
|
Port: 80,
|
||||||
|
Scheduler: "",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ipvs.Service{
|
||||||
|
Protocol: syscall.IPPROTO_UDP,
|
||||||
|
Port: 33434,
|
||||||
|
FWMark: 0,
|
||||||
|
SchedName: "wlc",
|
||||||
|
Flags: 1234,
|
||||||
|
Timeout: 100,
|
||||||
|
Netmask: 128,
|
||||||
|
AddressFamily: syscall.AF_INET6,
|
||||||
|
Address: net.ParseIP("2012::beef"),
|
||||||
|
PEName: "",
|
||||||
|
},
|
||||||
|
VirtualServer{
|
||||||
|
Address: net.ParseIP("2012::beef"),
|
||||||
|
Protocol: "UDP",
|
||||||
|
Port: 33434,
|
||||||
|
Scheduler: "wlc",
|
||||||
|
Flags: 1234,
|
||||||
|
Timeout: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ipvs.Service{
|
||||||
|
Protocol: 0,
|
||||||
|
Port: 0,
|
||||||
|
FWMark: 0,
|
||||||
|
SchedName: "lc",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
Netmask: 0xffffffff,
|
||||||
|
AddressFamily: syscall.AF_INET,
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
PEName: "",
|
||||||
|
},
|
||||||
|
VirtualServer{
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
Protocol: "",
|
||||||
|
Port: 0,
|
||||||
|
Scheduler: "lc",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ipvs.Service{
|
||||||
|
Protocol: 0,
|
||||||
|
Port: 0,
|
||||||
|
FWMark: 0,
|
||||||
|
SchedName: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
Netmask: 128,
|
||||||
|
AddressFamily: syscall.AF_INET6,
|
||||||
|
Address: nil,
|
||||||
|
PEName: "",
|
||||||
|
},
|
||||||
|
VirtualServer{
|
||||||
|
Address: net.ParseIP("::0"),
|
||||||
|
Protocol: "",
|
||||||
|
Port: 0,
|
||||||
|
Scheduler: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range Tests {
|
||||||
|
got, err := toVirtualServer(&Tests[i].ipvsService)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case: %d, unexpected error: %v", i, err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(*got, Tests[i].virtualServer) {
|
||||||
|
t.Errorf("case: %d, got %#v, want %#v", i, *got, Tests[i].virtualServer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_toBackendService(t *testing.T) {
|
||||||
|
Tests := []struct {
|
||||||
|
ipvsService ipvs.Service
|
||||||
|
virtualServer VirtualServer
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
ipvs.Service{
|
||||||
|
Protocol: syscall.IPPROTO_TCP,
|
||||||
|
Port: 80,
|
||||||
|
FWMark: 0,
|
||||||
|
SchedName: "",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
Netmask: 0xffffffff,
|
||||||
|
AddressFamily: syscall.AF_INET,
|
||||||
|
Address: net.ParseIP("0.0.0.0"),
|
||||||
|
PEName: "",
|
||||||
|
},
|
||||||
|
VirtualServer{
|
||||||
|
Address: net.ParseIP("0.0.0.0"),
|
||||||
|
Protocol: "TCP",
|
||||||
|
Port: 80,
|
||||||
|
Scheduler: "",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ipvs.Service{
|
||||||
|
Protocol: syscall.IPPROTO_UDP,
|
||||||
|
Port: 33434,
|
||||||
|
FWMark: 0,
|
||||||
|
SchedName: "wlc",
|
||||||
|
Flags: 1234,
|
||||||
|
Timeout: 100,
|
||||||
|
Netmask: 128,
|
||||||
|
AddressFamily: syscall.AF_INET6,
|
||||||
|
Address: net.ParseIP("2012::beef"),
|
||||||
|
PEName: "",
|
||||||
|
},
|
||||||
|
VirtualServer{
|
||||||
|
Address: net.ParseIP("2012::beef"),
|
||||||
|
Protocol: "UDP",
|
||||||
|
Port: 33434,
|
||||||
|
Scheduler: "wlc",
|
||||||
|
Flags: 1234,
|
||||||
|
Timeout: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ipvs.Service{
|
||||||
|
Protocol: 0,
|
||||||
|
Port: 0,
|
||||||
|
FWMark: 0,
|
||||||
|
SchedName: "lc",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
Netmask: 0xffffffff,
|
||||||
|
AddressFamily: syscall.AF_INET,
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
PEName: "",
|
||||||
|
},
|
||||||
|
VirtualServer{
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
Protocol: "",
|
||||||
|
Port: 0,
|
||||||
|
Scheduler: "lc",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ipvs.Service{
|
||||||
|
Protocol: 0,
|
||||||
|
Port: 0,
|
||||||
|
FWMark: 0,
|
||||||
|
SchedName: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
Netmask: 128,
|
||||||
|
AddressFamily: syscall.AF_INET6,
|
||||||
|
Address: net.ParseIP("::0"),
|
||||||
|
PEName: "",
|
||||||
|
},
|
||||||
|
VirtualServer{
|
||||||
|
Address: net.ParseIP("::0"),
|
||||||
|
Protocol: "",
|
||||||
|
Port: 0,
|
||||||
|
Scheduler: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range Tests {
|
||||||
|
got, err := toBackendService(&Tests[i].virtualServer)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case: %d, unexpected error: %v", i, err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(*got, Tests[i].ipvsService) {
|
||||||
|
t.Errorf("case: %d - got %#v, want %#v", i, *got, Tests[i].ipvsService)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_toFrontendDestination(t *testing.T) {
|
||||||
|
Tests := []struct {
|
||||||
|
ipvsDestination ipvs.Destination
|
||||||
|
realServer RealServer
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
ipvs.Destination{
|
||||||
|
Port: 54321,
|
||||||
|
ConnectionFlags: 0,
|
||||||
|
Weight: 1,
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
},
|
||||||
|
RealServer{
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
Port: 54321,
|
||||||
|
Weight: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ipvs.Destination{
|
||||||
|
Port: 53,
|
||||||
|
ConnectionFlags: 0,
|
||||||
|
Weight: 1,
|
||||||
|
Address: net.ParseIP("2002::cafe"),
|
||||||
|
},
|
||||||
|
RealServer{
|
||||||
|
Address: net.ParseIP("2002::cafe"),
|
||||||
|
Port: 53,
|
||||||
|
Weight: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i := range Tests {
|
||||||
|
got, err := toRealServer(&Tests[i].ipvsDestination)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case %d unexpected error: %d", i, err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(*got, Tests[i].realServer) {
|
||||||
|
t.Errorf("case %d Failed to translate Destination - got %#v, want %#v", i, *got, Tests[i].realServer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_toBackendDestination(t *testing.T) {
|
||||||
|
Tests := []struct {
|
||||||
|
realServer RealServer
|
||||||
|
ipvsDestination ipvs.Destination
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
RealServer{
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
Port: 54321,
|
||||||
|
Weight: 1,
|
||||||
|
},
|
||||||
|
ipvs.Destination{
|
||||||
|
Port: 54321,
|
||||||
|
ConnectionFlags: 0,
|
||||||
|
Weight: 1,
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
RealServer{
|
||||||
|
Address: net.ParseIP("2002::cafe"),
|
||||||
|
Port: 53,
|
||||||
|
Weight: 1,
|
||||||
|
},
|
||||||
|
ipvs.Destination{
|
||||||
|
Port: 53,
|
||||||
|
ConnectionFlags: 0,
|
||||||
|
Weight: 1,
|
||||||
|
Address: net.ParseIP("2002::cafe"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i := range Tests {
|
||||||
|
got, err := toBackendDestination(&Tests[i].realServer)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("case %d unexpected error: %d", i, err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(*got, Tests[i].ipvsDestination) {
|
||||||
|
t.Errorf("case %d Failed to translate Destination - got %#v, want %#v", i, *got, Tests[i].ipvsDestination)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_stringToProtocolNumber(t *testing.T) {
|
||||||
|
tests := []string{
|
||||||
|
"TCP", "UDP", "ICMP",
|
||||||
|
}
|
||||||
|
expecteds := []uint16{
|
||||||
|
uint16(syscall.IPPROTO_TCP), uint16(syscall.IPPROTO_UDP), uint16(0),
|
||||||
|
}
|
||||||
|
for i := range tests {
|
||||||
|
got := stringToProtocolNumber(tests[i])
|
||||||
|
if got != expecteds[i] {
|
||||||
|
t.Errorf("stringToProtocolNumber() failed - got %#v, want %#v",
|
||||||
|
got, expecteds[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_protocolNumberToString(t *testing.T) {
|
||||||
|
tests := []ProtoType{
|
||||||
|
syscall.IPPROTO_TCP, syscall.IPPROTO_UDP, ProtoType(0),
|
||||||
|
}
|
||||||
|
expecteds := []string{
|
||||||
|
"TCP", "UDP", "",
|
||||||
|
}
|
||||||
|
for i := range tests {
|
||||||
|
got := protocolNumbeToString(tests[i])
|
||||||
|
if got != expecteds[i] {
|
||||||
|
t.Errorf("protocolNumbeToString() failed - got %#v, want %#v",
|
||||||
|
got, expecteds[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,265 @@
|
||||||
|
/*
|
||||||
|
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 ipvs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVirtualServerEqual(t *testing.T) {
|
||||||
|
Tests := []struct {
|
||||||
|
svcA *VirtualServer
|
||||||
|
svcB *VirtualServer
|
||||||
|
equal bool
|
||||||
|
reason string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
svcA: &VirtualServer{
|
||||||
|
Address: net.ParseIP("10.20.30.40"),
|
||||||
|
Protocol: "",
|
||||||
|
Port: 0,
|
||||||
|
Scheduler: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
svcB: &VirtualServer{
|
||||||
|
Address: net.ParseIP("10.20.30.41"),
|
||||||
|
Protocol: "",
|
||||||
|
Port: 0,
|
||||||
|
Scheduler: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
equal: false,
|
||||||
|
reason: "IPv4 address not equal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
svcA: &VirtualServer{
|
||||||
|
Address: net.ParseIP("2012::beef"),
|
||||||
|
Protocol: "",
|
||||||
|
Port: 0,
|
||||||
|
Scheduler: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
svcB: &VirtualServer{
|
||||||
|
Address: net.ParseIP("2017::beef"),
|
||||||
|
Protocol: "",
|
||||||
|
Port: 0,
|
||||||
|
Scheduler: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
equal: false,
|
||||||
|
reason: "IPv6 address not equal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
svcA: &VirtualServer{
|
||||||
|
Address: net.ParseIP("2012::beef"),
|
||||||
|
Protocol: "TCP",
|
||||||
|
Port: 0,
|
||||||
|
Scheduler: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
svcB: &VirtualServer{
|
||||||
|
Address: net.ParseIP("2012::beeef"),
|
||||||
|
Protocol: "UDP",
|
||||||
|
Port: 0,
|
||||||
|
Scheduler: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
equal: false,
|
||||||
|
reason: "Protocol not equal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
svcA: &VirtualServer{
|
||||||
|
Address: net.ParseIP("2012::beef"),
|
||||||
|
Protocol: "TCP",
|
||||||
|
Port: 80,
|
||||||
|
Scheduler: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
svcB: &VirtualServer{
|
||||||
|
Address: net.ParseIP("2012::beef"),
|
||||||
|
Protocol: "TCP",
|
||||||
|
Port: 8080,
|
||||||
|
Scheduler: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
equal: false,
|
||||||
|
reason: "Port not equal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
svcA: &VirtualServer{
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
Protocol: "TCP",
|
||||||
|
Port: 80,
|
||||||
|
Scheduler: "rr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
svcB: &VirtualServer{
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
Protocol: "TCP",
|
||||||
|
Port: 80,
|
||||||
|
Scheduler: "wlc",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
equal: false,
|
||||||
|
reason: "Scheduler not equal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
svcA: &VirtualServer{
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
Protocol: "TCP",
|
||||||
|
Port: 80,
|
||||||
|
Scheduler: "rr",
|
||||||
|
Flags: 2,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
svcB: &VirtualServer{
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
Protocol: "TCP",
|
||||||
|
Port: 80,
|
||||||
|
Scheduler: "rr",
|
||||||
|
Flags: 3,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
equal: false,
|
||||||
|
reason: "Flags not equal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
svcA: &VirtualServer{
|
||||||
|
Address: net.ParseIP("2012::beef"),
|
||||||
|
Protocol: "",
|
||||||
|
Port: 0,
|
||||||
|
Scheduler: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 0,
|
||||||
|
},
|
||||||
|
svcB: &VirtualServer{
|
||||||
|
Address: net.ParseIP("2012::beef"),
|
||||||
|
Protocol: "",
|
||||||
|
Port: 0,
|
||||||
|
Scheduler: "wrr",
|
||||||
|
Flags: 0,
|
||||||
|
Timeout: 10800,
|
||||||
|
},
|
||||||
|
equal: false,
|
||||||
|
reason: "Timeout not equal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
svcA: &VirtualServer{
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
Protocol: "TCP",
|
||||||
|
Port: 80,
|
||||||
|
Scheduler: "rr",
|
||||||
|
Flags: 0x1,
|
||||||
|
Timeout: 10800,
|
||||||
|
},
|
||||||
|
svcB: &VirtualServer{
|
||||||
|
Address: net.ParseIP("1.2.3.4"),
|
||||||
|
Protocol: "TCP",
|
||||||
|
Port: 80,
|
||||||
|
Scheduler: "rr",
|
||||||
|
Flags: 0x1,
|
||||||
|
Timeout: 10800,
|
||||||
|
},
|
||||||
|
equal: true,
|
||||||
|
reason: "All fields equal",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range Tests {
|
||||||
|
equal := Tests[i].svcA.Equal(Tests[i].svcB)
|
||||||
|
if equal != Tests[i].equal {
|
||||||
|
t.Errorf("case: %d got %v, expected %v, reason: %s", i, equal, Tests[i].equal, Tests[i].reason)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFrontendServiceString(t *testing.T) {
|
||||||
|
Tests := []struct {
|
||||||
|
svc *VirtualServer
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
svc: &VirtualServer{
|
||||||
|
Address: net.ParseIP("10.20.30.40"),
|
||||||
|
Protocol: "TCP",
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
expected: "10.20.30.40:80/TCP",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
svc: &VirtualServer{
|
||||||
|
Address: net.ParseIP("2012::beef"),
|
||||||
|
Protocol: "UDP",
|
||||||
|
Port: 8080,
|
||||||
|
},
|
||||||
|
expected: "[2012::beef]:8080/UDP",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
svc: &VirtualServer{
|
||||||
|
Address: net.ParseIP("10.20.30.41"),
|
||||||
|
Protocol: "ESP",
|
||||||
|
Port: 1234,
|
||||||
|
},
|
||||||
|
expected: "10.20.30.41:1234/ESP",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range Tests {
|
||||||
|
if Tests[i].expected != Tests[i].svc.String() {
|
||||||
|
t.Errorf("case: %d got %v, expected %v", i, Tests[i].svc.String(), Tests[i].expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFrontendDestinationString(t *testing.T) {
|
||||||
|
Tests := []struct {
|
||||||
|
svc *RealServer
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
svc: &RealServer{
|
||||||
|
Address: net.ParseIP("10.20.30.40"),
|
||||||
|
Port: 80,
|
||||||
|
},
|
||||||
|
expected: "10.20.30.40:80",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
svc: &RealServer{
|
||||||
|
Address: net.ParseIP("2012::beef"),
|
||||||
|
Port: 8080,
|
||||||
|
},
|
||||||
|
expected: "[2012::beef]:8080",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range Tests {
|
||||||
|
if Tests[i].expected != Tests[i].svc.String() {
|
||||||
|
t.Errorf("case: %d got %v, expected %v", i, Tests[i].svc.String(), Tests[i].expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 ipvs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
utilexec "k8s.io/utils/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// New returns a dummy Interface for unsupported platform.
|
||||||
|
func New(utilexec.Interface) Interface {
|
||||||
|
return &runner{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type runner struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (runner *runner) Flush() error {
|
||||||
|
return fmt.Errorf("IPVS not supported for this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (runner *runner) EnsureVirtualServerAddressBind(*VirtualServer, string) (bool, error) {
|
||||||
|
return false, fmt.Errorf("IPVS not supported for this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (runner *runner) UnbindVirtualServerAddress(*VirtualServer, string) error {
|
||||||
|
return fmt.Errorf("IPVS not supported for this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (runner *runner) AddVirtualServer(*VirtualServer) error {
|
||||||
|
return fmt.Errorf("IPVS not supported for this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (runner *runner) UpdateVirtualServer(*VirtualServer) error {
|
||||||
|
return fmt.Errorf("IPVS not supported for this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (runner *runner) DeleteVirtualServer(*VirtualServer) error {
|
||||||
|
return fmt.Errorf("IPVS not supported for this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (runner *runner) GetVirtualServer(*VirtualServer) (*VirtualServer, error) {
|
||||||
|
return nil, fmt.Errorf("IPVS not supported for this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (runner *runner) GetVirtualServers() ([]*VirtualServer, error) {
|
||||||
|
return nil, fmt.Errorf("IPVS not supported for this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (runner *runner) AddRealServer(*VirtualServer, *RealServer) error {
|
||||||
|
return fmt.Errorf("IPVS not supported for this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (runner *runner) GetRealServers(*VirtualServer) ([]*RealServer, error) {
|
||||||
|
return nil, fmt.Errorf("IPVS not supported for this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (runner *runner) DeleteRealServer(*VirtualServer, *RealServer) error {
|
||||||
|
return fmt.Errorf("IPVS not supported for this platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Interface(&runner{})
|
|
@ -0,0 +1,28 @@
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
licenses(["notice"])
|
||||||
|
|
||||||
|
load(
|
||||||
|
"@io_bazel_rules_go//go:def.bzl",
|
||||||
|
"go_library",
|
||||||
|
)
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["fake.go"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
deps = ["//pkg/util/ipvs:go_default_library"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
|
@ -0,0 +1,168 @@
|
||||||
|
/*
|
||||||
|
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 testing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
utilipvs "k8s.io/kubernetes/pkg/util/ipvs"
|
||||||
|
)
|
||||||
|
|
||||||
|
//FakeIPVS no-op implementation of ipvs Interface
|
||||||
|
type FakeIPVS struct {
|
||||||
|
Scheduler string
|
||||||
|
Services map[serviceKey]*utilipvs.VirtualServer
|
||||||
|
Destinations map[serviceKey][]*utilipvs.RealServer
|
||||||
|
}
|
||||||
|
|
||||||
|
type serviceKey struct {
|
||||||
|
IP string
|
||||||
|
Port uint16
|
||||||
|
Protocol string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serviceKey) String() string {
|
||||||
|
return fmt.Sprintf("%s:%d/%s", s.IP, s.Port, s.Protocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewFake creates a fake ipvs strucuter
|
||||||
|
func NewFake() *FakeIPVS {
|
||||||
|
return &FakeIPVS{
|
||||||
|
Services: make(map[serviceKey]*utilipvs.VirtualServer),
|
||||||
|
Destinations: make(map[serviceKey][]*utilipvs.RealServer),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toServiceKey(serv *utilipvs.VirtualServer) serviceKey {
|
||||||
|
return serviceKey{
|
||||||
|
IP: serv.Address.To4().String(),
|
||||||
|
Port: serv.Port,
|
||||||
|
Protocol: serv.Protocol,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//EnsureVirtualServerAddressBind is a fake implementation
|
||||||
|
func (*FakeIPVS) EnsureVirtualServerAddressBind(serv *utilipvs.VirtualServer, dev string) (exist bool, err error) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//UnbindVirtualServerAddress is a fake implementation
|
||||||
|
func (*FakeIPVS) UnbindVirtualServerAddress(serv *utilipvs.VirtualServer, dev string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//AddVirtualServer is a fake implementation
|
||||||
|
func (f *FakeIPVS) AddVirtualServer(serv *utilipvs.VirtualServer) error {
|
||||||
|
if serv == nil {
|
||||||
|
return fmt.Errorf("Failed to add service: service can't be nil")
|
||||||
|
}
|
||||||
|
key := toServiceKey(serv)
|
||||||
|
f.Services[key] = serv
|
||||||
|
// make sure no destination present when creating new service
|
||||||
|
f.Destinations = make(map[serviceKey][]*utilipvs.RealServer)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//UpdateVirtualServer is a fake implementation
|
||||||
|
func (f *FakeIPVS) UpdateVirtualServer(serv *utilipvs.VirtualServer) error {
|
||||||
|
if serv == nil {
|
||||||
|
return fmt.Errorf("Failed to update service, service can't be nil")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//DeleteVirtualServer is a fake implementation
|
||||||
|
func (f *FakeIPVS) DeleteVirtualServer(serv *utilipvs.VirtualServer) error {
|
||||||
|
if serv == nil {
|
||||||
|
return fmt.Errorf("Failed to delete service: service can't be nil")
|
||||||
|
}
|
||||||
|
key := toServiceKey(serv)
|
||||||
|
delete(f.Services, key)
|
||||||
|
// clear specific destinations as well
|
||||||
|
f.Destinations[key] = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetVirtualServer is a fake implementation
|
||||||
|
func (f *FakeIPVS) GetVirtualServer(serv *utilipvs.VirtualServer) (*utilipvs.VirtualServer, error) {
|
||||||
|
if serv == nil {
|
||||||
|
return nil, fmt.Errorf("Failed to get service: service can't be nil")
|
||||||
|
}
|
||||||
|
key := toServiceKey(serv)
|
||||||
|
svc, found := f.Services[key]
|
||||||
|
if found {
|
||||||
|
return svc, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("Not found serv: %v", key.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetVirtualServers is a fake implementation
|
||||||
|
func (f *FakeIPVS) GetVirtualServers() ([]*utilipvs.VirtualServer, error) {
|
||||||
|
res := make([]*utilipvs.VirtualServer, 0)
|
||||||
|
for _, svc := range f.Services {
|
||||||
|
res = append(res, svc)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Flush is a fake implementation
|
||||||
|
func (f *FakeIPVS) Flush() error {
|
||||||
|
// directly drop old data
|
||||||
|
f.Services = nil
|
||||||
|
f.Destinations = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//AddRealServer is a fake implementation
|
||||||
|
func (f *FakeIPVS) AddRealServer(serv *utilipvs.VirtualServer, dest *utilipvs.RealServer) error {
|
||||||
|
if serv == nil || dest == nil {
|
||||||
|
return fmt.Errorf("Failed to add destination for service, neither service nor destination shouldn't be nil")
|
||||||
|
}
|
||||||
|
key := toServiceKey(serv)
|
||||||
|
if _, ok := f.Services[key]; !ok {
|
||||||
|
return fmt.Errorf("Failed to add destination for service %v, service not found", key.String())
|
||||||
|
}
|
||||||
|
dests := f.Destinations[key]
|
||||||
|
if dests == nil {
|
||||||
|
dests = make([]*utilipvs.RealServer, 0)
|
||||||
|
f.Destinations[key] = dests
|
||||||
|
}
|
||||||
|
f.Destinations[key] = append(f.Destinations[key], dest)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetRealServers is a fake implementation
|
||||||
|
func (f *FakeIPVS) GetRealServers(serv *utilipvs.VirtualServer) ([]*utilipvs.RealServer, error) {
|
||||||
|
if serv == nil {
|
||||||
|
return nil, fmt.Errorf("Failed to get destination for nil service")
|
||||||
|
}
|
||||||
|
key := toServiceKey(serv)
|
||||||
|
if _, ok := f.Services[key]; !ok {
|
||||||
|
return nil, fmt.Errorf("Failed to get destinations for service %v, service not found", key.String())
|
||||||
|
}
|
||||||
|
return f.Destinations[key], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//DeleteRealServer is a fake implementation
|
||||||
|
func (*FakeIPVS) DeleteRealServer(serv *utilipvs.VirtualServer, dest *utilipvs.RealServer) error {
|
||||||
|
if serv == nil || dest == nil {
|
||||||
|
return fmt.Errorf("Failed to delete destination, neither service nor destination can't be nil")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = utilipvs.Interface(&FakeIPVS{})
|
|
@ -140,6 +140,7 @@ filegroup(
|
||||||
"//vendor/github.com/docker/go-connections/sockets:all-srcs",
|
"//vendor/github.com/docker/go-connections/sockets:all-srcs",
|
||||||
"//vendor/github.com/docker/go-connections/tlsconfig:all-srcs",
|
"//vendor/github.com/docker/go-connections/tlsconfig:all-srcs",
|
||||||
"//vendor/github.com/docker/go-units:all-srcs",
|
"//vendor/github.com/docker/go-units:all-srcs",
|
||||||
|
"//vendor/github.com/docker/libnetwork/ipvs:all-srcs",
|
||||||
"//vendor/github.com/docker/spdystream:all-srcs",
|
"//vendor/github.com/docker/spdystream:all-srcs",
|
||||||
"//vendor/github.com/elazarl/go-bindata-assetfs:all-srcs",
|
"//vendor/github.com/elazarl/go-bindata-assetfs:all-srcs",
|
||||||
"//vendor/github.com/elazarl/goproxy:all-srcs",
|
"//vendor/github.com/elazarl/goproxy:all-srcs",
|
||||||
|
@ -306,6 +307,7 @@ filegroup(
|
||||||
"//vendor/github.com/syndtr/gocapability/capability:all-srcs",
|
"//vendor/github.com/syndtr/gocapability/capability:all-srcs",
|
||||||
"//vendor/github.com/ugorji/go/codec:all-srcs",
|
"//vendor/github.com/ugorji/go/codec:all-srcs",
|
||||||
"//vendor/github.com/vishvananda/netlink:all-srcs",
|
"//vendor/github.com/vishvananda/netlink:all-srcs",
|
||||||
|
"//vendor/github.com/vishvananda/netns:all-srcs",
|
||||||
"//vendor/github.com/vmware/govmomi:all-srcs",
|
"//vendor/github.com/vmware/govmomi:all-srcs",
|
||||||
"//vendor/github.com/vmware/photon-controller-go-sdk/SSPI:all-srcs",
|
"//vendor/github.com/vmware/photon-controller-go-sdk/SSPI:all-srcs",
|
||||||
"//vendor/github.com/vmware/photon-controller-go-sdk/photon:all-srcs",
|
"//vendor/github.com/vmware/photon-controller-go-sdk/photon:all-srcs",
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"addr.go",
|
||||||
|
"class.go",
|
||||||
|
"conntrack_unspecified.go",
|
||||||
|
"filter.go",
|
||||||
|
"genetlink_unspecified.go",
|
||||||
|
"handle_unspecified.go",
|
||||||
|
"link.go",
|
||||||
|
"neigh.go",
|
||||||
|
"netlink.go",
|
||||||
|
"netlink_unspecified.go",
|
||||||
|
"order.go",
|
||||||
|
"protinfo.go",
|
||||||
|
"qdisc.go",
|
||||||
|
"route.go",
|
||||||
|
"route_unspecified.go",
|
||||||
|
"rule.go",
|
||||||
|
"socket.go",
|
||||||
|
"xfrm.go",
|
||||||
|
"xfrm_policy.go",
|
||||||
|
"xfrm_state.go",
|
||||||
|
] + select({
|
||||||
|
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||||
|
"addr_linux.go",
|
||||||
|
"bpf_linux.go",
|
||||||
|
"bridge_linux.go",
|
||||||
|
"class_linux.go",
|
||||||
|
"conntrack_linux.go",
|
||||||
|
"filter_linux.go",
|
||||||
|
"genetlink_linux.go",
|
||||||
|
"gtp_linux.go",
|
||||||
|
"handle_linux.go",
|
||||||
|
"link_linux.go",
|
||||||
|
"link_tuntap_linux.go",
|
||||||
|
"neigh_linux.go",
|
||||||
|
"netlink_linux.go",
|
||||||
|
"protinfo_linux.go",
|
||||||
|
"qdisc_linux.go",
|
||||||
|
"route_linux.go",
|
||||||
|
"rule_linux.go",
|
||||||
|
"socket_linux.go",
|
||||||
|
"xfrm_monitor_linux.go",
|
||||||
|
"xfrm_policy_linux.go",
|
||||||
|
"xfrm_state_linux.go",
|
||||||
|
],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
cgo = True,
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"//vendor/github.com/vishvananda/netlink/nl:go_default_library",
|
||||||
|
"//vendor/github.com/vishvananda/netns:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [
|
||||||
|
":package-srcs",
|
||||||
|
"//vendor/github.com/vishvananda/netlink/nl:all-srcs",
|
||||||
|
],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
|
@ -0,0 +1,47 @@
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"nl_unspecified.go",
|
||||||
|
"syscall.go",
|
||||||
|
] + select({
|
||||||
|
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||||
|
"addr_linux.go",
|
||||||
|
"bridge_linux.go",
|
||||||
|
"conntrack_linux.go",
|
||||||
|
"genetlink_linux.go",
|
||||||
|
"link_linux.go",
|
||||||
|
"mpls_linux.go",
|
||||||
|
"nl_linux.go",
|
||||||
|
"route_linux.go",
|
||||||
|
"tc_linux.go",
|
||||||
|
"xfrm_linux.go",
|
||||||
|
"xfrm_monitor_linux.go",
|
||||||
|
"xfrm_policy_linux.go",
|
||||||
|
"xfrm_state_linux.go",
|
||||||
|
],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = select({
|
||||||
|
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||||
|
"//vendor/github.com/vishvananda/netns:go_default_library",
|
||||||
|
],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
|
@ -11,8 +11,13 @@ go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
"netns.go",
|
"netns.go",
|
||||||
"netns_linux.go",
|
"netns_unspecified.go",
|
||||||
],
|
] + select({
|
||||||
|
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||||
|
"netns_linux.go",
|
||||||
|
],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue