| // Copyright 2017 CNI 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 hns |
| |
| import ( |
| "encoding/json" |
| "net" |
| |
| "github.com/Microsoft/hcsshim/hcn" |
| . "github.com/onsi/ginkgo/v2" |
| . "github.com/onsi/gomega" |
| ) |
| |
| var _ = Describe("NetConf", func() { |
| Describe("ApplyLoopbackDSRPolicy", func() { |
| Context("via v1 api", func() { |
| var n NetConf |
| BeforeEach(func() { |
| n = NetConf{} |
| }) |
| |
| It("filter out duplicated IP", func() { |
| // mock duplicated IP |
| ip := net.ParseIP("172.16.0.12") |
| n.ApplyLoopbackDSRPolicy(&ip) |
| n.ApplyLoopbackDSRPolicy(&ip) |
| |
| // only one policy |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(1)) |
| |
| // normal type judgement |
| policy := addlArgs[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("OutBoundNAT")) |
| Expect(value).Should(HaveKey("Destinations")) |
| |
| // and only one item |
| destinationList := value["Destinations"].([]interface{}) |
| Expect(destinationList).Should(HaveLen(1)) |
| Expect(destinationList[0].(string)).Should(Equal("172.16.0.12")) |
| }) |
| |
| It("append different IP", func() { |
| // mock different IP |
| ip1 := net.ParseIP("172.16.0.12") |
| n.ApplyLoopbackDSRPolicy(&ip1) |
| ip2 := net.ParseIP("172.16.0.13") |
| n.ApplyLoopbackDSRPolicy(&ip2) |
| |
| // will be two policies |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(2)) |
| |
| // normal type judgement |
| policy := addlArgs[1] // pick second item |
| 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("OutBoundNAT")) |
| Expect(value).Should(HaveKey("Destinations")) |
| |
| // only one item |
| destinationList := value["Destinations"].([]interface{}) |
| Expect(destinationList).Should(HaveLen(1)) |
| Expect(destinationList[0].(string)).Should(Equal("172.16.0.13")) |
| }) |
| }) |
| |
| Context("via v2 api", func() { |
| var n NetConf |
| BeforeEach(func() { |
| n = NetConf{ApiVersion: 2} |
| }) |
| |
| It("filter out duplicated IP", func() { |
| // mock duplicated IP |
| ip := net.ParseIP("172.16.0.12") |
| n.ApplyLoopbackDSRPolicy(&ip) |
| n.ApplyLoopbackDSRPolicy(&ip) |
| |
| // only one policy |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(1)) |
| |
| // normal type judgement |
| policy := addlArgs[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("OutBoundNAT")) |
| Expect(value).Should(HaveKey("Settings")) |
| |
| // and only one item |
| settings := value["Settings"].(map[string]interface{}) |
| destinationList := settings["Destinations"].([]interface{}) |
| Expect(destinationList).Should(HaveLen(1)) |
| Expect(destinationList[0].(string)).Should(Equal("172.16.0.12")) |
| }) |
| |
| It("append different IP", func() { |
| // mock different IP |
| ip1 := net.ParseIP("172.16.0.12") |
| n.ApplyLoopbackDSRPolicy(&ip1) |
| ip2 := net.ParseIP("172.16.0.13") |
| n.ApplyLoopbackDSRPolicy(&ip2) |
| |
| // will be two policies |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(2)) |
| |
| // normal type judgement |
| policy := addlArgs[1] // pick second item |
| 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("OutBoundNAT")) |
| Expect(value).Should(HaveKey("Settings")) |
| |
| // only one item |
| settings := value["Settings"].(map[string]interface{}) |
| destinationList := settings["Destinations"].([]interface{}) |
| Expect(destinationList).Should(HaveLen(1)) |
| Expect(destinationList[0].(string)).Should(Equal("172.16.0.13")) |
| }) |
| }) |
| }) |
| |
| Describe("ApplyOutBoundNATPolicy", func() { |
| Context("via v1 api", func() { |
| var n NetConf |
| BeforeEach(func() { |
| n = NetConf{} |
| }) |
| |
| It("append different IP", func() { |
| // mock different IP |
| n.ApplyOutboundNatPolicy("192.168.0.0/16") |
| n.ApplyOutboundNatPolicy("10.244.0.0/16") |
| |
| // will be two policies |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(2)) |
| |
| // normal type judgement |
| policy := addlArgs[1] // pick second item |
| 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("OutBoundNAT")) |
| Expect(value).Should(HaveKey("ExceptionList")) |
| |
| // but get two items |
| exceptionList := value["ExceptionList"].([]interface{}) |
| Expect(exceptionList).Should(HaveLen(1)) |
| Expect(exceptionList[0].(string)).Should(Equal("10.244.0.0/16")) |
| }) |
| |
| It("append a new one if there is not an exception OutBoundNAT policy", func() { |
| // mock different OutBoundNAT routes |
| n.Policies = []Policy{ |
| { |
| Name: "EndpointPolicy", |
| Value: bprintf(`{"Type": "OutBoundNAT", "OtherList": []}`), |
| }, |
| } |
| n.ApplyOutboundNatPolicy("10.244.0.0/16") |
| |
| // has two policies |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(2)) |
| |
| // normal type judgement |
| policy := addlArgs[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("OutBoundNAT")) |
| Expect(value).Should(HaveKey("OtherList")) |
| policy = addlArgs[1] |
| value = make(map[string]interface{}) |
| json.Unmarshal(policy.Value, &value) |
| Expect(value).Should(HaveKey("Type")) |
| Expect(value["Type"]).Should(Equal("OutBoundNAT")) |
| Expect(value).Should(HaveKey("ExceptionList")) |
| |
| // only get one item |
| exceptionList := value["ExceptionList"].([]interface{}) |
| Expect(exceptionList).Should(HaveLen(1)) |
| Expect(exceptionList[0].(string)).Should(Equal("10.244.0.0/16")) |
| }) |
| |
| It("nothing to do if CIDR is blank", func() { |
| // mock different OutBoundNAT routes |
| n.Policies = []Policy{ |
| { |
| Name: "EndpointPolicy", |
| Value: bprintf(`{"Type": "OutBoundNAT", "ExceptionList": []}`), |
| }, |
| } |
| n.ApplyOutboundNatPolicy("") |
| |
| // only one policy |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(1)) |
| |
| // normal type judgement |
| policy := addlArgs[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("OutBoundNAT")) |
| Expect(value).Should(HaveKey("ExceptionList")) |
| |
| // empty list |
| Expect(value["ExceptionList"]).ShouldNot(BeNil()) |
| Expect(value["ExceptionList"]).Should(HaveLen(0)) |
| }) |
| }) |
| |
| Context("via v2 api", func() { |
| var n NetConf |
| BeforeEach(func() { |
| n = NetConf{ApiVersion: 2} |
| }) |
| |
| It("append different IP", func() { |
| // mock different IP |
| n.ApplyOutboundNatPolicy("192.168.0.0/16") |
| n.ApplyOutboundNatPolicy("10.244.0.0/16") |
| |
| // will be two policies |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(2)) |
| |
| // normal type judgement |
| policy := addlArgs[1] // pick second item |
| 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("OutBoundNAT")) |
| Expect(value).Should(HaveKey("Settings")) |
| |
| // but get two items |
| settings := value["Settings"].(map[string]interface{}) |
| exceptionList := settings["Exceptions"].([]interface{}) |
| Expect(exceptionList).Should(HaveLen(1)) |
| Expect(exceptionList[0].(string)).Should(Equal("10.244.0.0/16")) |
| }) |
| |
| It("append a new one if there is not an exception OutBoundNAT policy", func() { |
| // mock different OutBoundNAT routes |
| n.Policies = []Policy{ |
| { |
| Name: "EndpointPolicy", |
| Value: bprintf(`{"Type": "OutBoundNAT", "Settings": {"Others": []}}`), |
| }, |
| } |
| n.ApplyOutboundNatPolicy("10.244.0.0/16") |
| |
| // has two policies |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(2)) |
| |
| // normal type judgement |
| policy := addlArgs[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("OutBoundNAT")) |
| Expect(value).Should(HaveKey("Settings")) |
| Expect(value["Settings"]).Should(HaveKey("Others")) |
| policy = addlArgs[1] |
| value = make(map[string]interface{}) |
| json.Unmarshal(policy.Value, &value) |
| Expect(value).Should(HaveKey("Type")) |
| Expect(value["Type"]).Should(Equal("OutBoundNAT")) |
| Expect(value).Should(HaveKey("Settings")) |
| |
| // only get one item |
| settings := value["Settings"].(map[string]interface{}) |
| exceptionList := settings["Exceptions"].([]interface{}) |
| Expect(exceptionList).Should(HaveLen(1)) |
| Expect(exceptionList[0].(string)).Should(Equal("10.244.0.0/16")) |
| }) |
| |
| It("nothing to do if CIDR is blank", func() { |
| // mock different OutBoundNAT routes |
| n.Policies = []Policy{ |
| { |
| Name: "EndpointPolicy", |
| Value: bprintf(`{"Type": "OutBoundNAT", "Settings": {"Exceptions": []}}`), |
| }, |
| } |
| n.ApplyOutboundNatPolicy("") |
| |
| // only one policy |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(1)) |
| |
| // normal type judgement |
| policy := addlArgs[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("OutBoundNAT")) |
| Expect(value).Should(HaveKey("Settings")) |
| |
| // empty list |
| settings := value["Settings"].(map[string]interface{}) |
| Expect(settings["Exceptions"]).ShouldNot(BeNil()) |
| Expect(settings["Exceptions"]).Should(HaveLen(0)) |
| }) |
| }) |
| }) |
| |
| Describe("ApplyDefaultPAPolicy", func() { |
| Context("via v1 api", func() { |
| var n NetConf |
| BeforeEach(func() { |
| n = NetConf{} |
| }) |
| |
| It("append different IP", func() { |
| // mock different IP |
| n.ApplyDefaultPAPolicy("192.168.0.1") |
| n.ApplyDefaultPAPolicy("192.168.0.2") |
| |
| // will be two policies |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(2)) |
| |
| // normal type judgement |
| policy := addlArgs[1] // judge second item |
| 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("PA")) |
| |
| // compare with second item |
| paAddress := value["PA"].(string) |
| Expect(paAddress).Should(Equal("192.168.0.2")) |
| }) |
| |
| It("nothing to do if IP is blank", func() { |
| // mock different policy |
| n.Policies = []Policy{ |
| { |
| Name: "EndpointPolicy", |
| Value: bprintf(`{"Type": "OutBoundNAT", "Exceptions": ["192.168.0.0/16"]}`), |
| }, |
| } |
| n.ApplyDefaultPAPolicy("") |
| |
| // nothing |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(1)) |
| }) |
| }) |
| |
| Context("via v2 api", func() { |
| var n NetConf |
| BeforeEach(func() { |
| n = NetConf{ApiVersion: 2} |
| }) |
| |
| It("append different IP", func() { |
| // mock different IP |
| n.ApplyDefaultPAPolicy("192.168.0.1") |
| n.ApplyDefaultPAPolicy("192.168.0.2") |
| |
| // will be two policies |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(2)) |
| |
| // normal type judgement |
| policy := addlArgs[1] // judge second item |
| 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("ProviderAddress")) |
| Expect(value).Should(HaveKey("Settings")) |
| |
| // compare with second item |
| settings := value["Settings"].(map[string]interface{}) |
| paAddress := settings["ProviderAddress"].(string) |
| Expect(paAddress).Should(Equal("192.168.0.2")) |
| }) |
| |
| It("nothing to do if IP is blank", func() { |
| // mock different policy |
| n.Policies = []Policy{ |
| { |
| Name: "EndpointPolicy", |
| Value: bprintf(`{"Type": "OutBoundNAT", "Settings": {"Exceptions": ["192.168.0.0/16"]}}`), |
| }, |
| } |
| n.ApplyDefaultPAPolicy("") |
| |
| // nothing |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(1)) |
| }) |
| }) |
| }) |
| |
| Describe("ApplyPortMappingPolicy", func() { |
| Context("via v1 api", func() { |
| var n NetConf |
| BeforeEach(func() { |
| n = NetConf{} |
| }) |
| |
| It("nothing to do if input is empty", func() { |
| n.ApplyPortMappingPolicy(nil) |
| Expect(n.Policies).Should(BeNil()) |
| |
| n.ApplyPortMappingPolicy([]PortMapEntry{}) |
| Expect(n.Policies).Should(BeNil()) |
| }) |
| |
| It("create one NAT policy", func() { |
| // mock different IP |
| n.ApplyPortMappingPolicy([]PortMapEntry{ |
| { |
| ContainerPort: 80, |
| HostPort: 8080, |
| Protocol: "TCP", |
| HostIP: "192.168.1.2", |
| }, |
| }) |
| |
| // only one item |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(1)) |
| |
| // normal type judgement |
| policy := addlArgs[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")) |
| |
| // compare all values |
| 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")) |
| }) |
| }) |
| |
| Context("via v2 api", func() { |
| var n NetConf |
| BeforeEach(func() { |
| n = NetConf{ApiVersion: 2} |
| }) |
| |
| It("nothing to do if input is empty", func() { |
| n.ApplyPortMappingPolicy(nil) |
| Expect(n.Policies).Should(BeNil()) |
| |
| n.ApplyPortMappingPolicy([]PortMapEntry{}) |
| Expect(n.Policies).Should(BeNil()) |
| }) |
| |
| It("creates one NAT policy", func() { |
| // mock different IP |
| n.ApplyPortMappingPolicy([]PortMapEntry{ |
| { |
| ContainerPort: 80, |
| HostPort: 8080, |
| Protocol: "TCP", |
| HostIP: "192.168.1.2", |
| }, |
| }) |
| |
| // only one item |
| addlArgs := n.Policies |
| Expect(addlArgs).Should(HaveLen(1)) |
| |
| // normal type judgement |
| policy := addlArgs[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("PortMapping")) |
| Expect(value).Should(HaveKey("Settings")) |
| |
| // compare all values |
| settings := value["Settings"].(map[string]interface{}) |
| Expect(settings).Should(HaveKey("InternalPort")) |
| Expect(settings["InternalPort"]).Should(Equal(float64(80))) |
| Expect(settings).Should(HaveKey("ExternalPort")) |
| Expect(settings["ExternalPort"]).Should(Equal(float64(8080))) |
| Expect(settings).Should(HaveKey("Protocol")) |
| Expect(settings["Protocol"]).Should(Equal(float64(6))) |
| Expect(settings).Should(HaveKey("VIP")) |
| Expect(settings["VIP"]).Should(Equal("192.168.1.2")) |
| }) |
| }) |
| }) |
| |
| Describe("GetXEndpointPolicies", func() { |
| Context("via v1 api", func() { |
| var n NetConf |
| BeforeEach(func() { |
| n = NetConf{} |
| }) |
| |
| It("GetHNSEndpointPolicies", func() { |
| // mock different policies |
| n.Policies = []Policy{ |
| { |
| Name: "EndpointPolicy", |
| Value: []byte(`{"Type": "OutBoundNAT", "ExceptionList": [ "192.168.1.2" ]}`), |
| }, |
| { |
| Name: "someOtherType", |
| Value: []byte(`{"someOtherKey": "someOtherValue"}`), |
| }, |
| } |
| |
| // only one valid item |
| result := n.GetHNSEndpointPolicies() |
| Expect(len(result)).To(Equal(1)) |
| |
| // normal type judgement |
| policy := make(map[string]interface{}) |
| err := json.Unmarshal(result[0], &policy) |
| Expect(err).ToNot(HaveOccurred()) |
| Expect(policy).Should(HaveKey("Type")) |
| Expect(policy["Type"]).To(Equal("OutBoundNAT")) |
| Expect(policy).Should(HaveKey("ExceptionList")) |
| Expect(policy["ExceptionList"]).To(ContainElement("192.168.1.2")) |
| }) |
| }) |
| |
| Context("via v2 api", func() { |
| var n NetConf |
| BeforeEach(func() { |
| n = NetConf{ApiVersion: 2} |
| }) |
| |
| It("GetHostComputeEndpointPolicies", func() { |
| // mock different policies |
| n.Policies = []Policy{ |
| { |
| Name: "EndpointPolicy", |
| Value: []byte(`{"Type": "OutBoundNAT", "Settings": {"Exceptions": [ "192.168.1.2" ]}}`), |
| }, |
| { |
| Name: "someOtherType", |
| Value: []byte(`{"someOtherKey": "someOtherValue"}`), |
| }, |
| } |
| |
| // only one valid item |
| result := n.GetHostComputeEndpointPolicies() |
| Expect(len(result)).To(Equal(1)) |
| |
| // normal type judgement |
| policy := result[0] |
| Expect(policy.Type).Should(Equal(hcn.OutBoundNAT)) |
| settings := make(map[string]interface{}) |
| err := json.Unmarshal(policy.Settings, &settings) |
| Expect(err).ToNot(HaveOccurred()) |
| Expect(settings["Exceptions"]).To(ContainElement("192.168.1.2")) |
| }) |
| }) |
| }) |
| }) |