@@ -205,7 +205,9 @@ class DataSinkInputSpec(DynamicTraitedSpec, BaseInterfaceInputSpec):
205
205
206
206
# AWS S3 data attributes
207
207
creds_path = traits .Str (desc = 'Filepath to AWS credentials file for S3 bucket ' \
208
- 'access' )
208
+ 'access; if not specified, the credentials will ' \
209
+ 'be taken from the AWS_ACCESS_KEY_ID and ' \
210
+ 'AWS_SECRET_ACCESS_KEY environment variables' )
209
211
encrypt_bucket_keys = traits .Bool (desc = 'Flag indicating whether to use S3 ' \
210
212
'server-side AES-256 encryption' )
211
213
# Set this if user wishes to override the bucket with their own
@@ -426,16 +428,15 @@ def _check_s3_base_dir(self):
426
428
return s3_flag
427
429
428
430
# Function to return AWS secure environment variables
429
- def _return_aws_keys (self , creds_path ):
431
+ def _return_aws_keys (self ):
430
432
'''
431
433
Method to return AWS access key id and secret access key using
432
434
credentials found in a local file.
433
435
434
436
Parameters
435
437
----------
436
- creds_path : string (filepath)
437
- path to the csv file downloaded from AWS; can either be root
438
- or user credentials
438
+ self : nipype.interfaces.io.DataSink
439
+ self for instance method
439
440
440
441
Returns
441
442
-------
@@ -445,28 +446,38 @@ def _return_aws_keys(self, creds_path):
445
446
string of the AWS secret access key
446
447
'''
447
448
449
+ # Import packages
450
+ import os
451
+
448
452
# Init variables
449
- with open (creds_path , 'r' ) as creds_in :
450
- # Grab csv rows
451
- row1 = creds_in .readline ()
452
- row2 = creds_in .readline ()
453
-
454
- # Are they root or user keys
455
- if 'User Name' in row1 :
456
- # And split out for keys
457
- aws_access_key_id = row2 .split (',' )[1 ]
458
- aws_secret_access_key = row2 .split (',' )[2 ]
459
- elif 'AWSAccessKeyId' in row1 :
460
- # And split out for keys
461
- aws_access_key_id = row1 .split ('=' )[1 ]
462
- aws_secret_access_key = row2 .split ('=' )[1 ]
463
- else :
464
- err_msg = 'Credentials file not recognized, check file is correct'
465
- raise Exception (err_msg )
453
+ creds_path = self .inputs .creds_path
454
+
455
+ # Check if creds exist
456
+ if creds_path and os .path .exists (creds_path ):
457
+ with open (creds_path , 'r' ) as creds_in :
458
+ # Grab csv rows
459
+ row1 = creds_in .readline ()
460
+ row2 = creds_in .readline ()
461
+
462
+ # Are they root or user keys
463
+ if 'User Name' in row1 :
464
+ # And split out for keys
465
+ aws_access_key_id = row2 .split (',' )[1 ]
466
+ aws_secret_access_key = row2 .split (',' )[2 ]
467
+ elif 'AWSAccessKeyId' in row1 :
468
+ # And split out for keys
469
+ aws_access_key_id = row1 .split ('=' )[1 ]
470
+ aws_secret_access_key = row2 .split ('=' )[1 ]
471
+ else :
472
+ err_msg = 'Credentials file not recognized, check file is correct'
473
+ raise Exception (err_msg )
466
474
467
- # Strip any carriage return/line feeds
468
- aws_access_key_id = aws_access_key_id .replace ('\r ' , '' ).replace ('\n ' , '' )
469
- aws_secret_access_key = aws_secret_access_key .replace ('\r ' , '' ).replace ('\n ' , '' )
475
+ # Strip any carriage return/line feeds
476
+ aws_access_key_id = aws_access_key_id .replace ('\r ' , '' ).replace ('\n ' , '' )
477
+ aws_secret_access_key = aws_secret_access_key .replace ('\r ' , '' ).replace ('\n ' , '' )
478
+ else :
479
+ aws_access_key_id = os .getenv ('AWS_ACCESS_KEY_ID' )
480
+ aws_secret_access_key = os .getenv ('AWS_SECRET_ACCESS_KEY' )
470
481
471
482
# Return keys
472
483
return aws_access_key_id , aws_secret_access_key
@@ -479,6 +490,8 @@ def _fetch_bucket(self, bucket_name):
479
490
480
491
Parameters
481
492
----------
493
+ self : nipype.interfaces.io.DataSink
494
+ self for instance method
482
495
bucket_name : string
483
496
string corresponding to the name of the bucket on S3
484
497
@@ -504,19 +517,21 @@ def _fetch_bucket(self, bucket_name):
504
517
creds_path = self .inputs .creds_path
505
518
iflogger = logging .getLogger ('interface' )
506
519
520
+ # Get AWS credentials
521
+ try :
522
+ aws_access_key_id , aws_secret_access_key = \
523
+ self ._return_aws_keys ()
524
+ except Exception as exc :
525
+ err_msg = 'There was a problem extracting the AWS credentials ' \
526
+ 'from the credentials file provided: %s. Error:\n %s' \
527
+ % (creds_path , exc )
528
+ raise Exception (err_msg )
529
+
507
530
# Try and get AWS credentials if a creds_path is specified
508
- if creds_path :
509
- try :
510
- aws_access_key_id , aws_secret_access_key = \
511
- self ._return_aws_keys (creds_path )
512
- except Exception as exc :
513
- err_msg = 'There was a problem extracting the AWS credentials ' \
514
- 'from the credentials file provided: %s. Error:\n %s' \
515
- % (creds_path , exc )
516
- raise Exception (err_msg )
531
+ if aws_access_key_id and aws_secret_access_key :
517
532
# Init connection
518
- iflogger .info ('Connecting to S3 bucket: %s with credentials from ' \
519
- '%s ...' % ( bucket_name , creds_path ) )
533
+ iflogger .info ('Connecting to S3 bucket: %s with credentials... ' \
534
+ % bucket_name )
520
535
# Use individual session for each instance of DataSink
521
536
# Better when datasinks are being used in multi-threading, see:
522
537
# http://boto3.readthedocs.org/en/latest/guide/resources.html#multithreading
@@ -762,101 +777,6 @@ def _list_outputs(self):
762
777
return outputs
763
778
764
779
765
- class S3DataSinkInputSpec (DynamicTraitedSpec , BaseInterfaceInputSpec ):
766
- testing = traits .Bool (False , usedefault = True ,
767
- desc = 'Flag for using local fakes3 server.'
768
- ' (for testing purposes only)' )
769
- anon = traits .Bool (False , usedefault = True ,
770
- desc = 'Use anonymous connection to s3' )
771
- bucket = traits .Str (mandatory = True ,
772
- desc = 'Amazon S3 bucket where your data is stored' )
773
- bucket_path = traits .Str ('' , usedefault = True ,
774
- desc = 'Location within your bucket to store '
775
- 'data.' )
776
- base_directory = Directory (
777
- desc = 'Path to the base directory for storing data.' )
778
- container = traits .Str (
779
- desc = 'Folder within base directory in which to store output' )
780
- parameterization = traits .Bool (True , usedefault = True ,
781
- desc = 'store output in parametrized structure' )
782
- strip_dir = Directory (desc = 'path to strip out of filename' )
783
- substitutions = InputMultiPath (traits .Tuple (traits .Str , traits .Str ),
784
- desc = ('List of 2-tuples reflecting string '
785
- 'to substitute and string to replace '
786
- 'it with' ))
787
- regexp_substitutions = InputMultiPath (traits .Tuple (traits .Str , traits .Str ),
788
- desc = ('List of 2-tuples reflecting a pair '
789
- 'of a Python regexp pattern and a '
790
- 'replacement string. Invoked after '
791
- 'string `substitutions`' ))
792
-
793
- _outputs = traits .Dict (traits .Str , value = {}, usedefault = True )
794
- remove_dest_dir = traits .Bool (False , usedefault = True ,
795
- desc = 'remove dest directory when copying dirs' )
796
- # Set this if user wishes to have local copy of files as well
797
- local_copy = traits .Str (desc = 'Copy files locally as well as to S3 bucket' )
798
-
799
- def __setattr__ (self , key , value ):
800
- if key not in self .copyable_trait_names ():
801
- if not isdefined (value ):
802
- super (S3DataSinkInputSpec , self ).__setattr__ (key , value )
803
- self ._outputs [key ] = value
804
- else :
805
- if key in self ._outputs :
806
- self ._outputs [key ] = value
807
- super (S3DataSinkInputSpec , self ).__setattr__ (key , value )
808
-
809
-
810
- class S3DataSink (DataSink ):
811
- """ Works exactly like DataSink, except the specified files will
812
- also be uploaded to Amazon S3 storage in the specified bucket
813
- and location. 'bucket_path' is the s3 analog for
814
- 'base_directory'.
815
-
816
- """
817
- input_spec = S3DataSinkInputSpec
818
-
819
- def _list_outputs (self ):
820
- """Execute this module.
821
- """
822
- outputs = super (S3DataSink , self )._list_outputs ()
823
-
824
- self .localtos3 (outputs ['out_file' ])
825
-
826
- return outputs
827
-
828
- def localtos3 (self , paths ):
829
- if self .inputs .testing :
830
- conn = S3Connection (anon = True , is_secure = False , port = 4567 ,
831
- host = 'localhost' ,
832
- calling_format = OrdinaryCallingFormat ())
833
-
834
- else :
835
- conn = S3Connection (anon = self .inputs .anon )
836
- bkt = conn .get_bucket (self .inputs .bucket )
837
- s3paths = []
838
-
839
- for path in paths :
840
- # convert local path to s3 path
841
- bd_index = path .find (self .inputs .base_directory )
842
- if bd_index != - 1 : # base_directory is in path, maintain directory structure
843
- s3path = path [bd_index + len (self .inputs .base_directory ):] # cut out base directory
844
- if s3path [0 ] == os .path .sep :
845
- s3path = s3path [1 :]
846
- else : # base_directory isn't in path, simply place all files in bucket_path folder
847
- s3path = os .path .split (path )[1 ] # take filename from path
848
- s3path = os .path .join (self .inputs .bucket_path , s3path )
849
- if s3path [- 1 ] == os .path .sep :
850
- s3path = s3path [:- 1 ]
851
- s3paths .append (s3path )
852
-
853
- k = boto .s3 .key .Key (bkt )
854
- k .key = s3path
855
- k .set_contents_from_filename (path )
856
-
857
- return s3paths
858
-
859
-
860
780
class S3DataGrabberInputSpec (DynamicTraitedSpec , BaseInterfaceInputSpec ):
861
781
anon = traits .Bool (False , usedefault = True ,
862
782
desc = 'Use anonymous connection to s3. If this is set to True, boto may print' +
0 commit comments