mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #1900 from pradipd/overlay_one_endpoint
Tasks connected to a swarm network will have 1 endpoint on windows RS3.
This commit is contained in:
commit
a0bdc52fd7
6 changed files with 94 additions and 35 deletions
|
@ -39,6 +39,11 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
|
||||||
if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil {
|
if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil {
|
||||||
logrus.Errorf("overlay: Failed adding table entry to joininfo: %v", err)
|
logrus.Errorf("overlay: Failed adding table entry to joininfo: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ep.disablegateway {
|
||||||
|
jinfo.DisableGatewayService()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,11 @@ import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/Microsoft/hcsshim"
|
"github.com/Microsoft/hcsshim"
|
||||||
|
"github.com/docker/docker/pkg/system"
|
||||||
"github.com/docker/libnetwork/driverapi"
|
"github.com/docker/libnetwork/driverapi"
|
||||||
|
"github.com/docker/libnetwork/drivers/windows"
|
||||||
|
"github.com/docker/libnetwork/netlabel"
|
||||||
|
"github.com/docker/libnetwork/types"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -15,12 +19,14 @@ type endpointTable map[string]*endpoint
|
||||||
const overlayEndpointPrefix = "overlay/endpoint"
|
const overlayEndpointPrefix = "overlay/endpoint"
|
||||||
|
|
||||||
type endpoint struct {
|
type endpoint struct {
|
||||||
id string
|
id string
|
||||||
nid string
|
nid string
|
||||||
profileId string
|
profileID string
|
||||||
remote bool
|
remote bool
|
||||||
mac net.HardwareAddr
|
mac net.HardwareAddr
|
||||||
addr *net.IPNet
|
addr *net.IPNet
|
||||||
|
disablegateway bool
|
||||||
|
portMapping []types.PortBinding // Operation port bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateID(nid, eid string) error {
|
func validateID(nid, eid string) error {
|
||||||
|
@ -71,7 +77,7 @@ func (n *network) removeEndpointWithAddress(addr *net.IPNet) {
|
||||||
|
|
||||||
if networkEndpoint != nil {
|
if networkEndpoint != nil {
|
||||||
logrus.Debugf("Removing stale endpoint from HNS")
|
logrus.Debugf("Removing stale endpoint from HNS")
|
||||||
_, err := hcsshim.HNSEndpointRequest("DELETE", networkEndpoint.profileId, "")
|
_, err := hcsshim.HNSEndpointRequest("DELETE", networkEndpoint.profileID, "")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Debugf("Failed to delete stale overlay endpoint (%s) from hns", networkEndpoint.id[0:7])
|
logrus.Debugf("Failed to delete stale overlay endpoint (%s) from hns", networkEndpoint.id[0:7])
|
||||||
|
@ -96,7 +102,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||||
logrus.Debugf("Deleting stale endpoint %s", eid)
|
logrus.Debugf("Deleting stale endpoint %s", eid)
|
||||||
n.deleteEndpoint(eid)
|
n.deleteEndpoint(eid)
|
||||||
|
|
||||||
_, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileId, "")
|
_, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -113,17 +119,19 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||||
return fmt.Errorf("create endpoint was not passed interface IP address")
|
return fmt.Errorf("create endpoint was not passed interface IP address")
|
||||||
}
|
}
|
||||||
|
|
||||||
if s := n.getSubnetforIP(ep.addr); s == nil {
|
s := n.getSubnetforIP(ep.addr)
|
||||||
return fmt.Errorf("no matching subnet for IP %q in network %q\n", ep.addr, nid)
|
if s == nil {
|
||||||
|
return fmt.Errorf("no matching subnet for IP %q in network %q", ep.addr, nid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo: Add port bindings and qos policies here
|
// Todo: Add port bindings and qos policies here
|
||||||
|
|
||||||
hnsEndpoint := &hcsshim.HNSEndpoint{
|
hnsEndpoint := &hcsshim.HNSEndpoint{
|
||||||
Name: eid,
|
Name: eid,
|
||||||
VirtualNetwork: n.hnsId,
|
VirtualNetwork: n.hnsID,
|
||||||
IPAddress: ep.addr.IP,
|
IPAddress: ep.addr.IP,
|
||||||
EnableInternalDNS: true,
|
EnableInternalDNS: true,
|
||||||
|
GatewayAddress: s.gwIP.String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if ep.mac != nil {
|
if ep.mac != nil {
|
||||||
|
@ -141,6 +149,31 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||||
|
|
||||||
hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy)
|
hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy)
|
||||||
|
|
||||||
|
if system.GetOSVersion().Build > 16236 {
|
||||||
|
natPolicy, err := json.Marshal(hcsshim.PaPolicy{
|
||||||
|
Type: "OutBoundNAT",
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
hnsEndpoint.Policies = append(hnsEndpoint.Policies, natPolicy)
|
||||||
|
|
||||||
|
epConnectivity, err := windows.ParseEndpointConnectivity(epOptions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pbPolicy, err := windows.ConvertPortBindings(epConnectivity.PortBindings)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hnsEndpoint.Policies = append(hnsEndpoint.Policies, pbPolicy...)
|
||||||
|
|
||||||
|
ep.disablegateway = true
|
||||||
|
}
|
||||||
|
|
||||||
configurationb, err := json.Marshal(hnsEndpoint)
|
configurationb, err := json.Marshal(hnsEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -151,7 +184,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ep.profileId = hnsresponse.Id
|
ep.profileID = hnsresponse.Id
|
||||||
|
|
||||||
if ep.mac == nil {
|
if ep.mac == nil {
|
||||||
ep.mac, err = net.ParseMAC(hnsresponse.MacAddress)
|
ep.mac, err = net.ParseMAC(hnsresponse.MacAddress)
|
||||||
|
@ -164,6 +197,12 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ep.portMapping, err = windows.ParsePortBindingPolicies(hnsresponse.Policies)
|
||||||
|
if err != nil {
|
||||||
|
hcsshim.HNSEndpointRequest("DELETE", hnsresponse.Id, "")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
n.addEndpoint(ep)
|
n.addEndpoint(ep)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -186,7 +225,7 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||||
|
|
||||||
n.deleteEndpoint(eid)
|
n.deleteEndpoint(eid)
|
||||||
|
|
||||||
_, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileId, "")
|
_, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -210,7 +249,17 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
data := make(map[string]interface{}, 1)
|
data := make(map[string]interface{}, 1)
|
||||||
data["hnsid"] = ep.profileId
|
data["hnsid"] = ep.profileID
|
||||||
data["AllowUnqualifiedDNSQuery"] = true
|
data["AllowUnqualifiedDNSQuery"] = true
|
||||||
|
|
||||||
|
if ep.portMapping != nil {
|
||||||
|
// Return a copy of the operational data
|
||||||
|
pmc := make([]types.PortBinding, 0, len(ep.portMapping))
|
||||||
|
for _, pm := range ep.portMapping {
|
||||||
|
pmc = append(pmc, pm.GetCopy())
|
||||||
|
}
|
||||||
|
data[netlabel.PortMap] = pmc
|
||||||
|
}
|
||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ type subnetJSON struct {
|
||||||
type network struct {
|
type network struct {
|
||||||
id string
|
id string
|
||||||
name string
|
name string
|
||||||
hnsId string
|
hnsID string
|
||||||
providerAddress string
|
providerAddress string
|
||||||
interfaceName string
|
interfaceName string
|
||||||
endpoints endpointTable
|
endpoints endpointTable
|
||||||
|
@ -108,7 +108,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
|
||||||
case "com.docker.network.windowsshim.interface":
|
case "com.docker.network.windowsshim.interface":
|
||||||
interfaceName = value
|
interfaceName = value
|
||||||
case "com.docker.network.windowsshim.hnsid":
|
case "com.docker.network.windowsshim.hnsid":
|
||||||
n.hnsId = value
|
n.hnsID = value
|
||||||
case netlabel.OverlayVxlanIDList:
|
case netlabel.OverlayVxlanIDList:
|
||||||
vniStrings := strings.Split(value, ",")
|
vniStrings := strings.Split(value, ",")
|
||||||
for _, vniStr := range vniStrings {
|
for _, vniStr := range vniStrings {
|
||||||
|
@ -181,7 +181,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.deleteNetwork(id)
|
d.deleteNetwork(id)
|
||||||
} else {
|
} else {
|
||||||
genData["com.docker.network.windowsshim.hnsid"] = n.hnsId
|
genData["com.docker.network.windowsshim.hnsid"] = n.hnsID
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -197,7 +197,7 @@ func (d *driver) DeleteNetwork(nid string) error {
|
||||||
return types.ForbiddenErrorf("could not find network with id %s", nid)
|
return types.ForbiddenErrorf("could not find network with id %s", nid)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := hcsshim.HNSNetworkRequest("DELETE", n.hnsId, "")
|
_, err := hcsshim.HNSNetworkRequest("DELETE", n.hnsID, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.ForbiddenErrorf(err.Error())
|
return types.ForbiddenErrorf(err.Error())
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ func (d *driver) network(nid string) *network {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// for _, endpoint := range hnsresponse {
|
// for _, endpoint := range hnsresponse {
|
||||||
// if endpoint.VirtualNetwork != n.hnsId {
|
// if endpoint.VirtualNetwork != n.hnsID {
|
||||||
// continue
|
// continue
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
@ -260,7 +260,7 @@ func (d *driver) network(nid string) *network {
|
||||||
func (n *network) convertToOverlayEndpoint(v *hcsshim.HNSEndpoint) *endpoint {
|
func (n *network) convertToOverlayEndpoint(v *hcsshim.HNSEndpoint) *endpoint {
|
||||||
ep := &endpoint{
|
ep := &endpoint{
|
||||||
id: v.Name,
|
id: v.Name,
|
||||||
profileId: v.Id,
|
profileID: v.Id,
|
||||||
nid: n.id,
|
nid: n.id,
|
||||||
remote: v.IsRemoteEndpoint,
|
remote: v.IsRemoteEndpoint,
|
||||||
}
|
}
|
||||||
|
@ -311,6 +311,7 @@ func (d *driver) createHnsNetwork(n *network) error {
|
||||||
Type: d.Type(),
|
Type: d.Type(),
|
||||||
Subnets: subnets,
|
Subnets: subnets,
|
||||||
NetworkAdapterName: n.interfaceName,
|
NetworkAdapterName: n.interfaceName,
|
||||||
|
AutomaticDNS: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
configurationb, err := json.Marshal(network)
|
configurationb, err := json.Marshal(network)
|
||||||
|
@ -326,7 +327,7 @@ func (d *driver) createHnsNetwork(n *network) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
n.hnsId = hnsresponse.Id
|
n.hnsID = hnsresponse.Id
|
||||||
n.providerAddress = hnsresponse.ManagementIP
|
n.providerAddress = hnsresponse.ManagementIP
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -104,7 +104,7 @@ func (d *driver) restoreHNSNetworks() error {
|
||||||
func (d *driver) convertToOverlayNetwork(v *hcsshim.HNSNetwork) *network {
|
func (d *driver) convertToOverlayNetwork(v *hcsshim.HNSNetwork) *network {
|
||||||
n := &network{
|
n := &network{
|
||||||
id: v.Name,
|
id: v.Name,
|
||||||
hnsId: v.Id,
|
hnsID: v.Id,
|
||||||
driver: d,
|
driver: d,
|
||||||
endpoints: endpointTable{},
|
endpoints: endpointTable{},
|
||||||
subnets: []*subnet{},
|
subnets: []*subnet{},
|
||||||
|
|
|
@ -33,7 +33,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
|
||||||
|
|
||||||
hnsEndpoint := &hcsshim.HNSEndpoint{
|
hnsEndpoint := &hcsshim.HNSEndpoint{
|
||||||
Name: eid,
|
Name: eid,
|
||||||
VirtualNetwork: n.hnsId,
|
VirtualNetwork: n.hnsID,
|
||||||
MacAddress: peerMac.String(),
|
MacAddress: peerMac.String(),
|
||||||
IPAddress: peerIP,
|
IPAddress: peerIP,
|
||||||
IsRemoteEndpoint: true,
|
IsRemoteEndpoint: true,
|
||||||
|
@ -78,7 +78,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
|
||||||
nid: nid,
|
nid: nid,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
mac: peerMac,
|
mac: peerMac,
|
||||||
profileId: hnsresponse.Id,
|
profileID: hnsresponse.Id,
|
||||||
remote: true,
|
remote: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMas
|
||||||
}
|
}
|
||||||
|
|
||||||
if updateDb {
|
if updateDb {
|
||||||
_, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileId, "")
|
_, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,8 @@ type endpointOption struct {
|
||||||
DisableICC bool
|
DisableICC bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type endpointConnectivity struct {
|
// EndpointConnectivity stores the port bindings and exposed ports that the user has specified in epOptions.
|
||||||
|
type EndpointConnectivity struct {
|
||||||
PortBindings []types.PortBinding
|
PortBindings []types.PortBinding
|
||||||
ExposedPorts []types.TransportPort
|
ExposedPorts []types.TransportPort
|
||||||
}
|
}
|
||||||
|
@ -67,7 +68,7 @@ type hnsEndpoint struct {
|
||||||
Type string
|
Type string
|
||||||
macAddress net.HardwareAddr
|
macAddress net.HardwareAddr
|
||||||
epOption *endpointOption // User specified parameters
|
epOption *endpointOption // User specified parameters
|
||||||
epConnectivity *endpointConnectivity // User specified parameters
|
epConnectivity *EndpointConnectivity // User specified parameters
|
||||||
portMapping []types.PortBinding // Operation port bindings
|
portMapping []types.PortBinding // Operation port bindings
|
||||||
addr *net.IPNet
|
addr *net.IPNet
|
||||||
gateway net.IP
|
gateway net.IP
|
||||||
|
@ -95,7 +96,7 @@ const (
|
||||||
errNotFound = "HNS failed with error : The object identifier does not represent a valid object. "
|
errNotFound = "HNS failed with error : The object identifier does not represent a valid object. "
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsBuiltinWindowsDriver vaidates if network-type is a builtin local-scoped driver
|
// IsBuiltinLocalDriver validates if network-type is a builtin local-scoped driver
|
||||||
func IsBuiltinLocalDriver(networkType string) bool {
|
func IsBuiltinLocalDriver(networkType string) bool {
|
||||||
if "l2bridge" == networkType || "l2tunnel" == networkType || "nat" == networkType || "ics" == networkType || "transparent" == networkType {
|
if "l2bridge" == networkType || "l2tunnel" == networkType || "nat" == networkType || "ics" == networkType || "transparent" == networkType {
|
||||||
return true
|
return true
|
||||||
|
@ -396,7 +397,8 @@ func convertQosPolicies(qosPolicies []types.QosPolicy) ([]json.RawMessage, error
|
||||||
return qps, nil
|
return qps, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, error) {
|
// ConvertPortBindings converts PortBindings to JSON for HNS request
|
||||||
|
func ConvertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, error) {
|
||||||
var pbs []json.RawMessage
|
var pbs []json.RawMessage
|
||||||
|
|
||||||
// Enumerate through the port bindings specified by the user and convert
|
// Enumerate through the port bindings specified by the user and convert
|
||||||
|
@ -431,7 +433,8 @@ func convertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, e
|
||||||
return pbs, nil
|
return pbs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePortBindingPolicies(policies []json.RawMessage) ([]types.PortBinding, error) {
|
// ParsePortBindingPolicies parses HNS endpoint response message to PortBindings
|
||||||
|
func ParsePortBindingPolicies(policies []json.RawMessage) ([]types.PortBinding, error) {
|
||||||
var bindings []types.PortBinding
|
var bindings []types.PortBinding
|
||||||
hcsPolicy := &hcsshim.NatPolicy{}
|
hcsPolicy := &hcsshim.NatPolicy{}
|
||||||
|
|
||||||
|
@ -505,12 +508,13 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*endpointOption, er
|
||||||
return ec, nil
|
return ec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseEndpointConnectivity(epOptions map[string]interface{}) (*endpointConnectivity, error) {
|
// ParseEndpointConnectivity parses options passed to CreateEndpoint, specifically port bindings, and store in a endpointConnectivity object.
|
||||||
|
func ParseEndpointConnectivity(epOptions map[string]interface{}) (*EndpointConnectivity, error) {
|
||||||
if epOptions == nil {
|
if epOptions == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ec := &endpointConnectivity{}
|
ec := &EndpointConnectivity{}
|
||||||
|
|
||||||
if opt, ok := epOptions[netlabel.PortMap]; ok {
|
if opt, ok := epOptions[netlabel.PortMap]; ok {
|
||||||
if bs, ok := opt.([]types.PortBinding); ok {
|
if bs, ok := opt.([]types.PortBinding); ok {
|
||||||
|
@ -550,7 +554,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
epConnectivity, err := parseEndpointConnectivity(epOptions)
|
epConnectivity, err := ParseEndpointConnectivity(epOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -561,7 +565,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||||
endpointStruct.MacAddress = strings.Replace(macAddress.String(), ":", "-", -1)
|
endpointStruct.MacAddress = strings.Replace(macAddress.String(), ":", "-", -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
endpointStruct.Policies, err = convertPortBindings(epConnectivity.PortBindings)
|
endpointStruct.Policies, err = ConvertPortBindings(epConnectivity.PortBindings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -615,7 +619,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||||
endpoint.profileID = hnsresponse.Id
|
endpoint.profileID = hnsresponse.Id
|
||||||
endpoint.epConnectivity = epConnectivity
|
endpoint.epConnectivity = epConnectivity
|
||||||
endpoint.epOption = epOption
|
endpoint.epOption = epOption
|
||||||
endpoint.portMapping, err = parsePortBindingPolicies(hnsresponse.Policies)
|
endpoint.portMapping, err = ParsePortBindingPolicies(hnsresponse.Policies)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
hcsshim.HNSEndpointRequest("DELETE", hnsresponse.Id, "")
|
hcsshim.HNSEndpointRequest("DELETE", hnsresponse.Id, "")
|
||||||
|
|
Loading…
Add table
Reference in a new issue