[LYN-2151] Add argument to override aws profile and config file path (#994)

main
Vincent Liu 5 years ago committed by GitHub
parent 00e860f326
commit 9fb4ce59c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -38,6 +38,11 @@ namespace AWSCore
//! @return The path of AWS resource mapping config file //! @return The path of AWS resource mapping config file
virtual AZStd::string GetResourceMappingConfigFilePath() const = 0; virtual AZStd::string GetResourceMappingConfigFilePath() const = 0;
//! GetResourceMappingConfigFolderPath
//! Get the path of AWS resource mapping config folder
//! @return The path of AWS resource mapping config folder
virtual AZStd::string GetResourceMappingConfigFolderPath() const = 0;
//! ReloadConfiguration //! ReloadConfiguration
//! Reload AWSCore configuration without restarting application //! Reload AWSCore configuration without restarting application
virtual void ReloadConfiguration() = 0; virtual void ReloadConfiguration() = 0;

@ -53,6 +53,7 @@ namespace AWSCore
// AWSCoreInternalRequestBus interface implementation // AWSCoreInternalRequestBus interface implementation
AZStd::string GetResourceMappingConfigFilePath() const override; AZStd::string GetResourceMappingConfigFilePath() const override;
AZStd::string GetResourceMappingConfigFolderPath() const override;
AZStd::string GetProfileName() const override; AZStd::string GetProfileName() const override;
void ReloadConfiguration() override; void ReloadConfiguration() override;

@ -58,6 +58,19 @@ namespace AWSCore
return configFilePath; return configFilePath;
} }
AZStd::string AWSCoreConfiguration::GetResourceMappingConfigFolderPath() const
{
if (m_sourceProjectFolder.empty())
{
AZ_Warning(AWSCoreConfigurationName, false, ProjectSourceFolderNotFoundErrorMessage);
return "";
}
AZStd::string configFolderPath = AZStd::string::format(
"%s/%s", m_sourceProjectFolder.c_str(), AWSCoreResourceMappingConfigFolderName);
AzFramework::StringFunc::Path::Normalize(configFolderPath);
return configFolderPath;
}
void AWSCoreConfiguration::InitConfig() void AWSCoreConfiguration::InitConfig()
{ {
InitSourceProjectFolderPath(); InitSourceProjectFolderPath();
@ -123,7 +136,7 @@ namespace AWSCore
auto profileNamePath = AZStd::string::format("%s%s", auto profileNamePath = AZStd::string::format("%s%s",
AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreProfileNameKey); AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreProfileNameKey);
m_settingsRegistry.Remove(profileNamePath); m_settingsRegistry.Remove(profileNamePath);
m_profileName.clear(); m_profileName = AWSCoreDefaultProfileName;
auto resourceMappingConfigFileNamePath = AZStd::string::format("%s%s", auto resourceMappingConfigFileNamePath = AZStd::string::format("%s%s",
AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreResourceMappingConfigFileNameKey); AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreResourceMappingConfigFileNameKey);

@ -14,6 +14,7 @@
#include <AzCore/Utils/Utils.h> #include <AzCore/Utils/Utils.h>
#include <AzFramework/StringFunc/StringFunc.h> #include <AzFramework/StringFunc/StringFunc.h>
#include <AWSCoreInternalBus.h>
#include <Editor/UI/AWSCoreResourceMappingToolAction.h> #include <Editor/UI/AWSCoreResourceMappingToolAction.h>
namespace AWSCore namespace AWSCore
@ -108,17 +109,24 @@ namespace AWSCore
{ {
return ""; return "";
} }
AZStd::string profileName = "default";
AWSCoreInternalRequestBus::BroadcastResult(profileName, &AWSCoreInternalRequests::GetProfileName);
AZStd::string configPath = "";
AWSCoreInternalRequestBus::BroadcastResult(configPath, &AWSCoreInternalRequests::GetResourceMappingConfigFolderPath);
if (m_isDebug) if (m_isDebug)
{ {
return AZStd::string::format( return AZStd::string::format(
"%s debug %s --binaries_path %s --debug", "%s debug %s --binaries_path %s --debug --profile %s --config_path %s", m_enginePythonEntryPath.c_str(),
m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str()); m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(), profileName.c_str(), configPath.c_str());
} }
else else
{ {
return AZStd::string::format( return AZStd::string::format(
"%s %s --binaries_path %s", "%s %s --binaries_path %s --profile %s --config_path %s", m_enginePythonEntryPath.c_str(),
m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str()); m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(), profileName.c_str(), configPath.c_str());
} }
} }

