@@ -19,9 +19,12 @@ package app
19
19
import (
20
20
"context"
21
21
"errors"
22
+ "fmt"
23
+ "net"
22
24
"os"
23
25
"os/exec"
24
26
"path/filepath"
27
+ "strings"
25
28
"testing"
26
29
27
30
app_mocks "github.com/aws/amazon-ecs-agent/agent/app/mocks"
@@ -40,12 +43,36 @@ import (
40
43
mock_mobypkgwrapper "github.com/aws/amazon-ecs-agent/agent/utils/mobypkgwrapper/mocks"
41
44
"github.com/aws/amazon-ecs-agent/ecs-agent/api/ecs/model/ecs"
42
45
md "github.com/aws/amazon-ecs-agent/ecs-agent/manageddaemon"
46
+ "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/utils/netconfig"
43
47
"github.com/aws/amazon-ecs-agent/ecs-agent/utils/execwrapper"
44
48
mock_execwrapper "github.com/aws/amazon-ecs-agent/ecs-agent/utils/execwrapper/mocks"
49
+ mock_netlinkwrapper "github.com/aws/amazon-ecs-agent/ecs-agent/utils/netlinkwrapper/mocks"
45
50
"github.com/aws/aws-sdk-go/aws"
46
51
aws_credentials "github.com/aws/aws-sdk-go/aws/credentials"
47
52
"github.com/golang/mock/gomock"
48
53
"github.com/stretchr/testify/assert"
54
+ "github.com/vishvananda/netlink"
55
+ )
56
+
57
+ const (
58
+ deviceName = "eth0"
59
+ internalError = "internal error"
60
+ )
61
+
62
+ var (
63
+ routes = []netlink.Route {
64
+ netlink.Route {
65
+ Gw : net .ParseIP ("10.194.20.1" ),
66
+ Dst : nil ,
67
+ LinkIndex : 0 ,
68
+ },
69
+ }
70
+ link = & netlink.Device {
71
+ LinkAttrs : netlink.LinkAttrs {
72
+ Index : 0 ,
73
+ Name : deviceName ,
74
+ },
75
+ }
49
76
)
50
77
51
78
func init () {
@@ -982,21 +1009,34 @@ func TestCheckFaultInjectionTooling(t *testing.T) {
982
1009
lookPathFunc = originalLookPath
983
1010
}()
984
1011
originalOSExecWrapper := execwrapper .NewExec ()
1012
+ originalNetConfig := netconfig .NewNetworkConfigClient ()
985
1013
defer func () {
986
1014
osExecWrapper = originalOSExecWrapper
1015
+ networkConfigClient = originalNetConfig
987
1016
}()
988
1017
989
1018
t .Run ("all tools and kernel modules available" , func (t * testing.T ) {
990
1019
lookPathFunc = func (file string ) (string , error ) {
991
- return "/usr/bin" + file , nil
1020
+ return "/usr/bin/ " + file , nil
992
1021
}
993
1022
ctrl := gomock .NewController (t )
994
1023
defer ctrl .Finish ()
995
1024
mockExec := mock_execwrapper .NewMockExec (ctrl )
996
1025
cmdExec := mock_execwrapper .NewMockCmd (ctrl )
1026
+ mock_netlinkwrapper := mock_netlinkwrapper .NewMockNetLink (ctrl )
1027
+ cmdList := convertToInterfaceList (strings .Split (fmt .Sprintf (tcShowCmdString , deviceName ), " " ))
1028
+
1029
+ gomock .InOrder (
1030
+ mock_netlinkwrapper .EXPECT ().RouteList (nil , netlink .FAMILY_ALL ).Return (routes , nil ).AnyTimes (),
1031
+ mock_netlinkwrapper .EXPECT ().LinkByIndex (link .Attrs ().Index ).Return (link , nil ).AnyTimes (),
1032
+ )
1033
+ networkConfigClient .NetlinkClient = mock_netlinkwrapper
997
1034
gomock .InOrder (
998
1035
mockExec .EXPECT ().CommandContext (gomock .Any (), modInfoCmd , faultInjectionKernelModules ).Times (1 ).Return (cmdExec ),
999
1036
cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte {}, nil ),
1037
+
1038
+ mockExec .EXPECT ().CommandContext (gomock .Any (), cmdList [0 ], cmdList [1 :]... ).Times (1 ).Return (cmdExec ),
1039
+ cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte {}, nil ),
1000
1040
)
1001
1041
osExecWrapper = mockExec
1002
1042
assert .True (t ,
@@ -1006,7 +1046,7 @@ func TestCheckFaultInjectionTooling(t *testing.T) {
1006
1046
1007
1047
t .Run ("missing kernel modules" , func (t * testing.T ) {
1008
1048
lookPathFunc = func (file string ) (string , error ) {
1009
- return "/usr/bin" + file , nil
1049
+ return "/usr/bin/ " + file , nil
1010
1050
}
1011
1051
ctrl := gomock .NewController (t )
1012
1052
defer ctrl .Finish ()
@@ -1022,18 +1062,79 @@ func TestCheckFaultInjectionTooling(t *testing.T) {
1022
1062
"Expected checkFaultInjectionTooling to return false when kernel modules are not available" )
1023
1063
})
1024
1064
1065
+ t .Run ("failed to obtain default host device name" , func (t * testing.T ) {
1066
+ lookPathFunc = func (file string ) (string , error ) {
1067
+ return "/usr/bin/" + file , nil
1068
+ }
1069
+ ctrl := gomock .NewController (t )
1070
+ defer ctrl .Finish ()
1071
+ mockExec := mock_execwrapper .NewMockExec (ctrl )
1072
+ cmdExec := mock_execwrapper .NewMockCmd (ctrl )
1073
+ mock_netlinkwrapper := mock_netlinkwrapper .NewMockNetLink (ctrl )
1074
+
1075
+ gomock .InOrder (
1076
+ mock_netlinkwrapper .EXPECT ().RouteList (nil , netlink .FAMILY_ALL ).Return (routes , errors .New (internalError )).AnyTimes (),
1077
+ )
1078
+ networkConfigClient .NetlinkClient = mock_netlinkwrapper
1079
+ gomock .InOrder (
1080
+ mockExec .EXPECT ().CommandContext (gomock .Any (), modInfoCmd , faultInjectionKernelModules ).Times (1 ).Return (cmdExec ),
1081
+ cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte {}, nil ),
1082
+ )
1083
+ osExecWrapper = mockExec
1084
+ assert .False (t ,
1085
+ checkFaultInjectionTooling (),
1086
+ "Expected checkFaultInjectionTooling to return false when unable to find default host interface name" )
1087
+ })
1088
+
1089
+ t .Run ("failed tc show command" , func (t * testing.T ) {
1090
+ lookPathFunc = func (file string ) (string , error ) {
1091
+ return "/usr/bin/" + file , nil
1092
+ }
1093
+ ctrl := gomock .NewController (t )
1094
+ defer ctrl .Finish ()
1095
+ mockExec := mock_execwrapper .NewMockExec (ctrl )
1096
+ cmdExec := mock_execwrapper .NewMockCmd (ctrl )
1097
+ mock_netlinkwrapper := mock_netlinkwrapper .NewMockNetLink (ctrl )
1098
+ cmdList := convertToInterfaceList (strings .Split (fmt .Sprintf (tcShowCmdString , deviceName ), " " ))
1099
+
1100
+ gomock .InOrder (
1101
+ mock_netlinkwrapper .EXPECT ().RouteList (nil , netlink .FAMILY_ALL ).Return (routes , nil ).AnyTimes (),
1102
+ mock_netlinkwrapper .EXPECT ().LinkByIndex (link .Attrs ().Index ).Return (link , nil ).AnyTimes (),
1103
+ )
1104
+ networkConfigClient .NetlinkClient = mock_netlinkwrapper
1105
+ gomock .InOrder (
1106
+ mockExec .EXPECT ().CommandContext (gomock .Any (), modInfoCmd , faultInjectionKernelModules ).Times (1 ).Return (cmdExec ),
1107
+ cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte {}, nil ),
1108
+
1109
+ mockExec .EXPECT ().CommandContext (gomock .Any (), cmdList [0 ], cmdList [1 :]... ).Times (1 ).Return (cmdExec ),
1110
+ cmdExec .EXPECT ().CombinedOutput ().Times (1 ).Return ([]byte {}, errors .New ("What is \" parent\" ? Try \" tc qdisc help\" ." )),
1111
+ )
1112
+ osExecWrapper = mockExec
1113
+ assert .False (t ,
1114
+ checkFaultInjectionTooling (),
1115
+ "Expected checkFaultInjectionTooling to return false when required tc show command failed" )
1116
+ })
1117
+
1025
1118
tools := []string {"iptables" , "tc" , "nsenter" }
1026
1119
for _ , tool := range tools {
1027
1120
t .Run (tool + " missing" , func (t * testing.T ) {
1028
1121
lookPathFunc = func (file string ) (string , error ) {
1029
1122
if file == tool {
1030
1123
return "" , exec .ErrNotFound
1031
1124
}
1032
- return "/usr/bin" + file , nil
1125
+ return "/usr/bin/ " + file , nil
1033
1126
}
1034
1127
assert .False (t ,
1035
1128
checkFaultInjectionTooling (),
1036
1129
"Expected checkFaultInjectionTooling to return false when a tool is missing" )
1037
1130
})
1038
1131
}
1039
1132
}
1133
+
1134
+ func convertToInterfaceList (strings []string ) []interface {} {
1135
+ interfaces := make ([]interface {}, len (strings ))
1136
+ for i , s := range strings {
1137
+ interfaces [i ] = s
1138
+ }
1139
+ return interfaces
1140
+ }
0 commit comments