11using System ;
22using System . Collections . Generic ;
33using System . IO ;
4+ using System . Linq ;
45using System . Reflection ;
6+ using System . Runtime . InteropServices ;
57using LocalStack . AwsLocal . AmbientContexts ;
68using LocalStack . AwsLocal . Contracts ;
79using LocalStack . AwsLocal . Extensions ;
10+ using LocalStack . AwsLocal . ProcessCore ;
11+ using LocalStack . AwsLocal . ProcessCore . IO ;
812using LocalStack . Client . Contracts ;
913using LocalStack . Client . Models ;
1014
@@ -14,18 +18,16 @@ public class CommandDispatcher
1418 {
1519 private const string UsageResource = "LocalStack.AwsLocal.Docs.Usage.txt" ;
1620
17- private readonly IProcessHelper _processHelper ;
21+ private readonly IProcessRunner _processRunner ;
1822 private readonly IConfig _config ;
23+ private readonly IFileSystem _fileSystem ;
1924 private readonly string [ ] _args ;
2025
21- private CommandDispatcher ( )
26+ public CommandDispatcher ( IProcessRunner processRunner , IConfig config , IFileSystem fileSystem , string [ ] args )
2227 {
23- }
24-
25- public CommandDispatcher ( IProcessHelper processHelper , IConfig config , string [ ] args )
26- {
27- _processHelper = processHelper ;
28+ _processRunner = processRunner ;
2829 _config = config ;
30+ _fileSystem = fileSystem ;
2931 _args = args ;
3032 }
3133
@@ -57,31 +59,113 @@ public void Run()
5759 return ;
5860 }
5961
60- string cliCommand = _args . GetCliCommand ( awsServiceEndpoint . ServiceUrl ) ;
62+ var processSettings = new ProcessSettings
63+ { NoWorkingDirectory = true , Silent = true , EnvironmentVariables = new Dictionary < string , string > ( ) } ;
64+ processSettings . EnvironmentVariables . Add ( "AWS_DEFAULT_REGION" , Environment . GetEnvironmentVariable ( "AWS_DEFAULT_REGION" ) ?? "us-east-1" ) ;
65+ processSettings . EnvironmentVariables . Add ( "AWS_ACCESS_KEY_ID" , Environment . GetEnvironmentVariable ( "AWS_ACCESS_KEY_ID" ) ?? "_not_needed_locally_" ) ;
66+ processSettings . EnvironmentVariables . Add ( "AWS_SECRET_ACCESS_KEY" , Environment . GetEnvironmentVariable ( "AWS_SECRET_ACCESS_KEY" ) ?? "_not_needed_locally_" ) ;
67+
68+
69+ var builder = new ProcessArgumentBuilder ( ) ;
70+ builder . Append ( _args [ 0 ] ) ;
71+ builder . AppendSwitch ( "--endpoint-url" , "=" , awsServiceEndpoint . ServiceUrl ) ;
72+
73+ if ( awsServiceEndpoint . ServiceUrl . StartsWith ( "https" ) )
74+ {
75+ builder . Append ( "--no-verify-ssl" ) ;
76+ }
77+
78+ var passToNextArgument = false ;
79+ for ( var i = 0 ; i < _args . Length ; i ++ )
80+ {
81+ string argument = _args [ i ] ;
82+
83+ if ( argument == _args [ 0 ] )
84+ {
85+ continue ;
86+ }
87+
88+ if ( passToNextArgument )
89+ {
90+ passToNextArgument = false ;
91+ continue ;
92+ }
93+
94+
95+ if ( argument . StartsWith ( "--" ) && ! argument . Contains ( "=" ) && i + 1 < _args . Length ) // switch argument
96+ {
97+ string nextArgument = _args [ i + 1 ] ;
98+ builder . AppendSwitchQuoted ( argument , " " , nextArgument ) ;
99+
100+ passToNextArgument = true ;
101+ continue ;
102+ }
103+
104+ builder . Append ( argument ) ;
105+ }
106+
61107
62- string awsDefaultRegion = Environment . GetEnvironmentVariable ( "AWS_DEFAULT_REGION" ) ?? "us-east-1" ;
63- string awsAccessKeyId = Environment . GetEnvironmentVariable ( "AWS_ACCESS_KEY_ID" ) ?? "_not_needed_locally_" ;
64- string awsSecretAccessKey = Environment . GetEnvironmentVariable ( "AWS_SECRET_ACCESS_KEY" ) ?? "_not_needed_locally_" ;
108+ processSettings . Arguments = builder ;
65109
66- _processHelper . CmdExecute ( cliCommand , null , true , true , new Dictionary < string , string >
110+ string awsExec = RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ? "aws.cmd" : "aws" ;
111+ FilePath ? awsPath = GetAwsPath ( awsExec ) ;
112+
113+ if ( awsPath == null )
67114 {
68- { "AWS_DEFAULT_REGION" , awsDefaultRegion } ,
69- { "AWS_ACCESS_KEY_ID" , awsAccessKeyId } ,
70- { "AWS_SECRET_ACCESS_KEY" , awsSecretAccessKey }
71- } ) ;
115+ ConsoleContext . Current . WriteLine ( $ "ERROR: Unable to find aws cli") ;
116+ EnvironmentContext . Current . Exit ( 1 ) ;
117+ return ;
118+ }
119+
120+ IProcess ? process = _processRunner . Start ( awsPath , processSettings ) ;
121+
122+ process ? . WaitForExit ( ) ;
72123 }
73124
74125 private static string GetUsageInfo ( )
75126 {
76- using ( Stream stream = Assembly . GetCallingAssembly ( ) . GetManifestResourceStream ( UsageResource ) )
127+ using Stream ? stream = Assembly . GetCallingAssembly ( ) . GetManifestResourceStream ( UsageResource ) ;
128+ using var reader = new StreamReader ( stream ?? throw new NullReferenceException ( nameof ( stream ) ) ) ;
129+ string result = reader . ReadToEnd ( ) ;
130+
131+ return result ;
132+ }
133+
134+ private FilePath ? GetAwsPath ( params string [ ] awsPaths )
135+ {
136+ string [ ] ? pathDirs = null ;
137+
138+ // Look for each possible executable name in various places.
139+ foreach ( string toolExeName in awsPaths )
77140 {
78- using ( var reader = new StreamReader ( stream ) )
141+
142+ // Cache the PATH directory list if we didn't already.
143+ if ( pathDirs == null )
79144 {
80- string result = reader . ReadToEnd ( ) ;
145+ string ? pathEnv = Environment . GetEnvironmentVariable ( "PATH" ) ;
146+ if ( ! string . IsNullOrEmpty ( pathEnv ) )
147+ {
148+ pathDirs = pathEnv . Split ( new [ ] { ! RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ? ':' : ';' } ,
149+ StringSplitOptions . RemoveEmptyEntries ) ;
150+ }
151+ else
152+ {
153+ pathDirs = new string [ ] { } ;
154+ }
155+ }
81156
82- return result ;
157+ // Look in every PATH directory for the file.
158+ foreach ( var pathDir in pathDirs )
159+ {
160+ FilePath file = new DirectoryPath ( pathDir ) . CombineWithFilePath ( toolExeName ) ;
161+ if ( _fileSystem . Exist ( file ) )
162+ {
163+ return file . FullPath ;
164+ }
83165 }
84166 }
167+
168+ return null ;
85169 }
86170 }
87171}
0 commit comments