win-bridge: add support for portMappings capability
If the pluging receives portMappings in runtimeConfig, the pluing will add a NAT policy for each port mapping on the generated endpoints. It enables HostPort usage on Windows with win-bridge. Signed-off-by: Vincent Boulineau <vincent.boulineau@datadoghq.com>
This commit is contained in:
@ -20,10 +20,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Microsoft/hcsshim/hcn"
|
"github.com/Microsoft/hcsshim/hcn"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NetConf is the CNI spec
|
// NetConf is the CNI spec
|
||||||
@ -46,8 +47,16 @@ type RuntimeDNS struct {
|
|||||||
Search []string `json:"searches,omitempty"`
|
Search []string `json:"searches,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PortMapEntry struct {
|
||||||
|
HostPort int `json:"hostPort"`
|
||||||
|
ContainerPort int `json:"containerPort"`
|
||||||
|
Protocol string `json:"protocol"`
|
||||||
|
HostIP string `json:"hostIP,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type RuntimeConfig struct {
|
type RuntimeConfig struct {
|
||||||
DNS RuntimeDNS `json:"dns"`
|
DNS RuntimeDNS `json:"dns"`
|
||||||
|
PortMaps []PortMapEntry `json:"portMappings,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type policy struct {
|
type policy struct {
|
||||||
@ -207,3 +216,21 @@ func (n *NetConf) ApplyDefaultPAPolicy(paAddress string) {
|
|||||||
Value: []byte(`{"Type": "PA", "PA": "` + paAddress + `"}`),
|
Value: []byte(`{"Type": "PA", "PA": "` + paAddress + `"}`),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplyPortMappingPolicy is used to configure HostPort<>ContainerPort mapping in HNS
|
||||||
|
func (n *NetConf) ApplyPortMappingPolicy(portMappings []PortMapEntry) {
|
||||||
|
if portMappings == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.Policies == nil {
|
||||||
|
n.Policies = make([]policy, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, portMapping := range portMappings {
|
||||||
|
n.Policies = append(n.Policies, policy{
|
||||||
|
Name: "EndpointPolicy",
|
||||||
|
Value: []byte(fmt.Sprintf(`{"Type": "NAT", "InternalPort": %d, "ExternalPort": %d, "Protocol": "%s"}`, portMapping.ContainerPort, portMapping.HostPort, portMapping.Protocol)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -128,6 +128,53 @@ var _ = Describe("HNS NetConf", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Describe("ApplyPortMappingPolicy", func() {
|
||||||
|
Context("when portMappings not activated", func() {
|
||||||
|
It("does nothing", func() {
|
||||||
|
n := NetConf{}
|
||||||
|
n.ApplyPortMappingPolicy(nil)
|
||||||
|
Expect(n.Policies).Should(BeNil())
|
||||||
|
|
||||||
|
n.ApplyPortMappingPolicy([]PortMapEntry{})
|
||||||
|
Expect(n.Policies).Should(HaveLen(0))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("when portMappings is activated", func() {
|
||||||
|
It("creates NAT policies", func() {
|
||||||
|
n := NetConf{}
|
||||||
|
n.ApplyPortMappingPolicy([]PortMapEntry{
|
||||||
|
{
|
||||||
|
ContainerPort: 80,
|
||||||
|
HostPort: 8080,
|
||||||
|
Protocol: "TCP",
|
||||||
|
HostIP: "ignored",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
Expect(n.Policies).Should(HaveLen(1))
|
||||||
|
|
||||||
|
policy := n.Policies[0]
|
||||||
|
Expect(policy.Name).Should(Equal("EndpointPolicy"))
|
||||||
|
|
||||||
|
value := make(map[string]interface{})
|
||||||
|
json.Unmarshal(policy.Value, &value)
|
||||||
|
|
||||||
|
Expect(value).Should(HaveKey("Type"))
|
||||||
|
Expect(value["Type"]).Should(Equal("NAT"))
|
||||||
|
|
||||||
|
Expect(value).Should(HaveKey("InternalPort"))
|
||||||
|
Expect(value["InternalPort"]).Should(Equal(float64(80)))
|
||||||
|
|
||||||
|
Expect(value).Should(HaveKey("ExternalPort"))
|
||||||
|
Expect(value["ExternalPort"]).Should(Equal(float64(8080)))
|
||||||
|
|
||||||
|
Expect(value).Should(HaveKey("Protocol"))
|
||||||
|
Expect(value["Protocol"]).Should(Equal("TCP"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
Describe("MarshalPolicies", func() {
|
Describe("MarshalPolicies", func() {
|
||||||
Context("when not set by user", func() {
|
Context("when not set by user", func() {
|
||||||
It("sets it by adding a policy", func() {
|
It("sets it by adding a policy", func() {
|
||||||
|
@ -35,7 +35,8 @@ With win-bridge plugin, all containers (on the same host) are plugged into an L2
|
|||||||
],
|
],
|
||||||
"loopbackDSR": true,
|
"loopbackDSR": true,
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"dns": true
|
"dns": true,
|
||||||
|
"portMappings": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -54,4 +55,5 @@ With win-bridge plugin, all containers (on the same host) are plugged into an L2
|
|||||||
* `HcnPolicyArgs` (list, optional): List of hcn policies to be used (only used when ApiVersion is 2).
|
* `HcnPolicyArgs` (list, optional): List of hcn policies to be used (only used when ApiVersion is 2).
|
||||||
* `loopbackDSR` (bool, optional): If true, will add a policy to allow the interface to support loopback direct server return.
|
* `loopbackDSR` (bool, optional): If true, will add a policy to allow the interface to support loopback direct server return.
|
||||||
* `capabilities` (dictionary, optional): Runtime capabilities to enable.
|
* `capabilities` (dictionary, optional): Runtime capabilities to enable.
|
||||||
* `dns` (boolean, optional): If true, will take the dns config supplied by the runtime and override other settings.
|
* `dns` (boolean, optional): If true, will take the dns config supplied by the runtime and override other settings.
|
||||||
|
* `portMappings` (boolean, optional): If true, will handle HostPort<>ContainerPort mapping using NAT HNS Policies
|
@ -86,6 +86,9 @@ func ProcessEndpointArgs(args *skel.CmdArgs, n *NetConf) (*hns.EndpointInfo, err
|
|||||||
n.ApplyOutboundNatPolicy(n.IPMasqNetwork)
|
n.ApplyOutboundNatPolicy(n.IPMasqNetwork)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add HostPort mapping if any present
|
||||||
|
n.ApplyPortMappingPolicy(n.RuntimeConfig.PortMaps)
|
||||||
|
|
||||||
epInfo.DNS = n.GetDNS()
|
epInfo.DNS = n.GetDNS()
|
||||||
|
|
||||||
return epInfo, nil
|
return epInfo, nil
|
||||||
@ -107,7 +110,6 @@ func cmdHnsAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
epName := hns.ConstructEndpointName(args.ContainerID, args.Netns, n.Name)
|
epName := hns.ConstructEndpointName(args.ContainerID, args.Netns, n.Name)
|
||||||
|
|
||||||
hnsEndpoint, err := hns.ProvisionEndpoint(epName, hnsNetwork.Id, args.ContainerID, args.Netns, func() (*hcsshim.HNSEndpoint, error) {
|
hnsEndpoint, err := hns.ProvisionEndpoint(epName, hnsNetwork.Id, args.ContainerID, args.Netns, func() (*hcsshim.HNSEndpoint, error) {
|
||||||
epInfo, err := ProcessEndpointArgs(args, n)
|
epInfo, err := ProcessEndpointArgs(args, n)
|
||||||
epInfo.NetworkId = hnsNetwork.Id
|
epInfo.NetworkId = hnsNetwork.Id
|
||||||
@ -130,7 +132,6 @@ func cmdHnsAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdHcnAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) {
|
func cmdHcnAdd(args *skel.CmdArgs, n *NetConf) (*current.Result, error) {
|
||||||
|
Reference in New Issue
Block a user