231 lines
5.7 KiB
Python
231 lines
5.7 KiB
Python
|
# -*- 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)
|