# -*- coding: utf-8 -*- # type: ignore from __future__ import annotations import datetime import json from unittest import mock import boto3 import moto import pytest from pytest_mock import MockerFixture from keep_it_secret.ext import aws from keep_it_secret.secrets import Secrets class TestingAWSSecrets(Secrets): aws = aws.AWSSecrets() @pytest.fixture def aws_secrets_manager_client() -> mock.Mock: return mock.Mock(spec=['get_secret_value']) @pytest.fixture def mock_boto3_client(mocker: MockerFixture) -> mock.Mock: return mocker.patch.object(aws.boto3, 'client') @pytest.fixture def testing_aws_secrets() -> TestingAWSSecrets: return TestingAWSSecrets() def test_init(): # When result = aws.AWSSecretsManagerField('keep_it_secret/tests/spam') # Then assert result.secret_id == 'keep_it_secret/tests/spam' assert result.default is None assert result.decoder == json.loads assert result.client is None def test_init_with_default(): # When result = aws.AWSSecretsManagerField( 'keep_it_secret/tests/spam', default='eggs', ) # Then assert result.default == 'eggs' def test_init_with_decoder(): # When result = aws.AWSSecretsManagerField( 'keep_it_secret/tests/spam', decoder=int, ) # Then assert result.decoder == int def test_init_with_field_options(): # When result = aws.AWSSecretsManagerField( 'keep_it_secret/tests/spam', as_type=int, required=False, description='spameggs', ) # Then assert result.as_type is None assert result.required is False assert result.description == 'spameggs' def test_new(mocker: MockerFixture): # Given mock_init = mocker.patch.object( aws.AWSSecretsManagerField, '__init__', return_value=None, ) # When _ = aws.AWSSecretsManagerField.new( 'keep_it_secret/tests/spam', default='eggs', decoder=json.dumps, as_type=int, required=False, description='spameggs', ) # Then mock_init.assert_called_once_with( 'keep_it_secret/tests/spam', default='eggs', decoder=json.dumps, as_type=int, required=False, description='spameggs', ) def test_get_client_cache_miss(mock_boto3_client: mock.Mock, aws_secrets_manager_client: mock.Mock, testing_aws_secrets: TestingAWSSecrets): # Given mock_boto3_client.return_value = aws_secrets_manager_client field = aws.AWSSecretsManagerField('keep_it_secret/tests/spam') # When result = field.get_client(testing_aws_secrets) # Then assert result == aws_secrets_manager_client assert field.client == aws_secrets_manager_client mock_boto3_client.assert_called_once_with( 'secretsmanager', **testing_aws_secrets.aws.as_boto3_client_kwargs(), ) def test_get_client_cache_hit(mock_boto3_client: mock.Mock, aws_secrets_manager_client: mock.Mock, testing_aws_secrets: TestingAWSSecrets): # Given field = aws.AWSSecretsManagerField('keep_it_secret/tests/spam') field.client = aws_secrets_manager_client # When result = field.get_client(testing_aws_secrets) # Then assert result == aws_secrets_manager_client mock_boto3_client.assert_not_called() def test_get_value_aws_dependency_missing(mocker: MockerFixture, aws_secrets_manager_client: mock.Mock, testing_secrets: Secrets): # Given field = aws.AWSSecretsManagerField('keep_it_secret/tests/spam') mock_field_get_client = mocker.patch.object( field, 'get_client', return_value=aws_secrets_manager_client, ) with pytest.raises(field.DependencyMissing) as exception_info: # When _ = field(testing_secrets) # Then assert exception_info.value.args[0] == 'aws' mock_field_get_client.assert_not_called() aws_secrets_manager_client.get_secret_value.assert_not_called() @moto.mock_secretsmanager def test_get_value_required_value_not_found(testing_aws_secrets: Secrets): # Given field = aws.AWSSecretsManagerField('keep_it_secret/tests/spam') with pytest.raises(field.RequiredValueMissing) as exception_info: # When _ = field(testing_aws_secrets) # Then assert exception_info.value.args[0] == 'keep_it_secret/tests/spam' @moto.mock_secretsmanager def test_get_value_not_found_not_required(testing_aws_secrets: Secrets): # Given field = aws.AWSSecretsManagerField( 'keep_it_secret/tests/spam', required=False, ) result = field(testing_aws_secrets) # Then assert result is None @moto.mock_secretsmanager def test_get_value(testing_aws_secrets: Secrets): # Given aws_secrets_manager_client = boto3.client('secretsmanager') aws_secrets_manager_client.create_secret( Name='keep_it_secret/tests/spam', SecretString='{"spam":true}', ) field = aws.AWSSecretsManagerField('keep_it_secret/tests/spam') # When result = field(testing_aws_secrets) # Then assert result == {"spam": True} @moto.mock_secretsmanager def test_get_value_with_custom_decoder(testing_aws_secrets: Secrets): # Given aws_secrets_manager_client = boto3.client('secretsmanager') aws_secrets_manager_client.create_secret( Name='keep_it_secret/tests/spam', SecretString='1987-10-03T08:00:00', ) field = aws.AWSSecretsManagerField( 'keep_it_secret/tests/spam', decoder=datetime.datetime.fromisoformat, ) # When result = field(testing_aws_secrets) # Then assert result == datetime.datetime(1987, 10, 3, 8, 0, 0)