@ -34,7 +34,8 @@ public:
MOCK_METHOD0(GetAWSCredentials, Aws::Auth::AWSCredentials()); MOCK_METHOD0(GetAWSCredentials, Aws::Auth::AWSCredentials());
}; };
class AWSDefaultCredentialHandlerMock : public AWSDefaultCredentialHandler class AWSDefaultCredentialHandlerMock
: public AWSDefaultCredentialHandler
{ {
public: public:
void SetupMocks( void SetupMocks(
@ -76,6 +77,7 @@ public:
// AWSCoreInternalRequestBus interface implementation // AWSCoreInternalRequestBus interface implementation
AZStd::string GetProfileName() const override { return m_profileName; } AZStd::string GetProfileName() const override { return m_profileName; }
AZStd::string GetResourceMappingConfigFilePath() const override { return ""; } AZStd::string GetResourceMappingConfigFilePath() const override { return ""; }
AZStd::string GetResourceMappingConfigFolderPath() const override { return ""; }
void ReloadConfiguration() override {} void ReloadConfiguration() override {}
std::shared_ptr<EnvironmentAWSCredentialsProviderMock> m_environmentCredentialsProviderMock; std::shared_ptr<EnvironmentAWSCredentialsProviderMock> m_environmentCredentialsProviderMock;

@ -119,6 +119,7 @@ public:
// AWSCoreInternalRequestBus interface implementation // AWSCoreInternalRequestBus interface implementation
AZStd::string GetProfileName() const override { return ""; } AZStd::string GetProfileName() const override { return ""; }
AZStd::string GetResourceMappingConfigFilePath() const override { return m_normalizedConfigFilePath; } AZStd::string GetResourceMappingConfigFilePath() const override { return m_normalizedConfigFilePath; }
AZStd::string GetResourceMappingConfigFolderPath() const override { return m_normalizedConfigFolderPath; }
void ReloadConfiguration() override { m_reloadConfigurationCounter++; } void ReloadConfiguration() override { m_reloadConfigurationCounter++; }
AZStd::unique_ptr<AWSCore::AWSResourceMappingManager> m_resourceMappingManager; AZStd::unique_ptr<AWSCore::AWSResourceMappingManager> m_resourceMappingManager;

@ -48,11 +48,14 @@ class ConfigurationManager(object):
def configuration(self, new_configuration: ConfigurationManager) -> None: def configuration(self, new_configuration: ConfigurationManager) -> None:
self._configuration = new_configuration self._configuration = new_configuration
def setup(self) -> None: def setup(self, config_path: str) -> None:
logger.info("Setting up default configuration ...") logger.info("Setting up default configuration ...")
# TODO: remove config directory and files default setup once integrating with user input
try: try:
self._configuration.config_directory = file_utils.get_current_directory_path() normalized_config_path: str = file_utils.normalize_file_path(config_path);
if normalized_config_path:
self._configuration.config_directory = normalized_config_path
else:
self._configuration.config_directory = file_utils.get_current_directory_path()
self._configuration.config_files = \ self._configuration.config_files = \
file_utils.find_files_with_suffix_under_directory(self._configuration.config_directory, file_utils.find_files_with_suffix_under_directory(self._configuration.config_directory,
constants.RESOURCE_MAPPING_CONFIG_FILE_NAME_SUFFIX) constants.RESOURCE_MAPPING_CONFIG_FILE_NAME_SUFFIX)

@ -13,13 +13,16 @@ from argparse import (ArgumentParser, Namespace)
import logging import logging
import sys import sys
from utils import aws_utils
from utils import environment_utils from utils import environment_utils
from utils import file_utils from utils import file_utils
# arguments setup # arguments setup
argument_parser: ArgumentParser = ArgumentParser() argument_parser: ArgumentParser = ArgumentParser()
argument_parser.add_argument('--binaries_path', help='Path to QT Binaries necessary for PySide.') argument_parser.add_argument('--binaries_path', help='Path to QT Binaries necessary for PySide.')
argument_parser.add_argument('--config_path', help='Path to resource mapping config directory.')
argument_parser.add_argument('--debug', action='store_true', help='Execute on debug mode to enable DEBUG logging level') argument_parser.add_argument('--debug', action='store_true', help='Execute on debug mode to enable DEBUG logging level')
argument_parser.add_argument('--profile', default='default', help='Named AWS profile to use for querying AWS resources')
arguments: Namespace = argument_parser.parse_args() arguments: Namespace = argument_parser.parse_args()
# logging setup # logging setup
@ -70,9 +73,12 @@ if __name__ == "__main__":
except FileNotFoundError: except FileNotFoundError:
logger.warning("Failed to load style sheet for resource mapping tool") logger.warning("Failed to load style sheet for resource mapping tool")
logger.info("Initializing boto3 default session ...")
aws_utils.setup_default_session(arguments.profile)
logger.info("Initializing configuration manager ...") logger.info("Initializing configuration manager ...")
configuration_manager: ConfigurationManager = ConfigurationManager() configuration_manager: ConfigurationManager = ConfigurationManager()
configuration_manager.setup() configuration_manager.setup(arguments.config_path)
logger.info("Initializing thread manager ...") logger.info("Initializing thread manager ...")
thread_manager: ThreadManager = ThreadManager() thread_manager: ThreadManager = ThreadManager()

@ -43,7 +43,7 @@ class TestConfigurationManager(TestCase):
mock_find_files_with_suffix_under_directory: MagicMock, mock_find_files_with_suffix_under_directory: MagicMock,
mock_get_default_account_id: MagicMock, mock_get_default_account_id: MagicMock,
mock_get_default_region: MagicMock) -> None: mock_get_default_region: MagicMock) -> None:
TestConfigurationManager._expected_configuration_manager.setup() TestConfigurationManager._expected_configuration_manager.setup("")
mock_get_current_directory_path.assert_called_once() mock_get_current_directory_path.assert_called_once()
mock_check_path_exists.assert_called_once_with(TestConfigurationManager._expected_directory_path) mock_check_path_exists.assert_called_once_with(TestConfigurationManager._expected_directory_path)
mock_find_files_with_suffix_under_directory.assert_called_once_with( mock_find_files_with_suffix_under_directory.assert_called_once_with(
@ -58,3 +58,29 @@ class TestConfigurationManager(TestCase):
TestConfigurationManager._expected_account_id TestConfigurationManager._expected_account_id
assert TestConfigurationManager._expected_configuration_manager.configuration.region == \ assert TestConfigurationManager._expected_configuration_manager.configuration.region == \
TestConfigurationManager._expected_region TestConfigurationManager._expected_region
@patch("utils.aws_utils.get_default_region", return_value=_expected_region)
@patch("utils.aws_utils.get_default_account_id", return_value=_expected_account_id)
@patch("utils.file_utils.find_files_with_suffix_under_directory", return_value=_expected_config_files)
@patch("utils.file_utils.check_path_exists", return_value=True)
@patch("utils.file_utils.normalize_file_path", return_value=_expected_directory_path)
def test_setup_get_configuration_setup_with_path_as_expected(self, mock_normalize_file_path: MagicMock,
mock_check_path_exists: MagicMock,
mock_find_files_with_suffix_under_directory: MagicMock,
mock_get_default_account_id: MagicMock,
mock_get_default_region: MagicMock) -> None:
TestConfigurationManager._expected_configuration_manager.setup(TestConfigurationManager._expected_directory_path)
mock_normalize_file_path.assert_called_once()
mock_check_path_exists.assert_called_once_with(TestConfigurationManager._expected_directory_path)
mock_find_files_with_suffix_under_directory.assert_called_once_with(
TestConfigurationManager._expected_directory_path, constants.RESOURCE_MAPPING_CONFIG_FILE_NAME_SUFFIX)
mock_get_default_account_id.assert_called_once()
mock_get_default_region.assert_called_once()
assert TestConfigurationManager._expected_configuration_manager.configuration.config_directory == \
TestConfigurationManager._expected_directory_path
assert TestConfigurationManager._expected_configuration_manager.configuration.config_files == \
TestConfigurationManager._expected_config_files
assert TestConfigurationManager._expected_configuration_manager.configuration.account_id == \
TestConfigurationManager._expected_account_id
assert TestConfigurationManager._expected_configuration_manager.configuration.region == \
TestConfigurationManager._expected_region

@ -36,7 +36,7 @@ class TestViewManager(TestCase):
main_window_patcher: patch = patch("manager.view_manager.QMainWindow") main_window_patcher: patch = patch("manager.view_manager.QMainWindow")
cls._mock_main_window = main_window_patcher.start() cls._mock_main_window = main_window_patcher.start()
window_icon_patcher: patch = patch("manager.view_manager.QPixmap") window_icon_patcher: patch = patch("manager.view_manager.QIcon")
window_icon_patcher.start() window_icon_patcher.start()
stacked_pages_patcher: patch = patch("manager.view_manager.QStackedWidget") stacked_pages_patcher: patch = patch("manager.view_manager.QStackedWidget")

@ -37,13 +37,12 @@ class TestAWSUtils(TestCase):
.build() .build()
def setUp(self) -> None: def setUp(self) -> None:
client_patcher: patch = patch("boto3.client")
self.addCleanup(client_patcher.stop)
self._mock_client: MagicMock = client_patcher.start()
session_patcher: patch = patch("boto3.session.Session") session_patcher: patch = patch("boto3.session.Session")
self.addCleanup(session_patcher.stop) self.addCleanup(session_patcher.stop)
self._mock_session: MagicMock = session_patcher.start() self._mock_session: MagicMock = session_patcher.start()
self._mock_client: MagicMock = self._mock_session.return_value.client
aws_utils.setup_default_session("default")
def test_get_default_account_id_return_expected_account_id(self) -> None: def test_get_default_account_id_return_expected_account_id(self) -> None:
mocked_sts_client: MagicMock = self._mock_client.return_value mocked_sts_client: MagicMock = self._mock_client.return_value

@ -26,6 +26,8 @@ aws account, region, resources, etc.
_PAGINATION_MAX_ITEMS: int = 10 _PAGINATION_MAX_ITEMS: int = 10
_PAGINATION_PAGE_SIZE: int = 10 _PAGINATION_PAGE_SIZE: int = 10
default_session: boto3.session.Session = None
class AWSConstants(object): class AWSConstants(object):
CLOUDFORMATION_SERVICE_NAME: str = "cloudformation" CLOUDFORMATION_SERVICE_NAME: str = "cloudformation"
@ -53,15 +55,20 @@ def _close_client_connection(client: BaseClient) -> None:
def _initialize_boto3_aws_client(service: str, region: str = "") -> BaseClient: def _initialize_boto3_aws_client(service: str, region: str = "") -> BaseClient:
if region: if region:
boto3_client: BaseClient = boto3.client(service, region_name=region) boto3_client: BaseClient = default_session.client(service, region_name=region)
else: else:
boto3_client: BaseClient = boto3.client(service) boto3_client: BaseClient = default_session.client(service)
boto3_client.meta.events.register( boto3_client.meta.events.register(
f"after-call.{service}.*", lambda **kwargs: _close_client_connection(boto3_client) f"after-call.{service}.*", lambda **kwargs: _close_client_connection(boto3_client)
) )
return boto3_client return boto3_client
def setup_default_session(profile: str) -> None:
global default_session
default_session = boto3.session.Session(profile_name=profile)
def get_default_account_id() -> str: def get_default_account_id() -> str:
sts_client: BaseClient = _initialize_boto3_aws_client(AWSConstants.STS_SERVICE_NAME) sts_client: BaseClient = _initialize_boto3_aws_client(AWSConstants.STS_SERVICE_NAME)
try: try:
@ -72,7 +79,7 @@ def get_default_account_id() -> str:
def get_default_region() -> str: def get_default_region() -> str:
region: str = boto3.session.Session().region_name region: str = default_session.region_name
if region: if region:
return region return region

Loading…
Cancel
Save