mirror of https://github.com/k3s-io/k3s
Update winkernel proxy for overlay
parent
164f79e2d4
commit
b724bdb19a
|
@ -1,8 +1,10 @@
|
||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"hnsV1.go",
|
||||||
|
"hnsV2.go",
|
||||||
"metrics.go",
|
"metrics.go",
|
||||||
"proxier.go",
|
"proxier.go",
|
||||||
],
|
],
|
||||||
|
@ -15,6 +17,7 @@ go_library(
|
||||||
"//pkg/api/v1/service:go_default_library",
|
"//pkg/api/v1/service:go_default_library",
|
||||||
"//pkg/apis/core/v1/helper:go_default_library",
|
"//pkg/apis/core/v1/helper:go_default_library",
|
||||||
"//pkg/proxy:go_default_library",
|
"//pkg/proxy:go_default_library",
|
||||||
|
"//pkg/proxy/apis/config:go_default_library",
|
||||||
"//pkg/proxy/healthcheck:go_default_library",
|
"//pkg/proxy/healthcheck:go_default_library",
|
||||||
"//pkg/util/async:go_default_library",
|
"//pkg/util/async:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
|
@ -23,6 +26,7 @@ go_library(
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
||||||
"//vendor/github.com/Microsoft/hcsshim:go_default_library",
|
"//vendor/github.com/Microsoft/hcsshim:go_default_library",
|
||||||
|
"//vendor/github.com/Microsoft/hcsshim/hcn:go_default_library",
|
||||||
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
|
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
|
||||||
"//vendor/k8s.io/klog:go_default_library",
|
"//vendor/k8s.io/klog:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -43,3 +47,22 @@ filegroup(
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
go_test(
|
||||||
|
name = "go_default_test",
|
||||||
|
srcs = [
|
||||||
|
"hns_test.go",
|
||||||
|
"proxier_test.go",
|
||||||
|
],
|
||||||
|
embed = [":go_default_library"],
|
||||||
|
deps = select({
|
||||||
|
"@io_bazel_rules_go//go/platform:windows": [
|
||||||
|
"//pkg/proxy:go_default_library",
|
||||||
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
|
"//vendor/github.com/Microsoft/hcsshim/hcn:go_default_library",
|
||||||
|
],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,225 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2018 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 winkernel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/Microsoft/hcsshim"
|
||||||
|
"k8s.io/klog"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HostNetworkService interface {
|
||||||
|
getNetworkByName(name string) (*hnsNetworkInfo, error)
|
||||||
|
getEndpointByID(id string) (*endpointsInfo, error)
|
||||||
|
getEndpointByIpAddress(ip string, networkName string) (*endpointsInfo, error)
|
||||||
|
createEndpoint(ep *endpointsInfo, networkName string) (*endpointsInfo, error)
|
||||||
|
deleteEndpoint(hnsID string) error
|
||||||
|
getLoadBalancer(endpoints []endpointsInfo, isILB bool, isDSR bool, sourceVip string, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*loadBalancerInfo, error)
|
||||||
|
deleteLoadBalancer(hnsID string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// V1 HNS API
|
||||||
|
type hnsV1 struct{}
|
||||||
|
|
||||||
|
func (hns hnsV1) getNetworkByName(name string) (*hnsNetworkInfo, error) {
|
||||||
|
hnsnetwork, err := hcsshim.GetHNSNetworkByName(name)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &hnsNetworkInfo{
|
||||||
|
id: hnsnetwork.Id,
|
||||||
|
name: hnsnetwork.Name,
|
||||||
|
networkType: hnsnetwork.Type,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
func (hns hnsV1) getEndpointByID(id string) (*endpointsInfo, error) {
|
||||||
|
hnsendpoint, err := hcsshim.GetHNSEndpointByID(id)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &endpointsInfo{
|
||||||
|
ip: hnsendpoint.IPAddress.String(),
|
||||||
|
isLocal: !hnsendpoint.IsRemoteEndpoint, //TODO: Change isLocal to isRemote
|
||||||
|
macAddress: hnsendpoint.MacAddress,
|
||||||
|
hnsID: hnsendpoint.Id,
|
||||||
|
hns: hns,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
func (hns hnsV1) getEndpointByIpAddress(ip string, networkName string) (*endpointsInfo, error) {
|
||||||
|
hnsnetwork, err := hcsshim.GetHNSNetworkByName(networkName)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints, err := hcsshim.HNSListEndpointRequest()
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
equal := false
|
||||||
|
if endpoint.IPAddress != nil {
|
||||||
|
equal = endpoint.IPAddress.String() == ip
|
||||||
|
}
|
||||||
|
if equal && strings.EqualFold(endpoint.VirtualNetwork, hnsnetwork.Id) {
|
||||||
|
return &endpointsInfo{
|
||||||
|
ip: endpoint.IPAddress.String(),
|
||||||
|
isLocal: !endpoint.IsRemoteEndpoint,
|
||||||
|
macAddress: endpoint.MacAddress,
|
||||||
|
hnsID: endpoint.Id,
|
||||||
|
hns: hns,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("Endpoint %v not found on network %s", ip, networkName)
|
||||||
|
}
|
||||||
|
func (hns hnsV1) createEndpoint(ep *endpointsInfo, networkName string) (*endpointsInfo, error) {
|
||||||
|
hnsNetwork, err := hcsshim.GetHNSNetworkByName(networkName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not find network %s: %v", networkName, err)
|
||||||
|
}
|
||||||
|
hnsEndpoint := &hcsshim.HNSEndpoint{
|
||||||
|
MacAddress: ep.macAddress,
|
||||||
|
IPAddress: net.ParseIP(ep.ip),
|
||||||
|
}
|
||||||
|
|
||||||
|
var createdEndpoint *hcsshim.HNSEndpoint
|
||||||
|
if !ep.isLocal {
|
||||||
|
if len(ep.providerAddress) != 0 {
|
||||||
|
paPolicy := hcsshim.PaPolicy{
|
||||||
|
Type: hcsshim.PA,
|
||||||
|
PA: ep.providerAddress,
|
||||||
|
}
|
||||||
|
paPolicyJson, err := json.Marshal(paPolicy)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("PA Policy creation failed: %v", err)
|
||||||
|
}
|
||||||
|
hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicyJson)
|
||||||
|
}
|
||||||
|
createdEndpoint, err = hnsNetwork.CreateRemoteEndpoint(hnsEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Remote endpoint creation failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
createdEndpoint, err = hnsNetwork.CreateEndpoint(hnsEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Local endpoint creation failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &endpointsInfo{
|
||||||
|
ip: createdEndpoint.IPAddress.String(),
|
||||||
|
isLocal: createdEndpoint.IsRemoteEndpoint,
|
||||||
|
macAddress: createdEndpoint.MacAddress,
|
||||||
|
hnsID: createdEndpoint.Id,
|
||||||
|
providerAddress: ep.providerAddress, //TODO get from createdEndpoint
|
||||||
|
hns: hns,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
func (hns hnsV1) deleteEndpoint(hnsID string) error {
|
||||||
|
hnsendpoint, err := hcsshim.GetHNSEndpointByID(hnsID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = hnsendpoint.Delete()
|
||||||
|
if err == nil {
|
||||||
|
klog.V(3).Infof("Remote endpoint resource deleted id %s", hnsID)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hns hnsV1) getLoadBalancer(endpoints []endpointsInfo, isILB bool, isDSR bool, sourceVip string, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*loadBalancerInfo, error) {
|
||||||
|
plists, err := hcsshim.HNSListPolicyListRequest()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if isDSR {
|
||||||
|
klog.V(3).Info("DSR is not supported in V1. Using non DSR instead")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, plist := range plists {
|
||||||
|
if len(plist.EndpointReferences) != len(endpoints) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Validate if input meets any of the policy lists
|
||||||
|
elbPolicy := hcsshim.ELBPolicy{}
|
||||||
|
if err = json.Unmarshal(plist.Policies[0], &elbPolicy); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if elbPolicy.Protocol == protocol && elbPolicy.InternalPort == internalPort && elbPolicy.ExternalPort == externalPort && elbPolicy.ILB == isILB {
|
||||||
|
if len(vip) > 0 {
|
||||||
|
if len(elbPolicy.VIPs) == 0 || elbPolicy.VIPs[0] != vip {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LogJson(plist, "Found existing Hns loadbalancer policy resource", 1)
|
||||||
|
return &loadBalancerInfo{
|
||||||
|
hnsID: plist.ID,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hnsEndpoints []hcsshim.HNSEndpoint
|
||||||
|
for _, ep := range endpoints {
|
||||||
|
endpoint, err := hcsshim.GetHNSEndpointByID(ep.hnsID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hnsEndpoints = append(hnsEndpoints, *endpoint)
|
||||||
|
}
|
||||||
|
lb, err := hcsshim.AddLoadBalancer(
|
||||||
|
hnsEndpoints,
|
||||||
|
isILB,
|
||||||
|
sourceVip,
|
||||||
|
vip,
|
||||||
|
protocol,
|
||||||
|
internalPort,
|
||||||
|
externalPort,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
LogJson(lb, "Hns loadbalancer policy resource", 1)
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &loadBalancerInfo{
|
||||||
|
hnsID: lb.ID,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
func (hns hnsV1) deleteLoadBalancer(hnsID string) error {
|
||||||
|
if len(hnsID) == 0 {
|
||||||
|
// Return silently
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup HNS policies
|
||||||
|
hnsloadBalancer, err := hcsshim.GetPolicyListByID(hnsID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
LogJson(hnsloadBalancer, "Removing Policy", 2)
|
||||||
|
|
||||||
|
_, err = hnsloadBalancer.Delete()
|
||||||
|
return err
|
||||||
|
}
|
|
@ -0,0 +1,239 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2018 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 winkernel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Microsoft/hcsshim/hcn"
|
||||||
|
"k8s.io/klog"
|
||||||
|
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type hnsV2 struct{}
|
||||||
|
|
||||||
|
func (hns hnsV2) getNetworkByName(name string) (*hnsNetworkInfo, error) {
|
||||||
|
hnsnetwork, err := hcn.GetNetworkByName(name)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var remoteSubnets []*remoteSubnetInfo
|
||||||
|
for _, policy := range hnsnetwork.Policies {
|
||||||
|
if policy.Type == hcn.RemoteSubnetRoute {
|
||||||
|
policySettings := hcn.RemoteSubnetRoutePolicySetting{}
|
||||||
|
err = json.Unmarshal(policy.Settings, &policySettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to unmarshal Remote Subnet policy settings")
|
||||||
|
}
|
||||||
|
rs := &remoteSubnetInfo{
|
||||||
|
destinationPrefix: policySettings.DestinationPrefix,
|
||||||
|
isolationId: policySettings.IsolationId,
|
||||||
|
providerAddress: policySettings.ProviderAddress,
|
||||||
|
drMacAddress: policySettings.DistributedRouterMacAddress,
|
||||||
|
}
|
||||||
|
remoteSubnets = append(remoteSubnets, rs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &hnsNetworkInfo{
|
||||||
|
id: hnsnetwork.Id,
|
||||||
|
name: hnsnetwork.Name,
|
||||||
|
networkType: string(hnsnetwork.Type),
|
||||||
|
remoteSubnets: remoteSubnets,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
func (hns hnsV2) getEndpointByID(id string) (*endpointsInfo, error) {
|
||||||
|
hnsendpoint, err := hcn.GetEndpointByID(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &endpointsInfo{ //TODO: fill out PA
|
||||||
|
ip: hnsendpoint.IpConfigurations[0].IpAddress,
|
||||||
|
isLocal: uint32(hnsendpoint.Flags&hcn.EndpointFlagsRemoteEndpoint) == 0, //TODO: Change isLocal to isRemote
|
||||||
|
macAddress: hnsendpoint.MacAddress,
|
||||||
|
hnsID: hnsendpoint.Id,
|
||||||
|
hns: hns,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
func (hns hnsV2) getEndpointByIpAddress(ip string, networkName string) (*endpointsInfo, error) {
|
||||||
|
hnsnetwork, err := hcn.GetNetworkByName(networkName)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("%v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints, err := hcn.ListEndpoints()
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
equal := false
|
||||||
|
if endpoint.IpConfigurations != nil && len(endpoint.IpConfigurations) > 0 {
|
||||||
|
equal = endpoint.IpConfigurations[0].IpAddress == ip
|
||||||
|
}
|
||||||
|
if equal && strings.EqualFold(endpoint.HostComputeNetwork, hnsnetwork.Id) {
|
||||||
|
return &endpointsInfo{
|
||||||
|
ip: endpoint.IpConfigurations[0].IpAddress,
|
||||||
|
isLocal: uint32(endpoint.Flags&hcn.EndpointFlagsRemoteEndpoint) == 0, //TODO: Change isLocal to isRemote
|
||||||
|
macAddress: endpoint.MacAddress,
|
||||||
|
hnsID: endpoint.Id,
|
||||||
|
hns: hns,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("Endpoint %v not found on network %s", ip, networkName)
|
||||||
|
}
|
||||||
|
func (hns hnsV2) createEndpoint(ep *endpointsInfo, networkName string) (*endpointsInfo, error) {
|
||||||
|
hnsNetwork, err := hcn.GetNetworkByName(networkName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not find network %s: %v", networkName, err)
|
||||||
|
}
|
||||||
|
var flags hcn.EndpointFlags
|
||||||
|
if !ep.isLocal {
|
||||||
|
flags |= hcn.EndpointFlagsRemoteEndpoint
|
||||||
|
}
|
||||||
|
ipConfig := &hcn.IpConfig{
|
||||||
|
IpAddress: ep.ip,
|
||||||
|
}
|
||||||
|
hnsEndpoint := &hcn.HostComputeEndpoint{
|
||||||
|
IpConfigurations: []hcn.IpConfig{*ipConfig},
|
||||||
|
MacAddress: ep.macAddress,
|
||||||
|
Flags: flags,
|
||||||
|
SchemaVersion: hcn.SchemaVersion{
|
||||||
|
Major: 2,
|
||||||
|
Minor: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var createdEndpoint *hcn.HostComputeEndpoint
|
||||||
|
if !ep.isLocal {
|
||||||
|
if len(ep.providerAddress) != 0 {
|
||||||
|
policySettings := hcn.ProviderAddressEndpointPolicySetting{
|
||||||
|
ProviderAddress: ep.providerAddress,
|
||||||
|
}
|
||||||
|
policySettingsJson, err := json.Marshal(policySettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("PA Policy creation failed: %v", err)
|
||||||
|
}
|
||||||
|
paPolicy := hcn.EndpointPolicy{
|
||||||
|
Type: hcn.NetworkProviderAddress,
|
||||||
|
Settings: policySettingsJson,
|
||||||
|
}
|
||||||
|
hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy)
|
||||||
|
}
|
||||||
|
createdEndpoint, err = hnsNetwork.CreateRemoteEndpoint(hnsEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Remote endpoint creation failed: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
createdEndpoint, err = hnsNetwork.CreateEndpoint(hnsEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Local endpoint creation failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &endpointsInfo{
|
||||||
|
ip: createdEndpoint.IpConfigurations[0].IpAddress,
|
||||||
|
isLocal: uint32(createdEndpoint.Flags&hcn.EndpointFlagsRemoteEndpoint) == 0,
|
||||||
|
macAddress: createdEndpoint.MacAddress,
|
||||||
|
hnsID: createdEndpoint.Id,
|
||||||
|
providerAddress: ep.providerAddress, //TODO get from createdEndpoint
|
||||||
|
hns: hns,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
func (hns hnsV2) deleteEndpoint(hnsID string) error {
|
||||||
|
hnsendpoint, err := hcn.GetEndpointByID(hnsID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = hnsendpoint.Delete()
|
||||||
|
if err == nil {
|
||||||
|
klog.V(3).Infof("Remote endpoint resource deleted id %s", hnsID)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
func (hns hnsV2) getLoadBalancer(endpoints []endpointsInfo, isILB bool, isDSR bool, sourceVip string, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*loadBalancerInfo, error) {
|
||||||
|
plists, err := hcn.ListLoadBalancers()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, plist := range plists {
|
||||||
|
if len(plist.HostComputeEndpoints) != len(endpoints) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Validate if input meets any of the policy lists
|
||||||
|
lbPortMapping := plist.PortMappings[0]
|
||||||
|
if lbPortMapping.Protocol == uint32(protocol) && lbPortMapping.InternalPort == internalPort && lbPortMapping.ExternalPort == externalPort && (lbPortMapping.Flags&1 != 0) == isILB {
|
||||||
|
if len(vip) > 0 {
|
||||||
|
if len(plist.FrontendVIPs) == 0 || plist.FrontendVIPs[0] != vip {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LogJson(plist, "Found existing Hns loadbalancer policy resource", 1)
|
||||||
|
return &loadBalancerInfo{
|
||||||
|
hnsID: plist.Id,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hnsEndpoints []hcn.HostComputeEndpoint
|
||||||
|
for _, ep := range endpoints {
|
||||||
|
endpoint, err := hcn.GetEndpointByID(ep.hnsID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hnsEndpoints = append(hnsEndpoints, *endpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
vips := []string{}
|
||||||
|
if len(vip) > 0 {
|
||||||
|
vips = append(vips, vip)
|
||||||
|
}
|
||||||
|
lb, err := hcn.AddLoadBalancer(
|
||||||
|
hnsEndpoints,
|
||||||
|
isILB,
|
||||||
|
isDSR,
|
||||||
|
sourceVip,
|
||||||
|
vips,
|
||||||
|
protocol,
|
||||||
|
internalPort,
|
||||||
|
externalPort,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
LogJson(lb, "Hns loadbalancer policy resource", 1)
|
||||||
|
|
||||||
|
return &loadBalancerInfo{
|
||||||
|
hnsID: lb.Id,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
func (hns hnsV2) deleteLoadBalancer(hnsID string) error {
|
||||||
|
lb, err := hcn.GetLoadBalancerByID(hnsID)
|
||||||
|
if err != nil {
|
||||||
|
// Return silently
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = lb.Delete()
|
||||||
|
return err
|
||||||
|
}
|
|
@ -0,0 +1,557 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2018 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 winkernel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/Microsoft/hcsshim/hcn"
|
||||||
|
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const sourceVip = "192.168.1.2"
|
||||||
|
const serviceVip = "11.0.0.1"
|
||||||
|
const addressPrefix = "192.168.1.0/24"
|
||||||
|
const gatewayAddress = "192.168.1.1"
|
||||||
|
const epMacAddress = "00-11-22-33-44-55"
|
||||||
|
const epIpAddress = "192.168.1.3"
|
||||||
|
const epIpAddressRemote = "192.168.2.3"
|
||||||
|
const epPaAddress = "10.0.0.3"
|
||||||
|
const protocol = 6
|
||||||
|
const internalPort = 80
|
||||||
|
const externalPort = 32440
|
||||||
|
|
||||||
|
func TestGetNetworkByName(t *testing.T) {
|
||||||
|
hnsV1 := hnsV1{}
|
||||||
|
hnsV2 := hnsV2{}
|
||||||
|
|
||||||
|
testGetNetworkByName(t, hnsV1)
|
||||||
|
testGetNetworkByName(t, hnsV2)
|
||||||
|
}
|
||||||
|
func TestGetEndpointByID(t *testing.T) {
|
||||||
|
hnsV1 := hnsV1{}
|
||||||
|
hnsV2 := hnsV2{}
|
||||||
|
|
||||||
|
testGetEndpointByID(t, hnsV1)
|
||||||
|
testGetEndpointByID(t, hnsV2)
|
||||||
|
}
|
||||||
|
func TestGetEndpointByIpAddress(t *testing.T) {
|
||||||
|
hnsV1 := hnsV1{}
|
||||||
|
hnsV2 := hnsV2{}
|
||||||
|
|
||||||
|
testGetEndpointByIpAddress(t, hnsV1)
|
||||||
|
testGetEndpointByIpAddress(t, hnsV2)
|
||||||
|
}
|
||||||
|
func TestCreateEndpointLocal(t *testing.T) {
|
||||||
|
hnsV1 := hnsV1{}
|
||||||
|
hnsV2 := hnsV2{}
|
||||||
|
|
||||||
|
testCreateEndpointLocal(t, hnsV1)
|
||||||
|
testCreateEndpointLocal(t, hnsV2)
|
||||||
|
}
|
||||||
|
func TestCreateEndpointRemotePA(t *testing.T) {
|
||||||
|
hnsV1 := hnsV1{}
|
||||||
|
hnsV2 := hnsV2{}
|
||||||
|
|
||||||
|
testCreateEndpointRemote(t, hnsV1, epPaAddress)
|
||||||
|
testCreateEndpointRemote(t, hnsV2, epPaAddress)
|
||||||
|
}
|
||||||
|
func TestCreateEndpointRemoteNoPA(t *testing.T) {
|
||||||
|
hnsV1 := hnsV1{}
|
||||||
|
hnsV2 := hnsV2{}
|
||||||
|
|
||||||
|
testCreateEndpointRemote(t, hnsV1, "")
|
||||||
|
testCreateEndpointRemote(t, hnsV2, "")
|
||||||
|
}
|
||||||
|
func TestDeleteEndpoint(t *testing.T) {
|
||||||
|
hnsV1 := hnsV1{}
|
||||||
|
hnsV2 := hnsV2{}
|
||||||
|
|
||||||
|
testDeleteEndpoint(t, hnsV1)
|
||||||
|
testDeleteEndpoint(t, hnsV2)
|
||||||
|
}
|
||||||
|
func TestGetLoadBalancerExisting(t *testing.T) {
|
||||||
|
hnsV1 := hnsV1{}
|
||||||
|
hnsV2 := hnsV2{}
|
||||||
|
|
||||||
|
testGetLoadBalancerExisting(t, hnsV1)
|
||||||
|
testGetLoadBalancerExisting(t, hnsV2)
|
||||||
|
}
|
||||||
|
func TestGetLoadBalancerNew(t *testing.T) {
|
||||||
|
hnsV1 := hnsV1{}
|
||||||
|
hnsV2 := hnsV2{}
|
||||||
|
|
||||||
|
testGetLoadBalancerNew(t, hnsV1)
|
||||||
|
testGetLoadBalancerNew(t, hnsV2)
|
||||||
|
}
|
||||||
|
func TestDeleteLoadBalancer(t *testing.T) {
|
||||||
|
hnsV1 := hnsV1{}
|
||||||
|
hnsV2 := hnsV2{}
|
||||||
|
|
||||||
|
testDeleteLoadBalancer(t, hnsV1)
|
||||||
|
testDeleteLoadBalancer(t, hnsV2)
|
||||||
|
}
|
||||||
|
func testGetNetworkByName(t *testing.T, hns HostNetworkService) {
|
||||||
|
Network, err := createTestNetwork()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
network, err := hns.getNetworkByName(Network.Name)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.EqualFold(network.id, Network.Id) {
|
||||||
|
t.Errorf("%v does not match %v", network.id, Network.Id)
|
||||||
|
}
|
||||||
|
err = Network.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func testGetEndpointByID(t *testing.T, hns HostNetworkService) {
|
||||||
|
Network, err := createTestNetwork()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ipConfig := &hcn.IpConfig{
|
||||||
|
IpAddress: epIpAddress,
|
||||||
|
}
|
||||||
|
Endpoint := &hcn.HostComputeEndpoint{
|
||||||
|
IpConfigurations: []hcn.IpConfig{*ipConfig},
|
||||||
|
MacAddress: epMacAddress,
|
||||||
|
SchemaVersion: hcn.SchemaVersion{
|
||||||
|
Major: 2,
|
||||||
|
Minor: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Endpoint, err = Network.CreateEndpoint(Endpoint)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint, err := hns.getEndpointByID(Endpoint.Id)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) {
|
||||||
|
t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Endpoint.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
err = Network.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func testGetEndpointByIpAddress(t *testing.T, hns HostNetworkService) {
|
||||||
|
Network, err := createTestNetwork()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ipConfig := &hcn.IpConfig{
|
||||||
|
IpAddress: epIpAddress,
|
||||||
|
}
|
||||||
|
Endpoint := &hcn.HostComputeEndpoint{
|
||||||
|
IpConfigurations: []hcn.IpConfig{*ipConfig},
|
||||||
|
MacAddress: epMacAddress,
|
||||||
|
SchemaVersion: hcn.SchemaVersion{
|
||||||
|
Major: 2,
|
||||||
|
Minor: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Endpoint, err = Network.CreateEndpoint(Endpoint)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint, err := hns.getEndpointByIpAddress(Endpoint.IpConfigurations[0].IpAddress, Network.Name)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) {
|
||||||
|
t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id)
|
||||||
|
}
|
||||||
|
if endpoint.ip != Endpoint.IpConfigurations[0].IpAddress {
|
||||||
|
t.Errorf("%v does not match %v", endpoint.ip, Endpoint.IpConfigurations[0].IpAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Endpoint.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
err = Network.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func testCreateEndpointLocal(t *testing.T, hns HostNetworkService) {
|
||||||
|
Network, err := createTestNetwork()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint := &endpointsInfo{
|
||||||
|
ip: epIpAddress,
|
||||||
|
macAddress: epMacAddress,
|
||||||
|
isLocal: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint, err = hns.createEndpoint(endpoint, Network.Name)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
Endpoint, err := hcn.GetEndpointByID(endpoint.hnsID)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) {
|
||||||
|
t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id)
|
||||||
|
}
|
||||||
|
if endpoint.ip != Endpoint.IpConfigurations[0].IpAddress {
|
||||||
|
t.Errorf("%v does not match %v", endpoint.ip, Endpoint.IpConfigurations[0].IpAddress)
|
||||||
|
}
|
||||||
|
if endpoint.macAddress != Endpoint.MacAddress {
|
||||||
|
t.Errorf("%v does not match %v", endpoint.macAddress, Endpoint.MacAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Endpoint.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
err = Network.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func testCreateEndpointRemote(t *testing.T, hns HostNetworkService, providerAddress string) {
|
||||||
|
Network, err := createTestNetwork()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint := &endpointsInfo{
|
||||||
|
ip: epIpAddressRemote,
|
||||||
|
macAddress: epMacAddress,
|
||||||
|
isLocal: false,
|
||||||
|
providerAddress: providerAddress,
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint, err = hns.createEndpoint(endpoint, Network.Name)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
Endpoint, err := hcn.GetEndpointByID(endpoint.hnsID)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !strings.EqualFold(endpoint.hnsID, Endpoint.Id) {
|
||||||
|
t.Errorf("%v does not match %v", endpoint.hnsID, Endpoint.Id)
|
||||||
|
}
|
||||||
|
if endpoint.ip != Endpoint.IpConfigurations[0].IpAddress {
|
||||||
|
t.Errorf("%v does not match %v", endpoint.ip, Endpoint.IpConfigurations[0].IpAddress)
|
||||||
|
}
|
||||||
|
if endpoint.macAddress != Endpoint.MacAddress {
|
||||||
|
t.Errorf("%v does not match %v", endpoint.macAddress, Endpoint.MacAddress)
|
||||||
|
}
|
||||||
|
if len(providerAddress) != 0 && endpoint.providerAddress != epPaAddress {
|
||||||
|
t.Errorf("%v does not match %v", endpoint.providerAddress, providerAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Endpoint.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
err = Network.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func testDeleteEndpoint(t *testing.T, hns HostNetworkService) {
|
||||||
|
Network, err := createTestNetwork()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ipConfig := &hcn.IpConfig{
|
||||||
|
IpAddress: epIpAddress,
|
||||||
|
}
|
||||||
|
Endpoint := &hcn.HostComputeEndpoint{
|
||||||
|
IpConfigurations: []hcn.IpConfig{*ipConfig},
|
||||||
|
MacAddress: epMacAddress,
|
||||||
|
SchemaVersion: hcn.SchemaVersion{
|
||||||
|
Major: 2,
|
||||||
|
Minor: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Endpoint, err = Network.CreateEndpoint(Endpoint)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
err = hns.deleteEndpoint(Endpoint.Id)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
// Endpoint should no longer exist so this should fail
|
||||||
|
Endpoint, err = hcn.GetEndpointByID(Endpoint.Id)
|
||||||
|
if err == nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Network.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testGetLoadBalancerExisting(t *testing.T, hns HostNetworkService) {
|
||||||
|
Network, err := createTestNetwork()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ipConfig := &hcn.IpConfig{
|
||||||
|
IpAddress: epIpAddress,
|
||||||
|
}
|
||||||
|
Endpoint := &hcn.HostComputeEndpoint{
|
||||||
|
IpConfigurations: []hcn.IpConfig{*ipConfig},
|
||||||
|
MacAddress: epMacAddress,
|
||||||
|
SchemaVersion: hcn.SchemaVersion{
|
||||||
|
Major: 2,
|
||||||
|
Minor: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Endpoint, err = Network.CreateEndpoint(Endpoint)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
Endpoints := []hcn.HostComputeEndpoint{*Endpoint}
|
||||||
|
LoadBalancer, err := hcn.AddLoadBalancer(
|
||||||
|
Endpoints,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
sourceVip,
|
||||||
|
[]string{serviceVip},
|
||||||
|
protocol,
|
||||||
|
internalPort,
|
||||||
|
externalPort,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint := &endpointsInfo{
|
||||||
|
ip: Endpoint.IpConfigurations[0].IpAddress,
|
||||||
|
hnsID: Endpoint.Id,
|
||||||
|
}
|
||||||
|
endpoints := []endpointsInfo{*endpoint}
|
||||||
|
lb, err := hns.getLoadBalancer(endpoints, false, false, sourceVip, serviceVip, protocol, internalPort, externalPort)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.EqualFold(lb.hnsID, LoadBalancer.Id) {
|
||||||
|
t.Errorf("%v does not match %v", lb.hnsID, LoadBalancer.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = LoadBalancer.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
err = Endpoint.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
err = Network.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func testGetLoadBalancerNew(t *testing.T, hns HostNetworkService) {
|
||||||
|
Network, err := createTestNetwork()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ipConfig := &hcn.IpConfig{
|
||||||
|
IpAddress: epIpAddress,
|
||||||
|
}
|
||||||
|
Endpoint := &hcn.HostComputeEndpoint{
|
||||||
|
IpConfigurations: []hcn.IpConfig{*ipConfig},
|
||||||
|
MacAddress: epMacAddress,
|
||||||
|
SchemaVersion: hcn.SchemaVersion{
|
||||||
|
Major: 2,
|
||||||
|
Minor: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Endpoint, err = Network.CreateEndpoint(Endpoint)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
endpoint := &endpointsInfo{
|
||||||
|
ip: Endpoint.IpConfigurations[0].IpAddress,
|
||||||
|
hnsID: Endpoint.Id,
|
||||||
|
}
|
||||||
|
endpoints := []endpointsInfo{*endpoint}
|
||||||
|
lb, err := hns.getLoadBalancer(endpoints, false, false, sourceVip, serviceVip, protocol, internalPort, externalPort)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
LoadBalancer, err := hcn.GetLoadBalancerByID(lb.hnsID)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !strings.EqualFold(lb.hnsID, LoadBalancer.Id) {
|
||||||
|
t.Errorf("%v does not match %v", lb.hnsID, LoadBalancer.Id)
|
||||||
|
}
|
||||||
|
err = LoadBalancer.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Endpoint.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
err = Network.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func testDeleteLoadBalancer(t *testing.T, hns HostNetworkService) {
|
||||||
|
Network, err := createTestNetwork()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ipConfig := &hcn.IpConfig{
|
||||||
|
IpAddress: epIpAddress,
|
||||||
|
}
|
||||||
|
Endpoint := &hcn.HostComputeEndpoint{
|
||||||
|
IpConfigurations: []hcn.IpConfig{*ipConfig},
|
||||||
|
MacAddress: epMacAddress,
|
||||||
|
SchemaVersion: hcn.SchemaVersion{
|
||||||
|
Major: 2,
|
||||||
|
Minor: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Endpoint, err = Network.CreateEndpoint(Endpoint)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
Endpoints := []hcn.HostComputeEndpoint{*Endpoint}
|
||||||
|
LoadBalancer, err := hcn.AddLoadBalancer(
|
||||||
|
Endpoints,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
sourceVip,
|
||||||
|
[]string{serviceVip},
|
||||||
|
protocol,
|
||||||
|
internalPort,
|
||||||
|
externalPort,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
err = hns.deleteLoadBalancer(LoadBalancer.Id)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
// Load balancer should not longer exist
|
||||||
|
LoadBalancer, err = hcn.GetLoadBalancerByID(LoadBalancer.Id)
|
||||||
|
if err == nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Endpoint.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
err = Network.Delete()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func createTestNetwork() (*hcn.HostComputeNetwork, error) {
|
||||||
|
network := &hcn.HostComputeNetwork{
|
||||||
|
Type: "Overlay",
|
||||||
|
Name: "TestOverlay",
|
||||||
|
MacPool: hcn.MacPool{
|
||||||
|
Ranges: []hcn.MacRange{
|
||||||
|
{
|
||||||
|
StartMacAddress: "00-15-5D-52-C0-00",
|
||||||
|
EndMacAddress: "00-15-5D-52-CF-FF",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Ipams: []hcn.Ipam{
|
||||||
|
{
|
||||||
|
Type: "Static",
|
||||||
|
Subnets: []hcn.Subnet{
|
||||||
|
{
|
||||||
|
IpAddressPrefix: addressPrefix,
|
||||||
|
Routes: []hcn.Route{
|
||||||
|
{
|
||||||
|
NextHop: gatewayAddress,
|
||||||
|
DestinationPrefix: "0.0.0.0/0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SchemaVersion: hcn.SchemaVersion{
|
||||||
|
Major: 2,
|
||||||
|
Minor: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
vsid := &hcn.VsidPolicySetting{
|
||||||
|
IsolationId: 5000,
|
||||||
|
}
|
||||||
|
vsidJson, err := json.Marshal(vsid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sp := &hcn.SubnetPolicy{
|
||||||
|
Type: hcn.VSID,
|
||||||
|
}
|
||||||
|
sp.Settings = vsidJson
|
||||||
|
|
||||||
|
spJson, err := json.Marshal(sp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
network.Ipams[0].Subnets[0].Policies = append(network.Ipams[0].Subnets[0].Policies, spJson)
|
||||||
|
|
||||||
|
return network.Create()
|
||||||
|
}
|
|
@ -29,6 +29,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Microsoft/hcsshim"
|
"github.com/Microsoft/hcsshim"
|
||||||
|
"github.com/Microsoft/hcsshim/hcn"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
|
||||||
|
@ -40,6 +42,7 @@ import (
|
||||||
apiservice "k8s.io/kubernetes/pkg/api/v1/service"
|
apiservice "k8s.io/kubernetes/pkg/api/v1/service"
|
||||||
"k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
"k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
"k8s.io/kubernetes/pkg/proxy"
|
"k8s.io/kubernetes/pkg/proxy"
|
||||||
|
"k8s.io/kubernetes/pkg/proxy/apis/config"
|
||||||
"k8s.io/kubernetes/pkg/proxy/healthcheck"
|
"k8s.io/kubernetes/pkg/proxy/healthcheck"
|
||||||
"k8s.io/kubernetes/pkg/util/async"
|
"k8s.io/kubernetes/pkg/util/async"
|
||||||
)
|
)
|
||||||
|
@ -82,6 +85,10 @@ type loadBalancerIngressInfo struct {
|
||||||
hnsID string
|
hnsID string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type loadBalancerInfo struct {
|
||||||
|
hnsID string
|
||||||
|
}
|
||||||
|
|
||||||
// internal struct for string service information
|
// internal struct for string service information
|
||||||
type serviceInfo struct {
|
type serviceInfo struct {
|
||||||
clusterIP net.IP
|
clusterIP net.IP
|
||||||
|
@ -100,11 +107,22 @@ type serviceInfo struct {
|
||||||
hnsID string
|
hnsID string
|
||||||
nodePorthnsID string
|
nodePorthnsID string
|
||||||
policyApplied bool
|
policyApplied bool
|
||||||
|
remoteEndpoint *endpointsInfo
|
||||||
|
hns HostNetworkService
|
||||||
}
|
}
|
||||||
|
|
||||||
type hnsNetworkInfo struct {
|
type hnsNetworkInfo struct {
|
||||||
name string
|
name string
|
||||||
id string
|
id string
|
||||||
|
networkType string
|
||||||
|
remoteSubnets []*remoteSubnetInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type remoteSubnetInfo struct {
|
||||||
|
destinationPrefix string
|
||||||
|
isolationId uint16
|
||||||
|
providerAddress string
|
||||||
|
drMacAddress string
|
||||||
}
|
}
|
||||||
|
|
||||||
func Log(v interface{}, message string, level klog.Level) {
|
func Log(v interface{}, message string, level klog.Level) {
|
||||||
|
@ -120,12 +138,14 @@ func LogJson(v interface{}, message string, level klog.Level) {
|
||||||
|
|
||||||
// internal struct for endpoints information
|
// internal struct for endpoints information
|
||||||
type endpointsInfo struct {
|
type endpointsInfo struct {
|
||||||
ip string
|
ip string
|
||||||
port uint16
|
port uint16
|
||||||
isLocal bool
|
isLocal bool
|
||||||
macAddress string
|
macAddress string
|
||||||
hnsID string
|
hnsID string
|
||||||
refCount uint16
|
refCount uint16
|
||||||
|
providerAddress string
|
||||||
|
hns HostNetworkService
|
||||||
}
|
}
|
||||||
|
|
||||||
//Uses mac prefix and IPv4 address to return a mac address
|
//Uses mac prefix and IPv4 address to return a mac address
|
||||||
|
@ -139,7 +159,7 @@ func conjureMac(macPrefix string, ip net.IP) string {
|
||||||
return "02-11-22-33-44-55"
|
return "02-11-22-33-44-55"
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEndpointInfo(ip string, port uint16, isLocal bool) *endpointsInfo {
|
func newEndpointInfo(ip string, port uint16, isLocal bool, hns HostNetworkService) *endpointsInfo {
|
||||||
info := &endpointsInfo{
|
info := &endpointsInfo{
|
||||||
ip: ip,
|
ip: ip,
|
||||||
port: port,
|
port: port,
|
||||||
|
@ -147,6 +167,7 @@ func newEndpointInfo(ip string, port uint16, isLocal bool) *endpointsInfo {
|
||||||
macAddress: conjureMac("02-11", net.ParseIP(ip)),
|
macAddress: conjureMac("02-11", net.ParseIP(ip)),
|
||||||
refCount: 0,
|
refCount: 0,
|
||||||
hnsID: "",
|
hnsID: "",
|
||||||
|
hns: hns,
|
||||||
}
|
}
|
||||||
|
|
||||||
return info
|
return info
|
||||||
|
@ -160,14 +181,17 @@ func (ep *endpointsInfo) Cleanup() {
|
||||||
// Remove only remote endpoints created by this service
|
// Remove only remote endpoints created by this service
|
||||||
if ep.refCount <= 0 && !ep.isLocal {
|
if ep.refCount <= 0 && !ep.isLocal {
|
||||||
klog.V(4).Infof("Removing endpoints for %v, since no one is referencing it", ep)
|
klog.V(4).Infof("Removing endpoints for %v, since no one is referencing it", ep)
|
||||||
deleteHnsEndpoint(ep.hnsID)
|
err := ep.hns.deleteEndpoint(ep.hnsID)
|
||||||
ep.hnsID = ""
|
if err == nil {
|
||||||
|
ep.hnsID = ""
|
||||||
|
} else {
|
||||||
|
klog.Errorf("Endpoint deletion failed for %v: %v", ep.ip, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns a new serviceInfo struct
|
// returns a new serviceInfo struct
|
||||||
func newServiceInfo(svcPortName proxy.ServicePortName, port *v1.ServicePort, service *v1.Service) *serviceInfo {
|
func newServiceInfo(svcPortName proxy.ServicePortName, port *v1.ServicePort, service *v1.Service, hns HostNetworkService) *serviceInfo {
|
||||||
onlyNodeLocalEndpoints := false
|
onlyNodeLocalEndpoints := false
|
||||||
if apiservice.RequestsOnlyLocalTraffic(service) {
|
if apiservice.RequestsOnlyLocalTraffic(service) {
|
||||||
onlyNodeLocalEndpoints = true
|
onlyNodeLocalEndpoints = true
|
||||||
|
@ -175,8 +199,7 @@ func newServiceInfo(svcPortName proxy.ServicePortName, port *v1.ServicePort, ser
|
||||||
|
|
||||||
// set default session sticky max age 180min=10800s
|
// set default session sticky max age 180min=10800s
|
||||||
stickyMaxAgeSeconds := 10800
|
stickyMaxAgeSeconds := 10800
|
||||||
if service.Spec.SessionAffinity == v1.ServiceAffinityClientIP {
|
if service.Spec.SessionAffinity == v1.ServiceAffinityClientIP && service.Spec.SessionAffinityConfig != nil {
|
||||||
// Kube-apiserver side guarantees SessionAffinityConfig won't be nil when session affinity type is ClientIP
|
|
||||||
stickyMaxAgeSeconds = int(*service.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds)
|
stickyMaxAgeSeconds = int(*service.Spec.SessionAffinityConfig.ClientIP.TimeoutSeconds)
|
||||||
}
|
}
|
||||||
info := &serviceInfo{
|
info := &serviceInfo{
|
||||||
|
@ -193,6 +216,7 @@ func newServiceInfo(svcPortName proxy.ServicePortName, port *v1.ServicePort, ser
|
||||||
stickyMaxAgeSeconds: stickyMaxAgeSeconds,
|
stickyMaxAgeSeconds: stickyMaxAgeSeconds,
|
||||||
loadBalancerSourceRanges: make([]string, len(service.Spec.LoadBalancerSourceRanges)),
|
loadBalancerSourceRanges: make([]string, len(service.Spec.LoadBalancerSourceRanges)),
|
||||||
onlyNodeLocalEndpoints: onlyNodeLocalEndpoints,
|
onlyNodeLocalEndpoints: onlyNodeLocalEndpoints,
|
||||||
|
hns: hns,
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(info.loadBalancerSourceRanges, service.Spec.LoadBalancerSourceRanges)
|
copy(info.loadBalancerSourceRanges, service.Spec.LoadBalancerSourceRanges)
|
||||||
|
@ -256,17 +280,17 @@ func newEndpointsChangeMap(hostname string) endpointsChangeMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ecm *endpointsChangeMap) update(namespacedName *types.NamespacedName, previous, current *v1.Endpoints) bool {
|
func (ecm *endpointsChangeMap) update(namespacedName *types.NamespacedName, previous, current *v1.Endpoints, hns HostNetworkService) bool {
|
||||||
ecm.lock.Lock()
|
ecm.lock.Lock()
|
||||||
defer ecm.lock.Unlock()
|
defer ecm.lock.Unlock()
|
||||||
|
|
||||||
change, exists := ecm.items[*namespacedName]
|
change, exists := ecm.items[*namespacedName]
|
||||||
if !exists {
|
if !exists {
|
||||||
change = &endpointsChange{}
|
change = &endpointsChange{}
|
||||||
change.previous = endpointsToEndpointsMap(previous, ecm.hostname)
|
change.previous = endpointsToEndpointsMap(previous, ecm.hostname, hns)
|
||||||
ecm.items[*namespacedName] = change
|
ecm.items[*namespacedName] = change
|
||||||
}
|
}
|
||||||
change.current = endpointsToEndpointsMap(current, ecm.hostname)
|
change.current = endpointsToEndpointsMap(current, ecm.hostname, hns)
|
||||||
if reflect.DeepEqual(change.previous, change.current) {
|
if reflect.DeepEqual(change.previous, change.current) {
|
||||||
delete(ecm.items, *namespacedName)
|
delete(ecm.items, *namespacedName)
|
||||||
}
|
}
|
||||||
|
@ -279,7 +303,7 @@ func newServiceChangeMap() serviceChangeMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scm *serviceChangeMap) update(namespacedName *types.NamespacedName, previous, current *v1.Service) bool {
|
func (scm *serviceChangeMap) update(namespacedName *types.NamespacedName, previous, current *v1.Service, hns HostNetworkService) bool {
|
||||||
scm.lock.Lock()
|
scm.lock.Lock()
|
||||||
defer scm.lock.Unlock()
|
defer scm.lock.Unlock()
|
||||||
|
|
||||||
|
@ -287,10 +311,10 @@ func (scm *serviceChangeMap) update(namespacedName *types.NamespacedName, previo
|
||||||
if !exists {
|
if !exists {
|
||||||
// Service is Added
|
// Service is Added
|
||||||
change = &serviceChange{}
|
change = &serviceChange{}
|
||||||
change.previous = serviceToServiceMap(previous)
|
change.previous = serviceToServiceMap(previous, hns)
|
||||||
scm.items[*namespacedName] = change
|
scm.items[*namespacedName] = change
|
||||||
}
|
}
|
||||||
change.current = serviceToServiceMap(current)
|
change.current = serviceToServiceMap(current, hns)
|
||||||
if reflect.DeepEqual(change.previous, change.current) {
|
if reflect.DeepEqual(change.previous, change.current) {
|
||||||
delete(scm.items, *namespacedName)
|
delete(scm.items, *namespacedName)
|
||||||
}
|
}
|
||||||
|
@ -420,7 +444,11 @@ type Proxier struct {
|
||||||
// precomputing some number of those and cache for future reuse.
|
// precomputing some number of those and cache for future reuse.
|
||||||
precomputedProbabilities []string
|
precomputedProbabilities []string
|
||||||
|
|
||||||
network hnsNetworkInfo
|
hns HostNetworkService
|
||||||
|
network hnsNetworkInfo
|
||||||
|
sourceVip string
|
||||||
|
hostMac string
|
||||||
|
isDSR bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type localPort struct {
|
type localPort struct {
|
||||||
|
@ -465,6 +493,7 @@ func NewProxier(
|
||||||
nodeIP net.IP,
|
nodeIP net.IP,
|
||||||
recorder record.EventRecorder,
|
recorder record.EventRecorder,
|
||||||
healthzServer healthcheck.HealthzUpdater,
|
healthzServer healthcheck.HealthzUpdater,
|
||||||
|
config config.KubeProxyWinkernelConfiguration,
|
||||||
) (*Proxier, error) {
|
) (*Proxier, error) {
|
||||||
masqueradeValue := 1 << uint(masqueradeBit)
|
masqueradeValue := 1 << uint(masqueradeBit)
|
||||||
masqueradeMark := fmt.Sprintf("%#08x/%#08x", masqueradeValue, masqueradeValue)
|
masqueradeMark := fmt.Sprintf("%#08x/%#08x", masqueradeValue, masqueradeValue)
|
||||||
|
@ -479,19 +508,75 @@ func NewProxier(
|
||||||
}
|
}
|
||||||
|
|
||||||
healthChecker := healthcheck.NewServer(hostname, recorder, nil, nil) // use default implementations of deps
|
healthChecker := healthcheck.NewServer(hostname, recorder, nil, nil) // use default implementations of deps
|
||||||
|
var hns HostNetworkService
|
||||||
// TODO : Make this a param
|
hns = hnsV1{}
|
||||||
hnsNetworkName := os.Getenv("KUBE_NETWORK")
|
supportedFeatures := hcn.GetSupportedFeatures()
|
||||||
if len(hnsNetworkName) == 0 {
|
if supportedFeatures.Api.V2 {
|
||||||
return nil, fmt.Errorf("Environment variable KUBE_NETWORK not initialized")
|
hns = hnsV2{}
|
||||||
}
|
}
|
||||||
hnsNetwork, err := getHnsNetworkInfo(hnsNetworkName)
|
|
||||||
|
hnsNetworkName := config.NetworkName
|
||||||
|
if len(hnsNetworkName) == 0 {
|
||||||
|
klog.V(3).Infof("network-name flag not set. Checking environment variable")
|
||||||
|
hnsNetworkName = os.Getenv("KUBE_NETWORK")
|
||||||
|
if len(hnsNetworkName) == 0 {
|
||||||
|
return nil, fmt.Errorf("Environment variable KUBE_NETWORK and network-flag not initialized")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hnsNetworkInfo, err := hns.getNetworkByName(hnsNetworkName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Fatalf("Unable to find Hns Network specified by %s. Please check environment variable KUBE_NETWORK", hnsNetworkName)
|
klog.Errorf("Unable to find Hns Network specified by %s. Please check environment variable KUBE_NETWORK or network-name flag", hnsNetworkName)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
klog.V(1).Infof("Hns Network loaded with info = %v", hnsNetworkInfo)
|
||||||
|
isDSR := config.EnableDSR
|
||||||
|
err = hcn.DSRSupported()
|
||||||
|
if isDSR && err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.V(1).Infof("Hns Network loaded with info = %v", hnsNetwork)
|
var sourceVip string
|
||||||
|
var hostMac string
|
||||||
|
if hnsNetworkInfo.networkType == "Overlay" {
|
||||||
|
err = hcn.RemoteSubnetSupported()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sourceVip = config.SourceVip
|
||||||
|
if len(sourceVip) == 0 {
|
||||||
|
return nil, fmt.Errorf("source-vip flag not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
interfaces, _ := net.Interfaces() //TODO create interfaces
|
||||||
|
for _, inter := range interfaces {
|
||||||
|
addresses, _ := inter.Addrs()
|
||||||
|
for _, addr := range addresses {
|
||||||
|
addrIP, _, _ := net.ParseCIDR(addr.String())
|
||||||
|
if addrIP.String() == nodeIP.String() {
|
||||||
|
klog.V(2).Infof("Host MAC address is %s", inter.HardwareAddr.String())
|
||||||
|
hostMac = inter.HardwareAddr.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(hostMac) == 0 {
|
||||||
|
return nil, fmt.Errorf("Could not find host mac address for %s", nodeIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
existingSourceVip, _ := hns.getEndpointByIpAddress(sourceVip, hnsNetworkName)
|
||||||
|
if existingSourceVip == nil {
|
||||||
|
hnsEndpoint := &endpointsInfo{
|
||||||
|
ip: sourceVip,
|
||||||
|
isLocal: true,
|
||||||
|
macAddress: hostMac,
|
||||||
|
providerAddress: nodeIP.String(),
|
||||||
|
}
|
||||||
|
_, err = hns.createEndpoint(hnsEndpoint, hnsNetworkName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Source Vip endpoint creation failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
proxier := &Proxier{
|
proxier := &Proxier{
|
||||||
portsMap: make(map[localPort]closeable),
|
portsMap: make(map[localPort]closeable),
|
||||||
|
@ -507,7 +592,11 @@ func NewProxier(
|
||||||
recorder: recorder,
|
recorder: recorder,
|
||||||
healthChecker: healthChecker,
|
healthChecker: healthChecker,
|
||||||
healthzServer: healthzServer,
|
healthzServer: healthzServer,
|
||||||
network: *hnsNetwork,
|
hns: hns,
|
||||||
|
network: *hnsNetworkInfo,
|
||||||
|
sourceVip: sourceVip,
|
||||||
|
hostMac: hostMac,
|
||||||
|
isDSR: isDSR,
|
||||||
}
|
}
|
||||||
|
|
||||||
burstSyncs := 2
|
burstSyncs := 2
|
||||||
|
@ -536,27 +625,30 @@ func (svcInfo *serviceInfo) cleanupAllPolicies(endpoints []*endpointsInfo) {
|
||||||
for _, ep := range endpoints {
|
for _, ep := range endpoints {
|
||||||
ep.Cleanup()
|
ep.Cleanup()
|
||||||
}
|
}
|
||||||
|
if svcInfo.remoteEndpoint != nil {
|
||||||
|
svcInfo.remoteEndpoint.Cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
svcInfo.policyApplied = false
|
svcInfo.policyApplied = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (svcInfo *serviceInfo) deleteAllHnsLoadBalancerPolicy() {
|
func (svcInfo *serviceInfo) deleteAllHnsLoadBalancerPolicy() {
|
||||||
// Remove the Hns Policy corresponding to this service
|
// Remove the Hns Policy corresponding to this service
|
||||||
deleteHnsLoadBalancerPolicy(svcInfo.hnsID)
|
hns := svcInfo.hns
|
||||||
|
hns.deleteLoadBalancer(svcInfo.hnsID)
|
||||||
svcInfo.hnsID = ""
|
svcInfo.hnsID = ""
|
||||||
|
|
||||||
deleteHnsLoadBalancerPolicy(svcInfo.nodePorthnsID)
|
hns.deleteLoadBalancer(svcInfo.nodePorthnsID)
|
||||||
svcInfo.nodePorthnsID = ""
|
svcInfo.nodePorthnsID = ""
|
||||||
|
|
||||||
for _, externalIp := range svcInfo.externalIPs {
|
for _, externalIp := range svcInfo.externalIPs {
|
||||||
deleteHnsLoadBalancerPolicy(externalIp.hnsID)
|
hns.deleteLoadBalancer(externalIp.hnsID)
|
||||||
externalIp.hnsID = ""
|
externalIp.hnsID = ""
|
||||||
}
|
}
|
||||||
for _, lbIngressIp := range svcInfo.loadBalancerIngressIPs {
|
for _, lbIngressIp := range svcInfo.loadBalancerIngressIPs {
|
||||||
deleteHnsLoadBalancerPolicy(lbIngressIp.hnsID)
|
hns.deleteLoadBalancer(lbIngressIp.hnsID)
|
||||||
lbIngressIp.hnsID = ""
|
lbIngressIp.hnsID = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteAllHnsLoadBalancerPolicy() {
|
func deleteAllHnsLoadBalancerPolicy() {
|
||||||
|
@ -574,87 +666,6 @@ func deleteAllHnsLoadBalancerPolicy() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getHnsLoadBalancer returns the LoadBalancer policy resource, if already found.
|
|
||||||
// If not, it would create one and return
|
|
||||||
func getHnsLoadBalancer(endpoints []hcsshim.HNSEndpoint, isILB bool, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*hcsshim.PolicyList, error) {
|
|
||||||
plists, err := hcsshim.HNSListPolicyListRequest()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, plist := range plists {
|
|
||||||
if len(plist.EndpointReferences) != len(endpoints) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Validate if input meets any of the policy lists
|
|
||||||
elbPolicy := hcsshim.ELBPolicy{}
|
|
||||||
if err = json.Unmarshal(plist.Policies[0], &elbPolicy); err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if elbPolicy.Protocol == protocol && elbPolicy.InternalPort == internalPort && elbPolicy.ExternalPort == externalPort && elbPolicy.ILB == isILB {
|
|
||||||
if len(vip) > 0 {
|
|
||||||
if len(elbPolicy.VIPs) == 0 || elbPolicy.VIPs[0] != vip {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LogJson(plist, "Found existing Hns loadbalancer policy resource", 1)
|
|
||||||
return &plist, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//TODO: sourceVip is not used. If required, expose this as a param
|
|
||||||
var sourceVip string
|
|
||||||
lb, err := hcsshim.AddLoadBalancer(
|
|
||||||
endpoints,
|
|
||||||
isILB,
|
|
||||||
sourceVip,
|
|
||||||
vip,
|
|
||||||
protocol,
|
|
||||||
internalPort,
|
|
||||||
externalPort,
|
|
||||||
)
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
LogJson(lb, "Hns loadbalancer policy resource", 1)
|
|
||||||
}
|
|
||||||
return lb, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteHnsLoadBalancerPolicy(hnsID string) {
|
|
||||||
if len(hnsID) == 0 {
|
|
||||||
// Return silently
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup HNS policies
|
|
||||||
hnsloadBalancer, err := hcsshim.GetPolicyListByID(hnsID)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
LogJson(hnsloadBalancer, "Removing Policy", 2)
|
|
||||||
|
|
||||||
_, err = hnsloadBalancer.Delete()
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteHnsEndpoint(hnsID string) {
|
|
||||||
hnsendpoint, err := hcsshim.GetHNSEndpointByID(hnsID)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = hnsendpoint.Delete()
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
klog.V(3).Infof("Remote endpoint resource deleted id %s", hnsID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getHnsNetworkInfo(hnsNetworkName string) (*hnsNetworkInfo, error) {
|
func getHnsNetworkInfo(hnsNetworkName string) (*hnsNetworkInfo, error) {
|
||||||
hnsnetwork, err := hcsshim.GetHNSNetworkByName(hnsNetworkName)
|
hnsnetwork, err := hcsshim.GetHNSNetworkByName(hnsNetworkName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -663,29 +674,12 @@ func getHnsNetworkInfo(hnsNetworkName string) (*hnsNetworkInfo, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &hnsNetworkInfo{
|
return &hnsNetworkInfo{
|
||||||
id: hnsnetwork.Id,
|
id: hnsnetwork.Id,
|
||||||
name: hnsnetwork.Name,
|
name: hnsnetwork.Name,
|
||||||
|
networkType: hnsnetwork.Type,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHnsEndpointByIpAddress(ip net.IP, networkName string) (*hcsshim.HNSEndpoint, error) {
|
|
||||||
hnsnetwork, err := hcsshim.GetHNSNetworkByName(networkName)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoints, err := hcsshim.HNSListEndpointRequest()
|
|
||||||
for _, endpoint := range endpoints {
|
|
||||||
equal := reflect.DeepEqual(endpoint.IPAddress, ip)
|
|
||||||
if equal && endpoint.VirtualNetwork == hnsnetwork.Id {
|
|
||||||
return &endpoint, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("Endpoint %v not found on network %s", ip, networkName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync is called to synchronize the proxier state to hns as soon as possible.
|
// Sync is called to synchronize the proxier state to hns as soon as possible.
|
||||||
func (proxier *Proxier) Sync() {
|
func (proxier *Proxier) Sync() {
|
||||||
proxier.syncRunner.Run()
|
proxier.syncRunner.Run()
|
||||||
|
@ -714,21 +708,21 @@ func (proxier *Proxier) isInitialized() bool {
|
||||||
|
|
||||||
func (proxier *Proxier) OnServiceAdd(service *v1.Service) {
|
func (proxier *Proxier) OnServiceAdd(service *v1.Service) {
|
||||||
namespacedName := types.NamespacedName{Namespace: service.Namespace, Name: service.Name}
|
namespacedName := types.NamespacedName{Namespace: service.Namespace, Name: service.Name}
|
||||||
if proxier.serviceChanges.update(&namespacedName, nil, service) && proxier.isInitialized() {
|
if proxier.serviceChanges.update(&namespacedName, nil, service, proxier.hns) && proxier.isInitialized() {
|
||||||
proxier.syncRunner.Run()
|
proxier.syncRunner.Run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxier *Proxier) OnServiceUpdate(oldService, service *v1.Service) {
|
func (proxier *Proxier) OnServiceUpdate(oldService, service *v1.Service) {
|
||||||
namespacedName := types.NamespacedName{Namespace: service.Namespace, Name: service.Name}
|
namespacedName := types.NamespacedName{Namespace: service.Namespace, Name: service.Name}
|
||||||
if proxier.serviceChanges.update(&namespacedName, oldService, service) && proxier.isInitialized() {
|
if proxier.serviceChanges.update(&namespacedName, oldService, service, proxier.hns) && proxier.isInitialized() {
|
||||||
proxier.syncRunner.Run()
|
proxier.syncRunner.Run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxier *Proxier) OnServiceDelete(service *v1.Service) {
|
func (proxier *Proxier) OnServiceDelete(service *v1.Service) {
|
||||||
namespacedName := types.NamespacedName{Namespace: service.Namespace, Name: service.Name}
|
namespacedName := types.NamespacedName{Namespace: service.Namespace, Name: service.Name}
|
||||||
if proxier.serviceChanges.update(&namespacedName, service, nil) && proxier.isInitialized() {
|
if proxier.serviceChanges.update(&namespacedName, service, nil, proxier.hns) && proxier.isInitialized() {
|
||||||
proxier.syncRunner.Run()
|
proxier.syncRunner.Run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -789,21 +783,21 @@ func (proxier *Proxier) updateServiceMap() (result updateServiceMapResult) {
|
||||||
|
|
||||||
func (proxier *Proxier) OnEndpointsAdd(endpoints *v1.Endpoints) {
|
func (proxier *Proxier) OnEndpointsAdd(endpoints *v1.Endpoints) {
|
||||||
namespacedName := types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}
|
namespacedName := types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}
|
||||||
if proxier.endpointsChanges.update(&namespacedName, nil, endpoints) && proxier.isInitialized() {
|
if proxier.endpointsChanges.update(&namespacedName, nil, endpoints, proxier.hns) && proxier.isInitialized() {
|
||||||
proxier.syncRunner.Run()
|
proxier.syncRunner.Run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxier *Proxier) OnEndpointsUpdate(oldEndpoints, endpoints *v1.Endpoints) {
|
func (proxier *Proxier) OnEndpointsUpdate(oldEndpoints, endpoints *v1.Endpoints) {
|
||||||
namespacedName := types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}
|
namespacedName := types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}
|
||||||
if proxier.endpointsChanges.update(&namespacedName, oldEndpoints, endpoints) && proxier.isInitialized() {
|
if proxier.endpointsChanges.update(&namespacedName, oldEndpoints, endpoints, proxier.hns) && proxier.isInitialized() {
|
||||||
proxier.syncRunner.Run()
|
proxier.syncRunner.Run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxier *Proxier) OnEndpointsDelete(endpoints *v1.Endpoints) {
|
func (proxier *Proxier) OnEndpointsDelete(endpoints *v1.Endpoints) {
|
||||||
namespacedName := types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}
|
namespacedName := types.NamespacedName{Namespace: endpoints.Namespace, Name: endpoints.Name}
|
||||||
if proxier.endpointsChanges.update(&namespacedName, endpoints, nil) && proxier.isInitialized() {
|
if proxier.endpointsChanges.update(&namespacedName, endpoints, nil, proxier.hns) && proxier.isInitialized() {
|
||||||
proxier.syncRunner.Run()
|
proxier.syncRunner.Run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -867,7 +861,7 @@ func getLocalIPs(endpointsMap proxyEndpointsMap) map[types.NamespacedName]sets.S
|
||||||
// This function is used for incremental updated of endpointsMap.
|
// This function is used for incremental updated of endpointsMap.
|
||||||
//
|
//
|
||||||
// NOTE: endpoints object should NOT be modified.
|
// NOTE: endpoints object should NOT be modified.
|
||||||
func endpointsToEndpointsMap(endpoints *v1.Endpoints, hostname string) proxyEndpointsMap {
|
func endpointsToEndpointsMap(endpoints *v1.Endpoints, hostname string, hns HostNetworkService) proxyEndpointsMap {
|
||||||
if endpoints == nil {
|
if endpoints == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -880,7 +874,7 @@ func endpointsToEndpointsMap(endpoints *v1.Endpoints, hostname string) proxyEndp
|
||||||
for i := range ss.Ports {
|
for i := range ss.Ports {
|
||||||
port := &ss.Ports[i]
|
port := &ss.Ports[i]
|
||||||
if port.Port == 0 {
|
if port.Port == 0 {
|
||||||
klog.Warningf("ignoring invalid endpoint port %s", port.Name)
|
klog.Warningf("Ignoring invalid endpoint port %s", port.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
svcPortName := proxy.ServicePortName{
|
svcPortName := proxy.ServicePortName{
|
||||||
|
@ -890,11 +884,11 @@ func endpointsToEndpointsMap(endpoints *v1.Endpoints, hostname string) proxyEndp
|
||||||
for i := range ss.Addresses {
|
for i := range ss.Addresses {
|
||||||
addr := &ss.Addresses[i]
|
addr := &ss.Addresses[i]
|
||||||
if addr.IP == "" {
|
if addr.IP == "" {
|
||||||
klog.Warningf("ignoring invalid endpoint port %s with empty host", port.Name)
|
klog.Warningf("Ignoring invalid endpoint port %s with empty host", port.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
isLocal := addr.NodeName != nil && *addr.NodeName == hostname
|
isLocal := addr.NodeName != nil && *addr.NodeName == hostname
|
||||||
epInfo := newEndpointInfo(addr.IP, uint16(port.Port), isLocal)
|
epInfo := newEndpointInfo(addr.IP, uint16(port.Port), isLocal, hns)
|
||||||
endpointsMap[svcPortName] = append(endpointsMap[svcPortName], epInfo)
|
endpointsMap[svcPortName] = append(endpointsMap[svcPortName], epInfo)
|
||||||
}
|
}
|
||||||
if klog.V(3) {
|
if klog.V(3) {
|
||||||
|
@ -912,7 +906,7 @@ func endpointsToEndpointsMap(endpoints *v1.Endpoints, hostname string) proxyEndp
|
||||||
// Translates single Service object to proxyServiceMap.
|
// Translates single Service object to proxyServiceMap.
|
||||||
//
|
//
|
||||||
// NOTE: service object should NOT be modified.
|
// NOTE: service object should NOT be modified.
|
||||||
func serviceToServiceMap(service *v1.Service) proxyServiceMap {
|
func serviceToServiceMap(service *v1.Service, hns HostNetworkService) proxyServiceMap {
|
||||||
if service == nil {
|
if service == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -925,7 +919,7 @@ func serviceToServiceMap(service *v1.Service) proxyServiceMap {
|
||||||
for i := range service.Spec.Ports {
|
for i := range service.Spec.Ports {
|
||||||
servicePort := &service.Spec.Ports[i]
|
servicePort := &service.Spec.Ports[i]
|
||||||
svcPortName := proxy.ServicePortName{NamespacedName: svcName, Port: servicePort.Name}
|
svcPortName := proxy.ServicePortName{NamespacedName: svcName, Port: servicePort.Name}
|
||||||
serviceMap[svcPortName] = newServiceInfo(svcPortName, servicePort, service)
|
serviceMap[svcPortName] = newServiceInfo(svcPortName, servicePort, service, hns)
|
||||||
}
|
}
|
||||||
return serviceMap
|
return serviceMap
|
||||||
}
|
}
|
||||||
|
@ -972,12 +966,36 @@ func (proxier *Proxier) syncProxyRules() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var hnsEndpoints []hcsshim.HNSEndpoint
|
hnsNetworkName := proxier.network.name
|
||||||
|
hns := proxier.hns
|
||||||
|
if proxier.network.networkType == "Overlay" {
|
||||||
|
serviceVipEndpoint, _ := hns.getEndpointByIpAddress(svcInfo.clusterIP.String(), hnsNetworkName)
|
||||||
|
if serviceVipEndpoint == nil {
|
||||||
|
klog.V(4).Infof("No existing remote endpoint for service VIP %v", svcInfo.clusterIP.String())
|
||||||
|
hnsEndpoint := &endpointsInfo{
|
||||||
|
ip: svcInfo.clusterIP.String(),
|
||||||
|
isLocal: false,
|
||||||
|
macAddress: proxier.hostMac,
|
||||||
|
providerAddress: proxier.nodeIP.String(),
|
||||||
|
}
|
||||||
|
|
||||||
|
newHnsEndpoint, err := hns.createEndpoint(hnsEndpoint, hnsNetworkName)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("Remote endpoint creation failed for service VIP: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
newHnsEndpoint.refCount++
|
||||||
|
svcInfo.remoteEndpoint = newHnsEndpoint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hnsEndpoints []endpointsInfo
|
||||||
klog.V(4).Infof("====Applying Policy for %s====", svcName)
|
klog.V(4).Infof("====Applying Policy for %s====", svcName)
|
||||||
// Create Remote endpoints for every endpoint, corresponding to the service
|
// Create Remote endpoints for every endpoint, corresponding to the service
|
||||||
|
|
||||||
for _, ep := range proxier.endpointsMap[svcName] {
|
for _, ep := range proxier.endpointsMap[svcName] {
|
||||||
var newHnsEndpoint *hcsshim.HNSEndpoint
|
var newHnsEndpoint *endpointsInfo
|
||||||
hnsNetworkName := proxier.network.name
|
hnsNetworkName := proxier.network.name
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -989,14 +1007,14 @@ func (proxier *Proxier) syncProxyRules() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ep.hnsID) > 0 {
|
if len(ep.hnsID) > 0 {
|
||||||
newHnsEndpoint, err = hcsshim.GetHNSEndpointByID(ep.hnsID)
|
newHnsEndpoint, err = hns.getEndpointByID(ep.hnsID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if newHnsEndpoint == nil {
|
if newHnsEndpoint == nil {
|
||||||
// First check if an endpoint resource exists for this IP, on the current host
|
// First check if an endpoint resource exists for this IP, on the current host
|
||||||
// A Local endpoint could exist here already
|
// A Local endpoint could exist here already
|
||||||
// A remote endpoint was already created and proxy was restarted
|
// A remote endpoint was already created and proxy was restarted
|
||||||
newHnsEndpoint, err = getHnsEndpointByIpAddress(net.ParseIP(ep.ip), hnsNetworkName)
|
newHnsEndpoint, err = hns.getEndpointByIpAddress(ep.ip, hnsNetworkName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if newHnsEndpoint == nil {
|
if newHnsEndpoint == nil {
|
||||||
|
@ -1004,29 +1022,63 @@ func (proxier *Proxier) syncProxyRules() {
|
||||||
klog.Errorf("Local endpoint not found for %v: err: %v on network %s", ep.ip, err, hnsNetworkName)
|
klog.Errorf("Local endpoint not found for %v: err: %v on network %s", ep.ip, err, hnsNetworkName)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// hns Endpoint resource was not found, create one
|
|
||||||
hnsnetwork, err := hcsshim.GetHNSNetworkByName(hnsNetworkName)
|
|
||||||
if err != nil {
|
|
||||||
klog.Errorf("%v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
hnsEndpoint := &hcsshim.HNSEndpoint{
|
if proxier.network.networkType == "Overlay" {
|
||||||
MacAddress: ep.macAddress,
|
klog.Infof("Updating network %v to check for new remote subnet policies", proxier.network.name)
|
||||||
IPAddress: net.ParseIP(ep.ip),
|
networkName := proxier.network.name
|
||||||
}
|
updatedNetwork, err := hns.getNetworkByName(networkName)
|
||||||
|
if err != nil {
|
||||||
|
klog.Fatalf("Failed to get network %v: %v", networkName, err)
|
||||||
|
}
|
||||||
|
proxier.network = *updatedNetwork
|
||||||
|
var providerAddress string
|
||||||
|
for _, rs := range proxier.network.remoteSubnets {
|
||||||
|
_, ipNet, err := net.ParseCIDR(rs.destinationPrefix)
|
||||||
|
if err != nil {
|
||||||
|
klog.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
if ipNet.Contains(net.ParseIP(ep.ip)) {
|
||||||
|
providerAddress = rs.providerAddress
|
||||||
|
}
|
||||||
|
if ep.ip == rs.providerAddress {
|
||||||
|
providerAddress = rs.providerAddress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(providerAddress) == 0 {
|
||||||
|
klog.Errorf("Could not find provider address for %s", ep.ip)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hnsEndpoint := &endpointsInfo{
|
||||||
|
ip: ep.ip,
|
||||||
|
isLocal: false,
|
||||||
|
macAddress: conjureMac("02-11", net.ParseIP(ep.ip)),
|
||||||
|
providerAddress: providerAddress,
|
||||||
|
}
|
||||||
|
|
||||||
newHnsEndpoint, err = hnsnetwork.CreateRemoteEndpoint(hnsEndpoint)
|
newHnsEndpoint, err = hns.createEndpoint(hnsEndpoint, hnsNetworkName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Remote endpoint creation failed: %v", err)
|
klog.Errorf("Remote endpoint creation failed: %v, %s", err, spew.Sdump(hnsEndpoint))
|
||||||
continue
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hnsEndpoint := &endpointsInfo{
|
||||||
|
ip: ep.ip,
|
||||||
|
isLocal: false,
|
||||||
|
macAddress: ep.macAddress,
|
||||||
|
}
|
||||||
|
|
||||||
|
newHnsEndpoint, err = hns.createEndpoint(hnsEndpoint, hnsNetworkName)
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("Remote endpoint creation failed: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the hnsId for reference
|
// Save the hnsId for reference
|
||||||
LogJson(newHnsEndpoint, "Hns Endpoint resource", 1)
|
LogJson(newHnsEndpoint, "Hns Endpoint resource", 1)
|
||||||
hnsEndpoints = append(hnsEndpoints, *newHnsEndpoint)
|
hnsEndpoints = append(hnsEndpoints, *newHnsEndpoint)
|
||||||
ep.hnsID = newHnsEndpoint.Id
|
ep.hnsID = newHnsEndpoint.hnsID
|
||||||
ep.refCount++
|
ep.refCount++
|
||||||
Log(ep, "Endpoint resource found", 3)
|
Log(ep, "Endpoint resource found", 3)
|
||||||
}
|
}
|
||||||
|
@ -1044,11 +1096,13 @@ func (proxier *Proxier) syncProxyRules() {
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.V(4).Infof("Trying to Apply Policies for service %s", spew.Sdump(svcInfo))
|
klog.V(4).Infof("Trying to Apply Policies for service %s", spew.Sdump(svcInfo))
|
||||||
var hnsLoadBalancer *hcsshim.PolicyList
|
var hnsLoadBalancer *loadBalancerInfo
|
||||||
|
|
||||||
hnsLoadBalancer, err := getHnsLoadBalancer(
|
hnsLoadBalancer, err := hns.getLoadBalancer(
|
||||||
hnsEndpoints,
|
hnsEndpoints,
|
||||||
false,
|
false,
|
||||||
|
proxier.isDSR,
|
||||||
|
proxier.sourceVip,
|
||||||
svcInfo.clusterIP.String(),
|
svcInfo.clusterIP.String(),
|
||||||
Enum(svcInfo.protocol),
|
Enum(svcInfo.protocol),
|
||||||
uint16(svcInfo.targetPort),
|
uint16(svcInfo.targetPort),
|
||||||
|
@ -1059,15 +1113,17 @@ func (proxier *Proxier) syncProxyRules() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
svcInfo.hnsID = hnsLoadBalancer.ID
|
svcInfo.hnsID = hnsLoadBalancer.hnsID
|
||||||
klog.V(3).Infof("Hns LoadBalancer resource created for cluster ip resources %v, Id [%s]", svcInfo.clusterIP, hnsLoadBalancer.ID)
|
klog.V(3).Infof("Hns LoadBalancer resource created for cluster ip resources %v, Id [%s]", svcInfo.clusterIP, hnsLoadBalancer.hnsID)
|
||||||
|
|
||||||
// If nodePort is specified, user should be able to use nodeIP:nodePort to reach the backend endpoints
|
// If nodePort is specified, user should be able to use nodeIP:nodePort to reach the backend endpoints
|
||||||
if svcInfo.nodePort > 0 {
|
if svcInfo.nodePort > 0 {
|
||||||
hnsLoadBalancer, err := getHnsLoadBalancer(
|
hnsLoadBalancer, err := hns.getLoadBalancer(
|
||||||
hnsEndpoints,
|
hnsEndpoints,
|
||||||
false,
|
false,
|
||||||
"", // VIP has to be empty to automatically select the nodeIP
|
false,
|
||||||
|
proxier.sourceVip,
|
||||||
|
"",
|
||||||
Enum(svcInfo.protocol),
|
Enum(svcInfo.protocol),
|
||||||
uint16(svcInfo.targetPort),
|
uint16(svcInfo.targetPort),
|
||||||
uint16(svcInfo.nodePort),
|
uint16(svcInfo.nodePort),
|
||||||
|
@ -1077,16 +1133,18 @@ func (proxier *Proxier) syncProxyRules() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
svcInfo.nodePorthnsID = hnsLoadBalancer.ID
|
svcInfo.nodePorthnsID = hnsLoadBalancer.hnsID
|
||||||
klog.V(3).Infof("Hns LoadBalancer resource created for nodePort resources %v, Id [%s]", svcInfo.clusterIP, hnsLoadBalancer.ID)
|
klog.V(3).Infof("Hns LoadBalancer resource created for nodePort resources %v, Id [%s]", svcInfo.clusterIP, hnsLoadBalancer.hnsID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a Load Balancer Policy for each external IP
|
// Create a Load Balancer Policy for each external IP
|
||||||
for _, externalIp := range svcInfo.externalIPs {
|
for _, externalIp := range svcInfo.externalIPs {
|
||||||
// Try loading existing policies, if already available
|
// Try loading existing policies, if already available
|
||||||
hnsLoadBalancer, err := getHnsLoadBalancer(
|
hnsLoadBalancer, err = hns.getLoadBalancer(
|
||||||
hnsEndpoints,
|
hnsEndpoints,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
|
proxier.sourceVip,
|
||||||
externalIp.ip,
|
externalIp.ip,
|
||||||
Enum(svcInfo.protocol),
|
Enum(svcInfo.protocol),
|
||||||
uint16(svcInfo.targetPort),
|
uint16(svcInfo.targetPort),
|
||||||
|
@ -1096,15 +1154,17 @@ func (proxier *Proxier) syncProxyRules() {
|
||||||
klog.Errorf("Policy creation failed: %v", err)
|
klog.Errorf("Policy creation failed: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
externalIp.hnsID = hnsLoadBalancer.ID
|
externalIp.hnsID = hnsLoadBalancer.hnsID
|
||||||
klog.V(3).Infof("Hns LoadBalancer resource created for externalIp resources %v, Id[%s]", externalIp, hnsLoadBalancer.ID)
|
klog.V(3).Infof("Hns LoadBalancer resource created for externalIp resources %v, Id[%s]", externalIp, hnsLoadBalancer.hnsID)
|
||||||
}
|
}
|
||||||
// Create a Load Balancer Policy for each loadbalancer ingress
|
// Create a Load Balancer Policy for each loadbalancer ingress
|
||||||
for _, lbIngressIp := range svcInfo.loadBalancerIngressIPs {
|
for _, lbIngressIp := range svcInfo.loadBalancerIngressIPs {
|
||||||
// Try loading existing policies, if already available
|
// Try loading existing policies, if already available
|
||||||
hnsLoadBalancer, err := getHnsLoadBalancer(
|
hnsLoadBalancer, err := hns.getLoadBalancer(
|
||||||
hnsEndpoints,
|
hnsEndpoints,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
|
proxier.sourceVip,
|
||||||
lbIngressIp.ip,
|
lbIngressIp.ip,
|
||||||
Enum(svcInfo.protocol),
|
Enum(svcInfo.protocol),
|
||||||
uint16(svcInfo.targetPort),
|
uint16(svcInfo.targetPort),
|
||||||
|
@ -1114,7 +1174,7 @@ func (proxier *Proxier) syncProxyRules() {
|
||||||
klog.Errorf("Policy creation failed: %v", err)
|
klog.Errorf("Policy creation failed: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
lbIngressIp.hnsID = hnsLoadBalancer.ID
|
lbIngressIp.hnsID = hnsLoadBalancer.hnsID
|
||||||
klog.V(3).Infof("Hns LoadBalancer resource created for loadBalancer Ingress resources %v", lbIngressIp)
|
klog.V(3).Infof("Hns LoadBalancer resource created for loadBalancer Ingress resources %v", lbIngressIp)
|
||||||
}
|
}
|
||||||
svcInfo.policyApplied = true
|
svcInfo.policyApplied = true
|
||||||
|
|
|
@ -0,0 +1,379 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2018 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 winkernel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/kubernetes/pkg/proxy"
|
||||||
|
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
const testHostName = "test-hostname"
|
||||||
|
const macAddress = "00-11-22-33-44-55"
|
||||||
|
const clusterCIDR = "192.168.1.0/24"
|
||||||
|
const destinationPrefix = "192.168.2.0/24"
|
||||||
|
const providerAddress = "10.0.0.3"
|
||||||
|
const guid = "123ABC"
|
||||||
|
|
||||||
|
type fakeHealthChecker struct {
|
||||||
|
services map[types.NamespacedName]uint16
|
||||||
|
endpoints map[types.NamespacedName]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFakeHealthChecker() *fakeHealthChecker {
|
||||||
|
return &fakeHealthChecker{
|
||||||
|
services: map[types.NamespacedName]uint16{},
|
||||||
|
endpoints: map[types.NamespacedName]int{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (fake *fakeHealthChecker) SyncServices(newServices map[types.NamespacedName]uint16) error {
|
||||||
|
fake.services = newServices
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeHealthChecker) SyncEndpoints(newEndpoints map[types.NamespacedName]int) error {
|
||||||
|
fake.endpoints = newEndpoints
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeHNS struct{}
|
||||||
|
|
||||||
|
func newFakeHNS() *fakeHNS {
|
||||||
|
return &fakeHNS{}
|
||||||
|
}
|
||||||
|
func (hns fakeHNS) getNetworkByName(name string) (*hnsNetworkInfo, error) {
|
||||||
|
var remoteSubnets []*remoteSubnetInfo
|
||||||
|
rs := &remoteSubnetInfo{
|
||||||
|
destinationPrefix: destinationPrefix,
|
||||||
|
isolationId: 4096,
|
||||||
|
providerAddress: providerAddress,
|
||||||
|
drMacAddress: macAddress,
|
||||||
|
}
|
||||||
|
remoteSubnets = append(remoteSubnets, rs)
|
||||||
|
return &hnsNetworkInfo{
|
||||||
|
id: strings.ToUpper(guid),
|
||||||
|
name: name,
|
||||||
|
networkType: "Overlay",
|
||||||
|
remoteSubnets: remoteSubnets,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
func (hns fakeHNS) getEndpointByID(id string) (*endpointsInfo, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
func (hns fakeHNS) getEndpointByIpAddress(ip string, networkName string) (*endpointsInfo, error) {
|
||||||
|
_, ipNet, _ := net.ParseCIDR(destinationPrefix)
|
||||||
|
|
||||||
|
if ipNet.Contains(net.ParseIP(ip)) {
|
||||||
|
return &endpointsInfo{
|
||||||
|
ip: ip,
|
||||||
|
isLocal: true,
|
||||||
|
macAddress: macAddress,
|
||||||
|
hnsID: guid,
|
||||||
|
hns: hns,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
func (hns fakeHNS) createEndpoint(ep *endpointsInfo, networkName string) (*endpointsInfo, error) {
|
||||||
|
return &endpointsInfo{
|
||||||
|
ip: ep.ip,
|
||||||
|
isLocal: ep.isLocal,
|
||||||
|
macAddress: ep.macAddress,
|
||||||
|
hnsID: guid,
|
||||||
|
hns: hns,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
func (hns fakeHNS) deleteEndpoint(hnsID string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (hns fakeHNS) getLoadBalancer(endpoints []endpointsInfo, isILB bool, isDSR bool, sourceVip string, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*loadBalancerInfo, error) {
|
||||||
|
return &loadBalancerInfo{
|
||||||
|
hnsID: guid,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
func (hns fakeHNS) deleteLoadBalancer(hnsID string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func NewFakeProxier(syncPeriod time.Duration, minSyncPeriod time.Duration, clusterCIDR string, hostname string, nodeIP net.IP, networkType string) *Proxier {
|
||||||
|
sourceVip := "192.168.1.2"
|
||||||
|
hnsNetworkInfo := &hnsNetworkInfo{
|
||||||
|
name: "TestNetwork",
|
||||||
|
networkType: networkType,
|
||||||
|
}
|
||||||
|
proxier := &Proxier{
|
||||||
|
portsMap: make(map[localPort]closeable),
|
||||||
|
serviceMap: make(proxyServiceMap),
|
||||||
|
serviceChanges: newServiceChangeMap(),
|
||||||
|
endpointsMap: make(proxyEndpointsMap),
|
||||||
|
endpointsChanges: newEndpointsChangeMap(hostname),
|
||||||
|
clusterCIDR: clusterCIDR,
|
||||||
|
hostname: testHostName,
|
||||||
|
nodeIP: nodeIP,
|
||||||
|
healthChecker: newFakeHealthChecker(),
|
||||||
|
network: *hnsNetworkInfo,
|
||||||
|
sourceVip: sourceVip,
|
||||||
|
hostMac: macAddress,
|
||||||
|
isDSR: false,
|
||||||
|
hns: newFakeHNS(),
|
||||||
|
}
|
||||||
|
return proxier
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateServiceVip(t *testing.T) {
|
||||||
|
syncPeriod := 30 * time.Second
|
||||||
|
proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", net.ParseIP("10.0.0.1"), "Overlay")
|
||||||
|
if proxier == nil {
|
||||||
|
t.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
svcIP := "10.20.30.41"
|
||||||
|
svcPort := 80
|
||||||
|
svcNodePort := 3001
|
||||||
|
svcExternalIPs := "50.60.70.81"
|
||||||
|
svcPortName := proxy.ServicePortName{
|
||||||
|
NamespacedName: makeNSN("ns1", "svc1"),
|
||||||
|
Port: "p80",
|
||||||
|
}
|
||||||
|
timeoutSeconds := v1.DefaultClientIPServiceAffinitySeconds
|
||||||
|
|
||||||
|
makeServiceMap(proxier,
|
||||||
|
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
|
||||||
|
svc.Spec.Type = "NodePort"
|
||||||
|
svc.Spec.ClusterIP = svcIP
|
||||||
|
svc.Spec.ExternalIPs = []string{svcExternalIPs}
|
||||||
|
svc.Spec.SessionAffinity = v1.ServiceAffinityClientIP
|
||||||
|
svc.Spec.SessionAffinityConfig = &v1.SessionAffinityConfig{
|
||||||
|
ClientIP: &v1.ClientIPConfig{
|
||||||
|
TimeoutSeconds: &timeoutSeconds,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
svc.Spec.Ports = []v1.ServicePort{{
|
||||||
|
Name: svcPortName.Port,
|
||||||
|
Port: int32(svcPort),
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
NodePort: int32(svcNodePort),
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
makeEndpointsMap(proxier)
|
||||||
|
|
||||||
|
proxier.syncProxyRules()
|
||||||
|
|
||||||
|
if proxier.serviceMap[svcPortName].remoteEndpoint == nil {
|
||||||
|
t.Error()
|
||||||
|
}
|
||||||
|
if proxier.serviceMap[svcPortName].remoteEndpoint.ip != svcIP {
|
||||||
|
t.Error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestCreateRemoteEndpointOverlay(t *testing.T) {
|
||||||
|
syncPeriod := 30 * time.Second
|
||||||
|
proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", net.ParseIP("10.0.0.1"), "Overlay")
|
||||||
|
if proxier == nil {
|
||||||
|
t.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
svcIP := "10.20.30.41"
|
||||||
|
svcPort := 80
|
||||||
|
svcNodePort := 3001
|
||||||
|
svcPortName := proxy.ServicePortName{
|
||||||
|
NamespacedName: makeNSN("ns1", "svc1"),
|
||||||
|
Port: "p80",
|
||||||
|
}
|
||||||
|
|
||||||
|
makeServiceMap(proxier,
|
||||||
|
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
|
||||||
|
svc.Spec.Type = "NodePort"
|
||||||
|
svc.Spec.ClusterIP = svcIP
|
||||||
|
svc.Spec.Ports = []v1.ServicePort{{
|
||||||
|
Name: svcPortName.Port,
|
||||||
|
Port: int32(svcPort),
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
NodePort: int32(svcNodePort),
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
makeEndpointsMap(proxier,
|
||||||
|
makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *v1.Endpoints) {
|
||||||
|
ept.Subsets = []v1.EndpointSubset{{
|
||||||
|
Addresses: []v1.EndpointAddress{{
|
||||||
|
IP: epIpAddressRemote,
|
||||||
|
}},
|
||||||
|
Ports: []v1.EndpointPort{{
|
||||||
|
Name: svcPortName.Port,
|
||||||
|
Port: int32(svcPort),
|
||||||
|
}},
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
proxier.syncProxyRules()
|
||||||
|
|
||||||
|
if proxier.endpointsMap[svcPortName][0].hnsID != guid {
|
||||||
|
t.Errorf("%v does not match %v", proxier.endpointsMap[svcPortName][0].hnsID, guid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestCreateRemoteEndpointL2Bridge(t *testing.T) {
|
||||||
|
syncPeriod := 30 * time.Second
|
||||||
|
proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", net.ParseIP("10.0.0.1"), "L2Bridge")
|
||||||
|
if proxier == nil {
|
||||||
|
t.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
svcIP := "10.20.30.41"
|
||||||
|
svcPort := 80
|
||||||
|
svcNodePort := 3001
|
||||||
|
svcPortName := proxy.ServicePortName{
|
||||||
|
NamespacedName: makeNSN("ns1", "svc1"),
|
||||||
|
Port: "p80",
|
||||||
|
}
|
||||||
|
|
||||||
|
makeServiceMap(proxier,
|
||||||
|
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
|
||||||
|
svc.Spec.Type = "NodePort"
|
||||||
|
svc.Spec.ClusterIP = svcIP
|
||||||
|
svc.Spec.Ports = []v1.ServicePort{{
|
||||||
|
Name: svcPortName.Port,
|
||||||
|
Port: int32(svcPort),
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
NodePort: int32(svcNodePort),
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
makeEndpointsMap(proxier,
|
||||||
|
makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *v1.Endpoints) {
|
||||||
|
ept.Subsets = []v1.EndpointSubset{{
|
||||||
|
Addresses: []v1.EndpointAddress{{
|
||||||
|
IP: epIpAddressRemote,
|
||||||
|
}},
|
||||||
|
Ports: []v1.EndpointPort{{
|
||||||
|
Name: svcPortName.Port,
|
||||||
|
Port: int32(svcPort),
|
||||||
|
}},
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
proxier.syncProxyRules()
|
||||||
|
|
||||||
|
if proxier.endpointsMap[svcPortName][0].hnsID != guid {
|
||||||
|
t.Errorf("%v does not match %v", proxier.endpointsMap[svcPortName][0].hnsID, guid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestCreateLoadBalancer(t *testing.T) {
|
||||||
|
syncPeriod := 30 * time.Second
|
||||||
|
proxier := NewFakeProxier(syncPeriod, syncPeriod, clusterCIDR, "testhost", net.ParseIP("10.0.0.1"), "Overlay")
|
||||||
|
if proxier == nil {
|
||||||
|
t.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
svcIP := "10.20.30.41"
|
||||||
|
svcPort := 80
|
||||||
|
svcNodePort := 3001
|
||||||
|
svcPortName := proxy.ServicePortName{
|
||||||
|
NamespacedName: makeNSN("ns1", "svc1"),
|
||||||
|
Port: "p80",
|
||||||
|
}
|
||||||
|
|
||||||
|
makeServiceMap(proxier,
|
||||||
|
makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) {
|
||||||
|
svc.Spec.Type = "NodePort"
|
||||||
|
svc.Spec.ClusterIP = svcIP
|
||||||
|
svc.Spec.Ports = []v1.ServicePort{{
|
||||||
|
Name: svcPortName.Port,
|
||||||
|
Port: int32(svcPort),
|
||||||
|
Protocol: v1.ProtocolTCP,
|
||||||
|
NodePort: int32(svcNodePort),
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
makeEndpointsMap(proxier,
|
||||||
|
makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *v1.Endpoints) {
|
||||||
|
ept.Subsets = []v1.EndpointSubset{{
|
||||||
|
Addresses: []v1.EndpointAddress{{
|
||||||
|
IP: epIpAddressRemote,
|
||||||
|
}},
|
||||||
|
Ports: []v1.EndpointPort{{
|
||||||
|
Name: svcPortName.Port,
|
||||||
|
Port: int32(svcPort),
|
||||||
|
}},
|
||||||
|
}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
proxier.syncProxyRules()
|
||||||
|
|
||||||
|
if proxier.serviceMap[svcPortName].hnsID != guid {
|
||||||
|
t.Errorf("%v does not match %v", proxier.serviceMap[svcPortName].hnsID, guid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func makeNSN(namespace, name string) types.NamespacedName {
|
||||||
|
return types.NamespacedName{Namespace: namespace, Name: name}
|
||||||
|
}
|
||||||
|
func makeServiceMap(proxier *Proxier, allServices ...*v1.Service) {
|
||||||
|
for i := range allServices {
|
||||||
|
proxier.OnServiceAdd(allServices[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
proxier.mu.Lock()
|
||||||
|
defer proxier.mu.Unlock()
|
||||||
|
proxier.servicesSynced = true
|
||||||
|
}
|
||||||
|
func makeTestService(namespace, name string, svcFunc func(*v1.Service)) *v1.Service {
|
||||||
|
svc := &v1.Service{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
Namespace: namespace,
|
||||||
|
Annotations: map[string]string{},
|
||||||
|
},
|
||||||
|
Spec: v1.ServiceSpec{},
|
||||||
|
Status: v1.ServiceStatus{},
|
||||||
|
}
|
||||||
|
svcFunc(svc)
|
||||||
|
return svc
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeEndpointsMap(proxier *Proxier, allEndpoints ...*v1.Endpoints) {
|
||||||
|
for i := range allEndpoints {
|
||||||
|
proxier.OnEndpointsAdd(allEndpoints[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
proxier.mu.Lock()
|
||||||
|
defer proxier.mu.Unlock()
|
||||||
|
proxier.endpointsSynced = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTestEndpoints(namespace, name string, eptFunc func(*v1.Endpoints)) *v1.Endpoints {
|
||||||
|
ept := &v1.Endpoints{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
eptFunc(ept)
|
||||||
|
return ept
|
||||||
|
}
|
Loading…
Reference in New Issue