diff --git a/ecs-agent/netlib/model/tasknetworkconfig/network_namespace.go b/ecs-agent/netlib/model/tasknetworkconfig/network_namespace.go index a61a24d7e69..e971e208778 100644 --- a/ecs-agent/netlib/model/tasknetworkconfig/network_namespace.go +++ b/ecs-agent/netlib/model/tasknetworkconfig/network_namespace.go @@ -87,3 +87,14 @@ func (ns *NetworkNamespace) GetPrimaryInterface() *networkinterface.NetworkInter func (ns *NetworkNamespace) IsPrimary() bool { return ns.Index == 0 } + +// GetInterfaceByIndex returns the interface in the netns that has the specified index. +func (ns *NetworkNamespace) GetInterfaceByIndex(idx int64) *networkinterface.NetworkInterface { + for _, iface := range ns.NetworkInterfaces { + if iface.Index == idx { + return iface + } + } + + return nil +} diff --git a/ecs-agent/netlib/model/tasknetworkconfig/task_network_config.go b/ecs-agent/netlib/model/tasknetworkconfig/task_network_config.go index 1dec3d76452..31bdb0a10bb 100644 --- a/ecs-agent/netlib/model/tasknetworkconfig/task_network_config.go +++ b/ecs-agent/netlib/model/tasknetworkconfig/task_network_config.go @@ -73,3 +73,17 @@ func (tnc *TaskNetworkConfig) GetEniNamesToAssociationProtocolMapping() map[stri } return eniNameToAssociationProtocol } + +// GetInterfaceNamesToNetNSMapping returns a map where key is interface name and value is the netns +// in which the interface exists. +func (tnc *TaskNetworkConfig) GetInterfaceNamesToNetNSMapping() map[string]*NetworkNamespace { + name2NetNS := make(map[string]*NetworkNamespace) + for _, netNS := range tnc.NetworkNamespaces { + for _, iface := range netNS.NetworkInterfaces { + if iface.Name != "" { + name2NetNS[iface.Name] = netNS + } + } + } + return name2NetNS +} diff --git a/ecs-agent/netlib/model/tasknetworkconfig/task_network_config_test.go b/ecs-agent/netlib/model/tasknetworkconfig/task_network_config_test.go index 6ebdb7cfadc..72d75a23705 100644 --- a/ecs-agent/netlib/model/tasknetworkconfig/task_network_config_test.go +++ b/ecs-agent/netlib/model/tasknetworkconfig/task_network_config_test.go @@ -18,8 +18,12 @@ package tasknetworkconfig import ( "github.com/aws/amazon-ecs-agent/ecs-agent/api/ecs/model/ecs" + ni "github.com/aws/amazon-ecs-agent/ecs-agent/netlib/model/networkinterface" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "fmt" "testing" ) @@ -79,3 +83,29 @@ func TestNewTaskNetConfig(t *testing.T) { assert.Equal(t, *netNSs[0], *taskNetConfig.NetworkNamespaces[0]) assert.Equal(t, *netNSs[1], *taskNetConfig.NetworkNamespaces[1]) } + +// TestTaskNetworkConfig_GetInterfaceNamesToNetNSMapping verifies the map created +// between interface name and netNS is accurate. +func TestTaskNetworkConfig_GetInterfaceNamesToNetNSMapping(t *testing.T) { + var netNSs []*NetworkNamespace + for i := 0; i < 3; i++ { + netNSs = append(netNSs, &NetworkNamespace{ + Name: fmt.Sprintf("ns%d", i), + NetworkInterfaces: []*ni.NetworkInterface{ + { + Name: fmt.Sprintf("ni%d", i), + }, + }, + }) + } + + netConfig := &TaskNetworkConfig{ + NetworkNamespaces: netNSs, + } + + name2NetNS := netConfig.GetInterfaceNamesToNetNSMapping() + require.Equal(t, 3, len(name2NetNS)) + for i := 0; i < 3; i++ { + require.Equal(t, name2NetNS[fmt.Sprintf("ni%d", i)].Name, fmt.Sprintf("ns%d", i)) + } +} diff --git a/ecs-agent/netlib/platform/common_linux.go b/ecs-agent/netlib/platform/common_linux.go index fa0d758eb85..661ea1c5686 100644 --- a/ecs-agent/netlib/platform/common_linux.go +++ b/ecs-agent/netlib/platform/common_linux.go @@ -113,6 +113,18 @@ func NewPlatform( return &firecraker{ common: commonPlatform, }, nil + case WarmpoolDebugPlatform: + return &containerdDebug{ + containerd: containerd{ + common: commonPlatform, + }, + }, nil + case FirecrackerDebugPlatform: + return &firecrackerDebug{ + firecraker: firecraker{ + common: commonPlatform, + }, + }, nil } return nil, errors.New("invalid platform: " + platformString) } @@ -494,7 +506,7 @@ func (c *common) generateNetworkConfigFilesForDebugPlatforms( return nil } -func (c *common) copyFile(src, dst string, fileMode os.FileMode) error { +func (c *common) copyFile(dst, src string, fileMode os.FileMode) error { contents, err := c.ioutil.ReadFile(src) if err != nil { return errors.Wrapf(err, "unable to read %s", src) diff --git a/ecs-agent/netlib/platform/containerd_debug_linux.go b/ecs-agent/netlib/platform/containerd_debug_linux.go new file mode 100644 index 00000000000..7f348f77e96 --- /dev/null +++ b/ecs-agent/netlib/platform/containerd_debug_linux.go @@ -0,0 +1,14 @@ +package platform + +import ( + "github.com/aws/amazon-ecs-agent/ecs-agent/netlib/model/tasknetworkconfig" +) + +// containerdDebug implements platform API methods for non-firecrakcer infrastructure. +type containerdDebug struct { + containerd +} + +func (c *containerdDebug) CreateDNSConfig(taskID string, netNS *tasknetworkconfig.NetworkNamespace) error { + return c.common.createDNSConfig(taskID, true, netNS) +} diff --git a/ecs-agent/netlib/platform/firecracker_debug_linux.go b/ecs-agent/netlib/platform/firecracker_debug_linux.go new file mode 100644 index 00000000000..1f1f3588d3c --- /dev/null +++ b/ecs-agent/netlib/platform/firecracker_debug_linux.go @@ -0,0 +1,11 @@ +package platform + +import "github.com/aws/amazon-ecs-agent/ecs-agent/netlib/model/tasknetworkconfig" + +type firecrackerDebug struct { + firecraker +} + +func (fc *firecrackerDebug) CreateDNSConfig(taskID string, netNS *tasknetworkconfig.NetworkNamespace) error { + return fc.common.createDNSConfig(taskID, true, netNS) +}