diff --git a/seleniumbase/core/s3_manager.py b/seleniumbase/core/s3_manager.py index ad982bb8..3a581aad 100644 --- a/seleniumbase/core/s3_manager.py +++ b/seleniumbase/core/s3_manager.py @@ -24,19 +24,20 @@ class S3LoggingBucket(object): ) with pip_find_lock: try: - from boto.s3.connection import S3Connection + import boto3 except Exception: - shared_utils.pip_install("boto", version="2.49.0") - from boto.s3.connection import S3Connection - self.conn = S3Connection(selenium_access_key, selenium_secret_key) - self.bucket = self.conn.get_bucket(log_bucket) + shared_utils.pip_install("boto3") + import boto3 + self.conn = boto3.Session( + aws_access_key_id=selenium_access_key, + aws_secret_access_key=selenium_secret_key, + ) + self.bucket = log_bucket self.bucket_url = bucket_url def get_key(self, file_name): - """Create a new Key instance with the given name.""" - from boto.s3.key import Key - - return Key(bucket=self.bucket, name=file_name) + """Create a new S3 connection instance with the given name.""" + return self.conn.resource("s3").Object(self.bucket, file_name) def get_bucket(self): """Return the bucket being used.""" @@ -53,18 +54,19 @@ class S3LoggingBucket(object): content_type = "image/jpeg" elif file_name.endswith(".png"): content_type = "image/png" - upload_key.set_contents_from_filename( - file_path, headers={"Content-Type": content_type} + upload_key.Bucket().upload_file( + file_path, + file_name, + ExtraArgs={"ACL": "public-read", "ContentType": content_type}, ) - upload_key.url = upload_key.generate_url(expires_in=3600).split("?")[0] - try: - upload_key.make_public() - except Exception: - pass - def upload_index_file(self, test_address, timestamp): + def upload_index_file( + self, test_address, timestamp, data_path, save_data_to_logs + ): """Create an index.html file with links to all the log files that were just uploaded.""" + import os + global already_uploaded_files already_uploaded_files = list(set(already_uploaded_files)) already_uploaded_files.sort() @@ -76,15 +78,19 @@ class S3LoggingBucket(object): "%s" % (completed_file, completed_file) ) - index.set_contents_from_string( - "
".join(index_str), headers={"Content-Type": "text/html"} + index_page = str("
".join(index_str)) + save_data_to_logs(index_page, "index.html") + file_path = os.path.join(data_path, "index.html") + index.Bucket().upload_file( + file_path, + file_name, + ExtraArgs={"ACL": "public-read", "ContentType": "text/html"}, ) - index.make_public() return "%s%s" % (self.bucket_url, file_name) def save_uploaded_file_names(self, files): - """Keep a record of all file names that have been uploaded. Upload log - files related to each test after its execution. Once done, use - already_uploaded_files to create an index file.""" + """Keep a record of all file names that have been uploaded. + Upload log files related to each test after its execution. + Once done, use already_uploaded_files to create an index file.""" global already_uploaded_files already_uploaded_files.extend(files) diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py index ce79c09c..561f83bb 100644 --- a/seleniumbase/fixtures/base_case.py +++ b/seleniumbase/fixtures/base_case.py @@ -15174,16 +15174,16 @@ class BaseCase(unittest.TestCase): ) uploaded_files.append(logfile_name) s3_bucket.save_uploaded_file_names(uploaded_files) - index_file = s3_bucket.upload_index_file(test_id, guid) - print("\n\n*** Log files uploaded: ***\n%s\n" % index_file) + index_file = s3_bucket.upload_index_file( + test_id, guid, self.data_path, self.save_data_to_logs + ) + print("\n*** Log files uploaded: ***\n%s\n" % index_file) logging.info( - "\n\n*** Log files uploaded: ***\n%s\n" % index_file + "\n*** Log files uploaded: ***\n%s\n" % index_file ) if self.with_db_reporting: from seleniumbase.core.testcase_manager import ( TestcaseDataPayload, - ) - from seleniumbase.core.testcase_manager import ( TestcaseManager, ) diff --git a/seleniumbase/plugins/s3_logging_plugin.py b/seleniumbase/plugins/s3_logging_plugin.py index de40ea92..f83ac359 100644 --- a/seleniumbase/plugins/s3_logging_plugin.py +++ b/seleniumbase/plugins/s3_logging_plugin.py @@ -1,8 +1,6 @@ -"""The S3 Plugin for uploading test logs to the S3 bucket specified.""" +"""S3 Logging Plugin for SeleniumBase tests that run with pynose / nosetests""" import uuid -import logging import os -from seleniumbase.core.s3_manager import S3LoggingBucket from nose.plugins import Plugin @@ -14,25 +12,38 @@ class S3Logging(Plugin): """Get the options.""" super().configure(options, conf) self.options = options + self.test_id = None + + def save_data_to_logs(self, data, file_name): + from seleniumbase.fixtures import page_utils + + test_logpath = os.path.join(self.options.log_path, self.test_id) + file_name = str(file_name) + destination_folder = test_logpath + page_utils._save_data_as(data, destination_folder, file_name) def afterTest(self, test): - """After each testcase, upload logs to the S3 bucket.""" + """Upload logs to the S3 bucket after tests complete.""" + from seleniumbase.core.s3_manager import S3LoggingBucket + + self.test_id = test.test.id() s3_bucket = S3LoggingBucket() guid = str(uuid.uuid4().hex) - path = os.path.join(self.options.log_path, test.test.id()) + path = os.path.join(self.options.log_path, self.test_id) uploaded_files = [] for logfile in os.listdir(path): logfile_name = "%s/%s/%s" % ( guid, - test.test.id(), + self.test_id, logfile.split(path)[-1], ) s3_bucket.upload_file(logfile_name, os.path.join(path, logfile)) uploaded_files.append(logfile_name) s3_bucket.save_uploaded_file_names(uploaded_files) - index_file = s3_bucket.upload_index_file(test.id(), guid) - print("\n\n*** Log files uploaded: ***\n%s\n" % index_file) - logging.error("\n\n*** Log files uploaded: ***\n%s\n" % index_file) + index_file = s3_bucket.upload_index_file( + test.id(), guid, path, self.save_data_to_logs + ) + print("\n*** Log files uploaded: ***\n%s\n" % index_file) # If the SB database plugin is also being used, # attach a link to the logs index database row.