diff --git a/depot/containerstore/containerstore_test.go b/depot/containerstore/containerstore_test.go index fde81994..190aa9dd 100644 --- a/depot/containerstore/containerstore_test.go +++ b/depot/containerstore/containerstore_test.go @@ -994,6 +994,14 @@ var _ = Describe("Container Store", func() { Code: 10, }, }, + { + Protocol: "icmpv6", + Destinations: []string{"2100::1"}, + IcmpInfo: &models.ICMPInfo{ + Type: 1, + Code: 10, + }, + }, } runReq.EgressRules = egressRules }) @@ -1004,7 +1012,7 @@ var _ = Describe("Container Store", func() { Expect(gardenClient.CreateCallCount()).To(Equal(1)) containerSpec := gardenClient.CreateArgsForCall(0) - Expect(containerSpec.NetOut).To(HaveLen(2)) + Expect(containerSpec.NetOut).To(HaveLen(3)) icmpCode := garden.ICMPCode(10) Expect(containerSpec.NetOut).To(ContainElement(garden.NetOutRule{ Protocol: garden.Protocol(3), @@ -1032,6 +1040,19 @@ var _ = Describe("Container Store", func() { Code: &icmpCode, }, })) + Expect(containerSpec.NetOut).To(ContainElement(garden.NetOutRule{ + Protocol: garden.Protocol(4), + Networks: []garden.IPRange{ + { + Start: net.ParseIP("2100::1"), + End: net.ParseIP("2100::1"), + }, + }, + ICMPs: &garden.ICMPControl{ + Type: 1, + Code: &icmpCode, + }, + })) }) Context("when a destination is a comma-delimited list", func() { @@ -1045,6 +1066,14 @@ var _ = Describe("Container Store", func() { Code: 17, }, }, + { + Protocol: "icmpv6", + Destinations: []string{"2100::1,2100::2"}, + IcmpInfo: &models.ICMPInfo{ + Type: 3, + Code: 17, + }, + }, } runReq.EgressRules = egressRules }) @@ -1055,7 +1084,7 @@ var _ = Describe("Container Store", func() { Expect(gardenClient.CreateCallCount()).To(Equal(1)) containerSpec := gardenClient.CreateArgsForCall(0) - Expect(containerSpec.NetOut).To(HaveLen(2)) + Expect(containerSpec.NetOut).To(HaveLen(4)) icmpCode := garden.ICMPCode(17) Expect(containerSpec.NetOut).To(ContainElement(garden.NetOutRule{ Protocol: garden.Protocol(3), @@ -1083,6 +1112,32 @@ var _ = Describe("Container Store", func() { Code: &icmpCode, }, })) + Expect(containerSpec.NetOut).To(ContainElement(garden.NetOutRule{ + Protocol: garden.Protocol(4), + Networks: []garden.IPRange{ + { + Start: net.ParseIP("2100::1"), + End: net.ParseIP("2100::1"), + }, + }, + ICMPs: &garden.ICMPControl{ + Type: 3, + Code: &icmpCode, + }, + })) + Expect(containerSpec.NetOut).To(ContainElement(garden.NetOutRule{ + Protocol: garden.Protocol(4), + Networks: []garden.IPRange{ + { + Start: net.ParseIP("2100::2"), + End: net.ParseIP("2100::2"), + }, + }, + ICMPs: &garden.ICMPControl{ + Type: 3, + Code: &icmpCode, + }, + })) }) }) diff --git a/depot/containerstore/helpers.go b/depot/containerstore/helpers.go index f66c8108..72d8a3ea 100644 --- a/depot/containerstore/helpers.go +++ b/depot/containerstore/helpers.go @@ -66,6 +66,13 @@ func securityGroupRuleToNetOutRules(securityRule *models.SecurityGroupRule) ([]g Type: garden.ICMPType(securityRule.IcmpInfo.Type), Code: garden.ICMPControlCode(uint8(securityRule.IcmpInfo.Code)), } + case models.ICMPv6Protocol: + protocol = garden.ProtocolICMPv6 + // Can reuse icmp because the fields are the same + icmp = &garden.ICMPControl{ + Type: garden.ICMPType(securityRule.IcmpInfo.Type), + Code: garden.ICMPControlCode(uint8(securityRule.IcmpInfo.Code)), + } case models.AllProtocol: protocol = garden.ProtocolAll } diff --git a/depot/containerstore/storenode.go b/depot/containerstore/storenode.go index 4607999d..7e027890 100644 --- a/depot/containerstore/storenode.go +++ b/depot/containerstore/storenode.go @@ -459,8 +459,11 @@ func (n *storeNode) createGardenContainer(logger lager.Logger, traceID string, i info.Ports = n.portMappingFromContainerInfo(containerInfo, info.Ports, proxyPortMapping) info.ExternalIP = containerInfo.ExternalIP info.InternalIP = containerInfo.ContainerIP + info.InternalIPv6 = containerInfo.ContainerIPv6 info.AdvertisePreferenceForInstanceAddress = n.advertisePreferenceForInstanceAddress + logger.Debug("container-created", lager.Data{"info": info}) + info.MemoryLimit = containerSpec.Limits.Memory.LimitInBytes info.DiskLimit = containerSpec.Limits.Disk.ByteHard diff --git a/depot/steps/run_step.go b/depot/steps/run_step.go index e99d0bb5..1fd915c4 100644 --- a/depot/steps/run_step.go +++ b/depot/steps/run_step.go @@ -25,6 +25,7 @@ type runStep struct { logger lager.Logger externalIP string internalIP string + internalIPv6 string portMappings []executor.PortMapping clock clock.Clock gracefulShutdownInterval time.Duration @@ -46,6 +47,7 @@ func NewRun( logger lager.Logger, externalIP string, internalIP string, + internalIPv6 string, portMappings []executor.PortMapping, clock clock.Clock, gracefulShutdownInterval time.Duration, @@ -58,6 +60,7 @@ func NewRun( logger, externalIP, internalIP, + internalIPv6, portMappings, clock, gracefulShutdownInterval, @@ -74,6 +77,7 @@ func NewRunWithSidecar( logger lager.Logger, externalIP string, internalIP string, + internalIPv6 string, portMappings []executor.PortMapping, clock clock.Clock, gracefulShutdownInterval time.Duration, @@ -89,6 +93,7 @@ func NewRunWithSidecar( logger: logger, externalIP: externalIP, internalIP: internalIP, + internalIPv6: internalIPv6, portMappings: portMappings, clock: clock, gracefulShutdownInterval: gracefulShutdownInterval, @@ -309,6 +314,10 @@ func (step *runStep) networkingEnvVars() []string { envVars = append(envVars, "CF_INSTANCE_IP="+step.externalIP) envVars = append(envVars, "CF_INSTANCE_INTERNAL_IP="+step.internalIP) + if len(step.internalIPv6) != 0 { + envVars = append(envVars, "CF_INSTANCE_INTERNAL_IPV6="+step.internalIPv6) + } + if len(step.portMappings) > 0 { if step.portMappings[0].HostPort > 0 { envVars = append(envVars, fmt.Sprintf("CF_INSTANCE_PORT=%d", step.portMappings[0].HostPort)) diff --git a/depot/steps/run_step_test.go b/depot/steps/run_step_test.go index a2fc1587..8eed5b9d 100644 --- a/depot/steps/run_step_test.go +++ b/depot/steps/run_step_test.go @@ -27,15 +27,15 @@ var _ = Describe("RunAction", func() { var ( step ifrit.Runner - runAction models.RunAction - fakeStreamer *fake_log_streamer.FakeLogStreamer - gardenClient *fakes.FakeGardenClient - logger *lagertest.TestLogger - fileDescriptorLimit, processesLimit uint64 - externalIP, internalIP string - portMappings []executor.PortMapping - fakeClock *fakeclock.FakeClock - suppressExitStatusCode bool + runAction models.RunAction + fakeStreamer *fake_log_streamer.FakeLogStreamer + gardenClient *fakes.FakeGardenClient + logger *lagertest.TestLogger + fileDescriptorLimit, processesLimit uint64 + externalIP, internalIP, internalIPv6 string + portMappings []executor.PortMapping + fakeClock *fakeclock.FakeClock + suppressExitStatusCode bool spawnedProcess *gardenfakes.FakeProcess runError error @@ -85,6 +85,7 @@ var _ = Describe("RunAction", func() { externalIP = "external-ip" internalIP = "internal-ip" + internalIPv6 = "internal-ipv6" portMappings = nil fakeClock = fakeclock.NewFakeClock(time.Unix(123, 456)) }) @@ -104,6 +105,7 @@ var _ = Describe("RunAction", func() { logger, externalIP, internalIP, + internalIPv6, portMappings, fakeClock, gracefulShutdownInterval, @@ -298,9 +300,21 @@ var _ = Describe("RunAction", func() { Expect(spec.Env).To(ContainElement("CF_INSTANCE_IP=external-ip")) }) - It("sets CF_INSTANCE_INTERNAL_IP on the container", func() { + It("sets CF_INSTANCE_INTERNAL_IP and CF_INSTANCE_INTERNAL_IPV6 on the container", func() { _, spec, _ := gardenClient.Connection.RunArgsForCall(0) Expect(spec.Env).To(ContainElement("CF_INSTANCE_INTERNAL_IP=internal-ip")) + Expect(spec.Env).To(ContainElement("CF_INSTANCE_INTERNAL_IPV6=internal-ipv6")) + }) + + Context("when the container has no internal IPv6", func() { + BeforeEach(func() { + internalIPv6 = "" + }) + + It("does not set CF_INSTANCE_INTERNAL_IPV6 on the container", func() { + _, spec, _ := gardenClient.Connection.RunArgsForCall(0) + Expect(spec.Env).NotTo(ContainElement("CF_INSTANCE_INTERNAL_IPV6=")) + }) }) Context("when the container has port mappings configured", func() { diff --git a/depot/transformer/transformer.go b/depot/transformer/transformer.go index 366f4fe1..18073a20 100644 --- a/depot/transformer/transformer.go +++ b/depot/transformer/transformer.go @@ -162,6 +162,7 @@ func (t *transformer) stepFor( container garden.Container, externalIP string, internalIP string, + internalIPv6 string, ports []executor.PortMapping, suppressExitStatusCode bool, monitorOutputWrapper bool, @@ -177,6 +178,7 @@ func (t *transformer) stepFor( logger, externalIP, internalIP, + internalIPv6, ports, t.clock, t.gracefulShutdownInterval, @@ -212,6 +214,7 @@ func (t *transformer) stepFor( container, externalIP, internalIP, + internalIPv6, ports, suppressExitStatusCode, monitorOutputWrapper, @@ -232,6 +235,7 @@ func (t *transformer) stepFor( container, externalIP, internalIP, + internalIPv6, ports, suppressExitStatusCode, monitorOutputWrapper, @@ -250,6 +254,7 @@ func (t *transformer) stepFor( container, externalIP, internalIP, + internalIPv6, ports, suppressExitStatusCode, monitorOutputWrapper, @@ -271,6 +276,7 @@ func (t *transformer) stepFor( container, externalIP, internalIP, + internalIPv6, ports, suppressExitStatusCode, monitorOutputWrapper, @@ -285,6 +291,7 @@ func (t *transformer) stepFor( container, externalIP, internalIP, + internalIPv6, ports, suppressExitStatusCode, monitorOutputWrapper, @@ -308,6 +315,7 @@ func (t *transformer) stepFor( container, externalIP, internalIP, + internalIPv6, ports, suppressExitStatusCode, monitorOutputWrapper, @@ -322,6 +330,7 @@ func (t *transformer) stepFor( container, externalIP, internalIP, + internalIPv6, ports, suppressExitStatusCode, monitorOutputWrapper, @@ -342,6 +351,7 @@ func (t *transformer) stepFor( container, externalIP, internalIP, + internalIPv6, ports, suppressExitStatusCode, monitorOutputWrapper, @@ -377,6 +387,7 @@ func overrideSuppressLogOutput(monitorAction *models.Action) { overrideSuppressLogOutput(monitorAction.TimeoutAction.Action) } } + func (t *transformer) StepsRunner( logger lager.Logger, container executor.Container, @@ -394,6 +405,7 @@ func (t *transformer) StepsRunner( gardenContainer, container.ExternalIP, container.InternalIP, + container.InternalIPv6, container.Ports, false, false, @@ -416,6 +428,7 @@ func (t *transformer) StepsRunner( logger.Session("post-setup"), container.ExternalIP, container.InternalIP, + container.InternalIPv6, container.Ports, t.clock, t.gracefulShutdownInterval, @@ -435,6 +448,7 @@ func (t *transformer) StepsRunner( gardenContainer, container.ExternalIP, container.InternalIP, + container.InternalIPv6, container.Ports, false, false, @@ -449,6 +463,7 @@ func (t *transformer) StepsRunner( gardenContainer, container.ExternalIP, container.InternalIP, + container.InternalIPv6, container.Ports, false, false, @@ -550,6 +565,7 @@ func (t *transformer) StepsRunner( gardenContainer, container.ExternalIP, container.InternalIP, + container.InternalIPv6, container.Ports, true, true, @@ -672,6 +688,7 @@ func (t *transformer) createCheck( logger, container.ExternalIP, container.InternalIP, + container.InternalIPv6, container.Ports, t.clock, t.gracefulShutdownInterval, @@ -1002,6 +1019,7 @@ func (t *transformer) transformContainerProxyStep( proxyLogger, execContainer.ExternalIP, execContainer.InternalIP, + execContainer.InternalIPv6, execContainer.Ports, t.clock, t.gracefulShutdownInterval, diff --git a/depot/transformer/transformer_test.go b/depot/transformer/transformer_test.go index fa6abd61..e4013912 100644 --- a/depot/transformer/transformer_test.go +++ b/depot/transformer/transformer_test.go @@ -333,8 +333,9 @@ var _ = Describe("Transformer", func() { } container = executor.Container{ - ExternalIP: "10.0.0.1", - InternalIP: "11.0.0.1", + ExternalIP: "10.0.0.1", + InternalIP: "11.0.0.1", + InternalIPv6: "2000::1", RunInfo: executor.RunInfo{ Action: &models.Action{ RunAction: &models.RunAction{ @@ -417,6 +418,7 @@ var _ = Describe("Transformer", func() { Env: []string{ "CF_INSTANCE_IP=10.0.0.1", "CF_INSTANCE_INTERNAL_IP=11.0.0.1", + "CF_INSTANCE_INTERNAL_IPV6=2000::1", "CF_INSTANCE_PORT=61001", "CF_INSTANCE_ADDR=10.0.0.1:61001", "CF_INSTANCE_PORTS=[{\"external\":61001,\"internal\":8080},{\"external\":61002,\"internal\":61001}]", @@ -500,6 +502,7 @@ var _ = Describe("Transformer", func() { Env: []string{ "CF_INSTANCE_IP=10.0.0.1", "CF_INSTANCE_INTERNAL_IP=11.0.0.1", + "CF_INSTANCE_INTERNAL_IPV6=2000::1", "CF_INSTANCE_PORT=61001", "CF_INSTANCE_ADDR=10.0.0.1:61001", "CF_INSTANCE_PORTS=[{\"external\":61001,\"internal\":8080},{\"external\":61002,\"internal\":61001}]", diff --git a/resources.go b/resources.go index 9f4e8ab3..f28a0353 100644 --- a/resources.go +++ b/resources.go @@ -46,6 +46,7 @@ type Container struct { AllocatedAt int64 `json:"allocated_at"` ExternalIP string `json:"external_ip"` InternalIP string `json:"internal_ip"` + InternalIPv6 string `json:"internal_ip_v6,omitempty"` RunResult ContainerRunResult `json:"run_result"` MemoryLimit uint64 `json:"memory_limit"` DiskLimit uint64 `json:"disk_limit"`