@@ -74,6 +74,7 @@ def main():
7474 import awscli .clidriver # noqa: F401
7575 except Exception :
7676 return run_as_separate_process ()
77+ patch_awscli_libs ()
7778 run_in_process ()
7879
7980
@@ -139,5 +140,64 @@ def run_in_process():
139140 sys .exit (awscli .clidriver .main ())
140141
141142
143+ def patch_awscli_libs ():
144+ # TODO: Temporary fix until this PR is merged: https://github.com/aws/aws-cli/pull/3309
145+
146+ import inspect
147+ from awscli import paramfile
148+ from awscli .customizations .cloudformation import deploy , package
149+
150+ # add parameter definitions
151+ paramfile .PARAMFILE_DISABLED .add ('custom.package.s3-endpoint-url' )
152+ paramfile .PARAMFILE_DISABLED .add ('custom.deploy.s3-endpoint-url' )
153+ s3_endpoint_arg = {
154+ 'name' : 's3-endpoint-url' ,
155+ 'help_text' : (
156+ 'URL of storage service where packaged templates and artifacts'
157+ ' will be uploaded. Useful for testing and local development'
158+ ' or when uploading to a non-AWS storage service that is'
159+ ' nonetheless S3-compatible.'
160+ )
161+ }
162+
163+ # add argument definition for S3 endpoint to use for CF package/deploy
164+ for arg_table in [deploy .DeployCommand .ARG_TABLE , package .PackageCommand .ARG_TABLE ]:
165+ existing = [a for a in arg_table if a .get ('name' ) == 's3-endpoint-url' ]
166+ if not existing :
167+ arg_table .append (s3_endpoint_arg )
168+
169+
170+ def wrap_create_client (_init_orig ):
171+ """ Returns a new constructor that wraps the S3 client creation to use the custom endpoint for CF. """
172+
173+ def new_init (self , session , * args , ** kwargs ):
174+ def create_client (* args , ** kwargs ):
175+ if args and args [0 ] == 's3' :
176+ # get stack frame of caller
177+ curframe = inspect .currentframe ()
178+ calframe = inspect .getouterframes (curframe , 2 )
179+ fname = calframe [1 ].filename
180+
181+ # check if we are executing within the target method
182+ is_target = (os .path .join ('cloudformation' , 'deploy.py' ) in fname or
183+ os .path .join ('cloudformation' , 'package.py' ) in fname )
184+ if is_target :
185+ if 'endpoint_url' not in kwargs :
186+ args_passed = inspect .getargvalues (calframe [1 ].frame ).locals
187+ kwargs ['endpoint_url' ] = args_passed ['parsed_args' ].s3_endpoint_url
188+ return create_client_orig (* args , ** kwargs )
189+
190+ if not hasattr (session , '_s3_endpoint_patch_applied' ):
191+ create_client_orig = session .create_client
192+ session .create_client = create_client
193+ session ._s3_endpoint_patch_applied = True
194+ _init_orig (self , session , * args , ** kwargs )
195+
196+ return new_init
197+
198+ deploy .DeployCommand .__init__ = wrap_create_client (deploy .DeployCommand .__init__ )
199+ package .PackageCommand .__init__ = wrap_create_client (package .PackageCommand .__init__ )
200+
201+
142202if __name__ == '__main__' :
143203 main ()
0 commit comments