def test_save_config(config: Config) -> None: """Saving the configuration to the yaml file works.""" config.data = {"a": "b"} config.save() # act with open(config.config_path, "r") as file_cursor: assert "a:" in file_cursor.read()
def test_load_handles_file_not_found(config: Config) -> None: """ Given: An inexistent config file. When: configuration is loaded. Then: A ConfigError is returned. """ config.config_path = "inexistent.yaml" with pytest.raises(ConfigError): config.load()
def test_get_an_inexistent_key_raises_error(config: Config) -> None: """If the key you're trying to fetch doesn't exist, raise a KeyError exception.""" config.data = { "reports": { "second": "value" }, } with pytest.raises(ConfigError): config.get("reports.inexistent")
def set_active_project(config: Config, project_id: str) -> None: """Set the active project. Raises: ConfigError: If the project to activate doesn't exist. """ _check_project(config, project_id) config["active_project"] = project_id config.save() log.info(f"The project {project_id} is now active")
def test_get_can_fetch_nested_items_with_dots(config: Config) -> None: """Fetching values of configuration keys using dot notation works.""" config.data = { "first": { "second": "value" }, } result = config.get("first.second") assert result == "value"
def test_get_returns_the_default_if_it_doesnt_exist(config: Config) -> None: """ Given: An inexistent config key. When: The user calls the get method with a default value. Then: The default value is returned """ config.data = {"a": "b"} result = config.get("inexistent", "default_value") assert result == "default_value"
def test_load_handles_wrong_file_format(yaml_mock: Mock, config: Config) -> None: """ Given: A config file with wrong yaml format. When: configuration is loaded. Then: A ConfigError is returned. """ yaml_mock.return_value.load.side_effect = ParserError( "error", FileMarkMock(), "problem", FileMarkMock(), ) with pytest.raises(ConfigError): config.load()
def load_config(config_path: str) -> Config: """Configure the Config object.""" try: return Config(config_path) except ConfigError as error: log.error(str(error)) sys.exit(1)
def project_status(config: Config, aws: AWS) -> ProjectStatus: """Fetch the status of the autoscaling groups of the active project. Raises: ConfigError: If there are no active projects, no configured projects or the active project doesn't exist. """ project: ProjectStatus = {} active_project = get_active_project(config) for environment in ["Production", "Staging"]: try: autoscaler_name = config.get( f"projects.{active_project}." f"aws.autoscaling_groups.{environment.lower()}" ) if not isinstance(autoscaler_name, str): raise ConfigError("The autoscaler name is not a string") autoscaler_info = aws.get_autoscaling_group(autoscaler_name) except ConfigError: autoscaler_info = {} project[environment] = autoscaler_info return project
def fixture_config(tmpdir_factory: TempdirFactory) -> Config: """Configure the Config object for the tests.""" data = tmpdir_factory.mktemp("data") config_file = str(data.join("config.yaml")) copyfile("tests/assets/config.yaml", config_file) config = Config(config_file) return config
def test_project_handles_none_projects(config: Config) -> None: """ Given: A configuration with no configured projects. When: Asked for the project. Then: A ConfigError exception is raised. """ config.data["projects"] = {} with pytest.raises(ConfigError): services.get_active_project(config)
def test_active_project_unhappy_path( runner: CliRunner, caplog: LogCaptureFixture, config: Config ) -> None: """ Given: A drode program without any active project When: The active subcommand is called. Then: The exception is gracefully handled. """ del config.data["active_project"] config.save() result = runner.invoke(cli, ["active"]) assert result.exit_code == 1 assert ( "drode.entrypoints.cli", logging.ERROR, "There are more than one project configured but none is marked as active. " "Please use drode set command to define one.", ) in caplog.record_tuples
def test_set_active_project_handles_inexistent(config: Config) -> None: """ Given: A configuration without configured projects. When: Activating an inexistent project. Then: A ConfigError exception is raised. """ config.data = { "projects": {"test_project_1": {}}, } with pytest.raises(ConfigError): services.set_active_project(config, "inexistent_project")
def test_config_can_fetch_nested_items_with_dictionary_notation( config: Config) -> None: """Fetching values of configuration keys using the dictionary notation works.""" config.data = { "first": { "second": "value" }, } result = config["first"]["second"] assert result == "value"
def test_project_returns_only_project_if_just_one(config: Config) -> None: """ Given: A configuration with just one project. When: Asked for the project. Then: The project is returned. """ config.data = { "projects": {"test_project_1": {}}, } result = services.get_active_project(config) assert result == "test_project_1"
def test_set_active_project_works_if_existent( config: Config, caplog: LogCaptureFixture ) -> None: """ Given: A configuration with configured project. When: Set that project as active. Then: The project is activated and the configuration is saved. """ config.data = { "projects": {"project_1": {}}, } services.set_active_project(config, "project_1") # act # Reload the config from the file Config(config.config_path) assert config["active_project"] == "project_1" assert ( "drode.services", logging.INFO, "The project project_1 is now active", ) in caplog.record_tuples
def test_project_handles_inexistent_active_project(config: Config) -> None: """ Given: A configuration with an active project that doesn't exist. When: Asked for the project. Then: A ConfigError exception is raised. """ config.data = { "active_project": "inexistent_project", "projects": {"test_project_1": {}}, } with pytest.raises(ConfigError): services.get_active_project(config)
def test_status_unhappy_path( runner: CliRunner, fake_dependencies: FakeDeps, caplog: LogCaptureFixture, config: Config, ) -> None: """ Given: A wrong configured drode program. When: The status command is called. Then: The exception is handled gracefuly. """ del config.data["active_project"] config.save() result = runner.invoke(cli, ["status"], obj=fake_dependencies) assert result.exit_code == 1 assert ( "drode.entrypoints.cli", logging.ERROR, "There are more than one project configured but none is marked as active. " "Please use drode set command to define one.", ) in caplog.record_tuples
def test_project_handles_several_projects_and_no_active(config: Config) -> None: """ Given: A configuration with more than one projects but none activated. When: Asked for the project. Then: A ConfigError exception is raised. """ config.data = { "active_project": None, "projects": { "test_project_1": {}, "test_project_2": {}, }, } with pytest.raises(ConfigError): services.get_active_project(config)
def test_project_returns_active_project_if_set(config: Config) -> None: """ Given: A configuration with two projects and one activated. When: Asked for the project. Then: The activated project is returned. """ config.data = { "active_project": "test_project_2", "projects": { "test_project_1": {}, "test_project_2": {}, }, } result = services.get_active_project(config) assert result == "test_project_2"
def test_config_load(config: Config) -> None: """Loading the configuration from the yaml file works.""" config.load() # act assert config.data["verbose"] == "info"
def test_set_can_set_nested_items_with_dots(config: Config) -> None: """Setting values of configuration keys using dot notation works.""" config.set("storage.type", "tinydb") # act