Feature: AppConfig (#6391)
This commit is contained in:
		
							parent
							
								
									6d9f4646c1
								
							
						
					
					
						commit
						6b86113534
					
				@ -280,6 +280,55 @@
 | 
				
			|||||||
- [X] update_vpc_link
 | 
					- [X] update_vpc_link
 | 
				
			||||||
</details>
 | 
					</details>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## appconfig
 | 
				
			||||||
 | 
					<details>
 | 
				
			||||||
 | 
					<summary>34% implemented</summary>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [X] create_application
 | 
				
			||||||
 | 
					- [X] create_configuration_profile
 | 
				
			||||||
 | 
					- [ ] create_deployment_strategy
 | 
				
			||||||
 | 
					- [ ] create_environment
 | 
				
			||||||
 | 
					- [ ] create_extension
 | 
				
			||||||
 | 
					- [ ] create_extension_association
 | 
				
			||||||
 | 
					- [X] create_hosted_configuration_version
 | 
				
			||||||
 | 
					- [X] delete_application
 | 
				
			||||||
 | 
					- [X] delete_configuration_profile
 | 
				
			||||||
 | 
					- [ ] delete_deployment_strategy
 | 
				
			||||||
 | 
					- [ ] delete_environment
 | 
				
			||||||
 | 
					- [ ] delete_extension
 | 
				
			||||||
 | 
					- [ ] delete_extension_association
 | 
				
			||||||
 | 
					- [X] delete_hosted_configuration_version
 | 
				
			||||||
 | 
					- [X] get_application
 | 
				
			||||||
 | 
					- [ ] get_configuration
 | 
				
			||||||
 | 
					- [X] get_configuration_profile
 | 
				
			||||||
 | 
					- [ ] get_deployment
 | 
				
			||||||
 | 
					- [ ] get_deployment_strategy
 | 
				
			||||||
 | 
					- [ ] get_environment
 | 
				
			||||||
 | 
					- [ ] get_extension
 | 
				
			||||||
 | 
					- [ ] get_extension_association
 | 
				
			||||||
 | 
					- [X] get_hosted_configuration_version
 | 
				
			||||||
 | 
					- [ ] list_applications
 | 
				
			||||||
 | 
					- [X] list_configuration_profiles
 | 
				
			||||||
 | 
					- [ ] list_deployment_strategies
 | 
				
			||||||
 | 
					- [ ] list_deployments
 | 
				
			||||||
 | 
					- [ ] list_environments
 | 
				
			||||||
 | 
					- [ ] list_extension_associations
 | 
				
			||||||
 | 
					- [ ] list_extensions
 | 
				
			||||||
 | 
					- [ ] list_hosted_configuration_versions
 | 
				
			||||||
 | 
					- [X] list_tags_for_resource
 | 
				
			||||||
 | 
					- [ ] start_deployment
 | 
				
			||||||
 | 
					- [ ] stop_deployment
 | 
				
			||||||
 | 
					- [X] tag_resource
 | 
				
			||||||
 | 
					- [X] untag_resource
 | 
				
			||||||
 | 
					- [X] update_application
 | 
				
			||||||
 | 
					- [X] update_configuration_profile
 | 
				
			||||||
 | 
					- [ ] update_deployment_strategy
 | 
				
			||||||
 | 
					- [ ] update_environment
 | 
				
			||||||
 | 
					- [ ] update_extension
 | 
				
			||||||
 | 
					- [ ] update_extension_association
 | 
				
			||||||
 | 
					- [ ] validate_configuration
 | 
				
			||||||
 | 
					</details>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## application-autoscaling
 | 
					## application-autoscaling
 | 
				
			||||||
<details>
 | 
					<details>
 | 
				
			||||||
<summary>69% implemented</summary>
 | 
					<summary>69% implemented</summary>
 | 
				
			||||||
@ -7121,7 +7170,6 @@
 | 
				
			|||||||
- amplifybackend
 | 
					- amplifybackend
 | 
				
			||||||
- amplifyuibuilder
 | 
					- amplifyuibuilder
 | 
				
			||||||
- apigatewaymanagementapi
 | 
					- apigatewaymanagementapi
 | 
				
			||||||
- appconfig
 | 
					 | 
				
			||||||
- appconfigdata
 | 
					- appconfigdata
 | 
				
			||||||
- appflow
 | 
					- appflow
 | 
				
			||||||
- appintegrations
 | 
					- appintegrations
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										77
									
								
								docs/docs/services/appconfig.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								docs/docs/services/appconfig.rst
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					.. _implementedservice_appconfig:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. |start-h3| raw:: html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. |end-h3| raw:: html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    </h3>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=========
 | 
				
			||||||
 | 
					appconfig
 | 
				
			||||||
 | 
					=========
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. autoclass:: moto.appconfig.models.AppConfigBackend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					|start-h3| Example usage |end-h3|
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. sourcecode:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            @mock_appconfig
 | 
				
			||||||
 | 
					            def test_appconfig_behaviour:
 | 
				
			||||||
 | 
					                boto3.client("appconfig")
 | 
				
			||||||
 | 
					                ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					|start-h3| Implemented features for this service |end-h3|
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [X] create_application
 | 
				
			||||||
 | 
					- [X] create_configuration_profile
 | 
				
			||||||
 | 
					- [ ] create_deployment_strategy
 | 
				
			||||||
 | 
					- [ ] create_environment
 | 
				
			||||||
 | 
					- [ ] create_extension
 | 
				
			||||||
 | 
					- [ ] create_extension_association
 | 
				
			||||||
 | 
					- [X] create_hosted_configuration_version
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					        The LatestVersionNumber-parameter is not yet implemented
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [X] delete_application
 | 
				
			||||||
 | 
					- [X] delete_configuration_profile
 | 
				
			||||||
 | 
					- [ ] delete_deployment_strategy
 | 
				
			||||||
 | 
					- [ ] delete_environment
 | 
				
			||||||
 | 
					- [ ] delete_extension
 | 
				
			||||||
 | 
					- [ ] delete_extension_association
 | 
				
			||||||
 | 
					- [X] delete_hosted_configuration_version
 | 
				
			||||||
 | 
					- [X] get_application
 | 
				
			||||||
 | 
					- [ ] get_configuration
 | 
				
			||||||
 | 
					- [X] get_configuration_profile
 | 
				
			||||||
 | 
					- [ ] get_deployment
 | 
				
			||||||
 | 
					- [ ] get_deployment_strategy
 | 
				
			||||||
 | 
					- [ ] get_environment
 | 
				
			||||||
 | 
					- [ ] get_extension
 | 
				
			||||||
 | 
					- [ ] get_extension_association
 | 
				
			||||||
 | 
					- [X] get_hosted_configuration_version
 | 
				
			||||||
 | 
					- [ ] list_applications
 | 
				
			||||||
 | 
					- [X] list_configuration_profiles
 | 
				
			||||||
 | 
					- [ ] list_deployment_strategies
 | 
				
			||||||
 | 
					- [ ] list_deployments
 | 
				
			||||||
 | 
					- [ ] list_environments
 | 
				
			||||||
 | 
					- [ ] list_extension_associations
 | 
				
			||||||
 | 
					- [ ] list_extensions
 | 
				
			||||||
 | 
					- [ ] list_hosted_configuration_versions
 | 
				
			||||||
 | 
					- [X] list_tags_for_resource
 | 
				
			||||||
 | 
					- [ ] start_deployment
 | 
				
			||||||
 | 
					- [ ] stop_deployment
 | 
				
			||||||
 | 
					- [X] tag_resource
 | 
				
			||||||
 | 
					- [X] untag_resource
 | 
				
			||||||
 | 
					- [X] update_application
 | 
				
			||||||
 | 
					- [X] update_configuration_profile
 | 
				
			||||||
 | 
					- [ ] update_deployment_strategy
 | 
				
			||||||
 | 
					- [ ] update_environment
 | 
				
			||||||
 | 
					- [ ] update_extension
 | 
				
			||||||
 | 
					- [ ] update_extension_association
 | 
				
			||||||
 | 
					- [ ] validate_configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -20,6 +20,7 @@ mock_acmpca = lazy_load(".acmpca", "mock_acmpca", boto3_name="acm-pca")
 | 
				
			|||||||
mock_amp = lazy_load(".amp", "mock_amp")
 | 
					mock_amp = lazy_load(".amp", "mock_amp")
 | 
				
			||||||
mock_apigateway = lazy_load(".apigateway", "mock_apigateway")
 | 
					mock_apigateway = lazy_load(".apigateway", "mock_apigateway")
 | 
				
			||||||
mock_apigatewayv2 = lazy_load(".apigatewayv2", "mock_apigatewayv2")
 | 
					mock_apigatewayv2 = lazy_load(".apigatewayv2", "mock_apigatewayv2")
 | 
				
			||||||
 | 
					mock_appconfig = lazy_load(".appconfig", "mock_appconfig")
 | 
				
			||||||
mock_appsync = lazy_load(".appsync", "mock_appsync")
 | 
					mock_appsync = lazy_load(".appsync", "mock_appsync")
 | 
				
			||||||
mock_athena = lazy_load(".athena", "mock_athena")
 | 
					mock_athena = lazy_load(".athena", "mock_athena")
 | 
				
			||||||
mock_applicationautoscaling = lazy_load(
 | 
					mock_applicationautoscaling = lazy_load(
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								moto/appconfig/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								moto/appconfig/__init__.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					"""appconfig module initialization; sets value for base decorator."""
 | 
				
			||||||
 | 
					from .models import appconfig_backends
 | 
				
			||||||
 | 
					from ..core.models import base_decorator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mock_appconfig = base_decorator(appconfig_backends)
 | 
				
			||||||
							
								
								
									
										19
									
								
								moto/appconfig/exceptions.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								moto/appconfig/exceptions.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					"""Exceptions raised by the appconfig service."""
 | 
				
			||||||
 | 
					from moto.core.exceptions import JsonRESTError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AppNotFoundException(JsonRESTError):
 | 
				
			||||||
 | 
					    def __init__(self) -> None:
 | 
				
			||||||
 | 
					        super().__init__("ResourceNotFoundException", "Application not found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConfigurationProfileNotFound(JsonRESTError):
 | 
				
			||||||
 | 
					    def __init__(self) -> None:
 | 
				
			||||||
 | 
					        super().__init__("ResourceNotFoundException", "ConfigurationProfile not found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConfigurationVersionNotFound(JsonRESTError):
 | 
				
			||||||
 | 
					    def __init__(self) -> None:
 | 
				
			||||||
 | 
					        super().__init__(
 | 
				
			||||||
 | 
					            "ResourceNotFoundException", "HostedConfigurationVersion not found"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
							
								
								
									
										281
									
								
								moto/appconfig/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								moto/appconfig/models.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,281 @@
 | 
				
			|||||||
 | 
					from moto.core import BaseBackend, BackendDict, BaseModel
 | 
				
			||||||
 | 
					from moto.moto_api._internal import mock_random
 | 
				
			||||||
 | 
					from moto.utilities.tagging_service import TaggingService
 | 
				
			||||||
 | 
					from typing import Any, Dict, List, Iterable, Optional
 | 
				
			||||||
 | 
					from .exceptions import (
 | 
				
			||||||
 | 
					    AppNotFoundException,
 | 
				
			||||||
 | 
					    ConfigurationProfileNotFound,
 | 
				
			||||||
 | 
					    ConfigurationVersionNotFound,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class HostedConfigurationVersion(BaseModel):
 | 
				
			||||||
 | 
					    def __init__(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        app_id: str,
 | 
				
			||||||
 | 
					        config_id: str,
 | 
				
			||||||
 | 
					        version: int,
 | 
				
			||||||
 | 
					        description: str,
 | 
				
			||||||
 | 
					        content: str,
 | 
				
			||||||
 | 
					        content_type: str,
 | 
				
			||||||
 | 
					        version_label: str,
 | 
				
			||||||
 | 
					    ):
 | 
				
			||||||
 | 
					        self.app_id = app_id
 | 
				
			||||||
 | 
					        self.config_id = config_id
 | 
				
			||||||
 | 
					        self.version = version
 | 
				
			||||||
 | 
					        self.description = description
 | 
				
			||||||
 | 
					        self.content = content
 | 
				
			||||||
 | 
					        self.content_type = content_type
 | 
				
			||||||
 | 
					        self.version_label = version_label
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_headers(self) -> Dict[str, Any]:
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            "application-id": self.app_id,
 | 
				
			||||||
 | 
					            "configuration-profile-id": self.config_id,
 | 
				
			||||||
 | 
					            "version-number": self.version,
 | 
				
			||||||
 | 
					            "description": self.description,
 | 
				
			||||||
 | 
					            "content-type": self.content_type,
 | 
				
			||||||
 | 
					            "VersionLabel": self.version_label,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConfigurationProfile(BaseModel):
 | 
				
			||||||
 | 
					    def __init__(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        application_id: str,
 | 
				
			||||||
 | 
					        name: str,
 | 
				
			||||||
 | 
					        region: str,
 | 
				
			||||||
 | 
					        account_id: str,
 | 
				
			||||||
 | 
					        description: str,
 | 
				
			||||||
 | 
					        location_uri: str,
 | 
				
			||||||
 | 
					        retrieval_role_arn: str,
 | 
				
			||||||
 | 
					        validators: List[Dict[str, str]],
 | 
				
			||||||
 | 
					        _type: str,
 | 
				
			||||||
 | 
					    ):
 | 
				
			||||||
 | 
					        self.id = mock_random.get_random_hex(7)
 | 
				
			||||||
 | 
					        self.arn = f"arn:aws:appconfig:{region}:{account_id}:application/{application_id}/configurationprofile/{self.id}"
 | 
				
			||||||
 | 
					        self.application_id = application_id
 | 
				
			||||||
 | 
					        self.name = name
 | 
				
			||||||
 | 
					        self.description = description
 | 
				
			||||||
 | 
					        self.location_uri = location_uri
 | 
				
			||||||
 | 
					        self.retrieval_role_arn = retrieval_role_arn
 | 
				
			||||||
 | 
					        self.validators = validators
 | 
				
			||||||
 | 
					        self._type = _type
 | 
				
			||||||
 | 
					        self.config_versions: Dict[int, HostedConfigurationVersion] = dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def create_version(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        app_id: str,
 | 
				
			||||||
 | 
					        config_id: str,
 | 
				
			||||||
 | 
					        description: str,
 | 
				
			||||||
 | 
					        content: str,
 | 
				
			||||||
 | 
					        content_type: str,
 | 
				
			||||||
 | 
					        version_label: str,
 | 
				
			||||||
 | 
					    ) -> HostedConfigurationVersion:
 | 
				
			||||||
 | 
					        if self.config_versions:
 | 
				
			||||||
 | 
					            version = sorted(self.config_versions.keys())[-1] + 1
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            version = 1
 | 
				
			||||||
 | 
					        self.config_versions[version] = HostedConfigurationVersion(
 | 
				
			||||||
 | 
					            app_id=app_id,
 | 
				
			||||||
 | 
					            config_id=config_id,
 | 
				
			||||||
 | 
					            version=version,
 | 
				
			||||||
 | 
					            description=description,
 | 
				
			||||||
 | 
					            content=content,
 | 
				
			||||||
 | 
					            content_type=content_type,
 | 
				
			||||||
 | 
					            version_label=version_label,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return self.config_versions[version]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_version(self, version: int) -> HostedConfigurationVersion:
 | 
				
			||||||
 | 
					        if version not in self.config_versions:
 | 
				
			||||||
 | 
					            raise ConfigurationVersionNotFound
 | 
				
			||||||
 | 
					        return self.config_versions[version]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def delete_version(self, version: int) -> None:
 | 
				
			||||||
 | 
					        self.config_versions.pop(version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_json(self) -> Dict[str, Any]:
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            "Id": self.id,
 | 
				
			||||||
 | 
					            "Name": self.name,
 | 
				
			||||||
 | 
					            "ApplicationId": self.application_id,
 | 
				
			||||||
 | 
					            "Description": self.description,
 | 
				
			||||||
 | 
					            "LocationUri": self.location_uri,
 | 
				
			||||||
 | 
					            "RetrievalRoleArn": self.retrieval_role_arn,
 | 
				
			||||||
 | 
					            "Validators": self.validators,
 | 
				
			||||||
 | 
					            "Type": self._type,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Application(BaseModel):
 | 
				
			||||||
 | 
					    def __init__(
 | 
				
			||||||
 | 
					        self, name: str, description: Optional[str], region: str, account_id: str
 | 
				
			||||||
 | 
					    ):
 | 
				
			||||||
 | 
					        self.id = mock_random.get_random_hex(7)
 | 
				
			||||||
 | 
					        self.arn = f"arn:aws:appconfig:{region}:{account_id}:application/{self.id}"
 | 
				
			||||||
 | 
					        self.name = name
 | 
				
			||||||
 | 
					        self.description = description
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.config_profiles: Dict[str, ConfigurationProfile] = dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def to_json(self) -> Dict[str, Any]:
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            "Id": self.id,
 | 
				
			||||||
 | 
					            "Name": self.name,
 | 
				
			||||||
 | 
					            "Description": self.description,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AppConfigBackend(BaseBackend):
 | 
				
			||||||
 | 
					    """Implementation of AppConfig APIs."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, region_name: str, account_id: str):
 | 
				
			||||||
 | 
					        super().__init__(region_name, account_id)
 | 
				
			||||||
 | 
					        self.applications: Dict[str, Application] = dict()
 | 
				
			||||||
 | 
					        self.tagger = TaggingService()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def create_application(
 | 
				
			||||||
 | 
					        self, name: str, description: Optional[str], tags: Dict[str, str]
 | 
				
			||||||
 | 
					    ) -> Application:
 | 
				
			||||||
 | 
					        app = Application(
 | 
				
			||||||
 | 
					            name, description, region=self.region_name, account_id=self.account_id
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.applications[app.id] = app
 | 
				
			||||||
 | 
					        self.tag_resource(app.arn, tags)
 | 
				
			||||||
 | 
					        return app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def delete_application(self, app_id: str) -> None:
 | 
				
			||||||
 | 
					        self.applications.pop(app_id, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_application(self, app_id: str) -> Application:
 | 
				
			||||||
 | 
					        if app_id not in self.applications:
 | 
				
			||||||
 | 
					            raise AppNotFoundException
 | 
				
			||||||
 | 
					        return self.applications[app_id]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_application(
 | 
				
			||||||
 | 
					        self, application_id: str, name: str, description: str
 | 
				
			||||||
 | 
					    ) -> Application:
 | 
				
			||||||
 | 
					        app = self.get_application(application_id)
 | 
				
			||||||
 | 
					        if name is not None:
 | 
				
			||||||
 | 
					            app.name = name
 | 
				
			||||||
 | 
					        if description is not None:
 | 
				
			||||||
 | 
					            app.description = description
 | 
				
			||||||
 | 
					        return app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def create_configuration_profile(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        application_id: str,
 | 
				
			||||||
 | 
					        name: str,
 | 
				
			||||||
 | 
					        description: str,
 | 
				
			||||||
 | 
					        location_uri: str,
 | 
				
			||||||
 | 
					        retrieval_role_arn: str,
 | 
				
			||||||
 | 
					        validators: List[Dict[str, str]],
 | 
				
			||||||
 | 
					        _type: str,
 | 
				
			||||||
 | 
					        tags: Dict[str, str],
 | 
				
			||||||
 | 
					    ) -> ConfigurationProfile:
 | 
				
			||||||
 | 
					        config_profile = ConfigurationProfile(
 | 
				
			||||||
 | 
					            application_id=application_id,
 | 
				
			||||||
 | 
					            name=name,
 | 
				
			||||||
 | 
					            region=self.region_name,
 | 
				
			||||||
 | 
					            account_id=self.account_id,
 | 
				
			||||||
 | 
					            description=description,
 | 
				
			||||||
 | 
					            location_uri=location_uri,
 | 
				
			||||||
 | 
					            retrieval_role_arn=retrieval_role_arn,
 | 
				
			||||||
 | 
					            validators=validators,
 | 
				
			||||||
 | 
					            _type=_type,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.tag_resource(config_profile.arn, tags)
 | 
				
			||||||
 | 
					        self.get_application(application_id).config_profiles[
 | 
				
			||||||
 | 
					            config_profile.id
 | 
				
			||||||
 | 
					        ] = config_profile
 | 
				
			||||||
 | 
					        return config_profile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def delete_configuration_profile(self, app_id: str, config_profile_id: str) -> None:
 | 
				
			||||||
 | 
					        self.get_application(app_id).config_profiles.pop(config_profile_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_configuration_profile(
 | 
				
			||||||
 | 
					        self, app_id: str, config_profile_id: str
 | 
				
			||||||
 | 
					    ) -> ConfigurationProfile:
 | 
				
			||||||
 | 
					        app = self.get_application(app_id)
 | 
				
			||||||
 | 
					        if config_profile_id not in app.config_profiles:
 | 
				
			||||||
 | 
					            raise ConfigurationProfileNotFound
 | 
				
			||||||
 | 
					        return app.config_profiles[config_profile_id]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_configuration_profile(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        application_id: str,
 | 
				
			||||||
 | 
					        config_profile_id: str,
 | 
				
			||||||
 | 
					        name: str,
 | 
				
			||||||
 | 
					        description: str,
 | 
				
			||||||
 | 
					        retrieval_role_arn: str,
 | 
				
			||||||
 | 
					        validators: List[Dict[str, str]],
 | 
				
			||||||
 | 
					    ) -> ConfigurationProfile:
 | 
				
			||||||
 | 
					        config_profile = self.get_configuration_profile(
 | 
				
			||||||
 | 
					            application_id, config_profile_id
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        if name is not None:
 | 
				
			||||||
 | 
					            config_profile.name = name
 | 
				
			||||||
 | 
					        if description is not None:
 | 
				
			||||||
 | 
					            config_profile.description = description
 | 
				
			||||||
 | 
					        if retrieval_role_arn is not None:
 | 
				
			||||||
 | 
					            config_profile.retrieval_role_arn = retrieval_role_arn
 | 
				
			||||||
 | 
					        if validators is not None:
 | 
				
			||||||
 | 
					            config_profile.validators = validators
 | 
				
			||||||
 | 
					        return config_profile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def list_configuration_profiles(
 | 
				
			||||||
 | 
					        self, app_id: str
 | 
				
			||||||
 | 
					    ) -> Iterable[ConfigurationProfile]:
 | 
				
			||||||
 | 
					        app = self.get_application(app_id)
 | 
				
			||||||
 | 
					        return app.config_profiles.values()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def create_hosted_configuration_version(
 | 
				
			||||||
 | 
					        self,
 | 
				
			||||||
 | 
					        app_id: str,
 | 
				
			||||||
 | 
					        config_profile_id: str,
 | 
				
			||||||
 | 
					        description: str,
 | 
				
			||||||
 | 
					        content: str,
 | 
				
			||||||
 | 
					        content_type: str,
 | 
				
			||||||
 | 
					        version_label: str,
 | 
				
			||||||
 | 
					    ) -> HostedConfigurationVersion:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        The LatestVersionNumber-parameter is not yet implemented
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        profile = self.get_configuration_profile(app_id, config_profile_id)
 | 
				
			||||||
 | 
					        return profile.create_version(
 | 
				
			||||||
 | 
					            app_id=app_id,
 | 
				
			||||||
 | 
					            config_id=config_profile_id,
 | 
				
			||||||
 | 
					            description=description,
 | 
				
			||||||
 | 
					            content=content,
 | 
				
			||||||
 | 
					            content_type=content_type,
 | 
				
			||||||
 | 
					            version_label=version_label,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_hosted_configuration_version(
 | 
				
			||||||
 | 
					        self, app_id: str, config_profile_id: str, version: int
 | 
				
			||||||
 | 
					    ) -> HostedConfigurationVersion:
 | 
				
			||||||
 | 
					        profile = self.get_configuration_profile(
 | 
				
			||||||
 | 
					            app_id=app_id, config_profile_id=config_profile_id
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return profile.get_version(version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def delete_hosted_configuration_version(
 | 
				
			||||||
 | 
					        self, app_id: str, config_profile_id: str, version: int
 | 
				
			||||||
 | 
					    ) -> None:
 | 
				
			||||||
 | 
					        profile = self.get_configuration_profile(
 | 
				
			||||||
 | 
					            app_id=app_id, config_profile_id=config_profile_id
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        profile.delete_version(version=version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def list_tags_for_resource(self, arn: str) -> Dict[str, str]:
 | 
				
			||||||
 | 
					        return self.tagger.get_tag_dict_for_resource(arn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def tag_resource(self, arn: str, tags: Dict[str, str]) -> None:
 | 
				
			||||||
 | 
					        self.tagger.tag_resource(arn, TaggingService.convert_dict_to_tags_input(tags))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def untag_resource(self, arn: str, tag_keys: List[str]) -> None:
 | 
				
			||||||
 | 
					        self.tagger.untag_resource_using_names(arn, tag_keys)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					appconfig_backends = BackendDict(AppConfigBackend, "appconfig")
 | 
				
			||||||
							
								
								
									
										169
									
								
								moto/appconfig/responses.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								moto/appconfig/responses.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,169 @@
 | 
				
			|||||||
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from moto.core.responses import BaseResponse
 | 
				
			||||||
 | 
					from .models import appconfig_backends, AppConfigBackend
 | 
				
			||||||
 | 
					from typing import Any, Dict, Tuple
 | 
				
			||||||
 | 
					from urllib.parse import unquote
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AppConfigResponse(BaseResponse):
 | 
				
			||||||
 | 
					    def tags(self, request: Any, full_url: str, headers: Any) -> str:  # type: ignore[return]
 | 
				
			||||||
 | 
					        self.setup_class(request, full_url, headers)
 | 
				
			||||||
 | 
					        if request.method == "GET":
 | 
				
			||||||
 | 
					            return self.list_tags_for_resource()
 | 
				
			||||||
 | 
					        if request.method == "POST":
 | 
				
			||||||
 | 
					            return self.tag_resource()
 | 
				
			||||||
 | 
					        if request.method == "DELETE":
 | 
				
			||||||
 | 
					            return self.untag_resource()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self) -> None:
 | 
				
			||||||
 | 
					        super().__init__(service_name="appconfig")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def appconfig_backend(self) -> AppConfigBackend:
 | 
				
			||||||
 | 
					        return appconfig_backends[self.current_account][self.region]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def create_application(self) -> str:
 | 
				
			||||||
 | 
					        name = self._get_param("Name")
 | 
				
			||||||
 | 
					        description = self._get_param("Description")
 | 
				
			||||||
 | 
					        tags = self._get_param("Tags")
 | 
				
			||||||
 | 
					        app = self.appconfig_backend.create_application(
 | 
				
			||||||
 | 
					            name=name,
 | 
				
			||||||
 | 
					            description=description,
 | 
				
			||||||
 | 
					            tags=tags,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return json.dumps(app.to_json())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def delete_application(self) -> str:
 | 
				
			||||||
 | 
					        app_id = self._get_param("ApplicationId")
 | 
				
			||||||
 | 
					        self.appconfig_backend.delete_application(app_id)
 | 
				
			||||||
 | 
					        return "{}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_application(self) -> str:
 | 
				
			||||||
 | 
					        app_id = self._get_param("ApplicationId")
 | 
				
			||||||
 | 
					        app = self.appconfig_backend.get_application(app_id)
 | 
				
			||||||
 | 
					        return json.dumps(app.to_json())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_application(self) -> str:
 | 
				
			||||||
 | 
					        app_id = self._get_param("ApplicationId")
 | 
				
			||||||
 | 
					        name = self._get_param("Name")
 | 
				
			||||||
 | 
					        description = self._get_param("Description")
 | 
				
			||||||
 | 
					        app = self.appconfig_backend.update_application(
 | 
				
			||||||
 | 
					            application_id=app_id,
 | 
				
			||||||
 | 
					            name=name,
 | 
				
			||||||
 | 
					            description=description,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return json.dumps(app.to_json())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def create_configuration_profile(self) -> str:
 | 
				
			||||||
 | 
					        app_id = self._get_param("ApplicationId")
 | 
				
			||||||
 | 
					        name = self._get_param("Name")
 | 
				
			||||||
 | 
					        description = self._get_param("Description")
 | 
				
			||||||
 | 
					        location_uri = self._get_param("LocationUri")
 | 
				
			||||||
 | 
					        retrieval_role_arn = self._get_param("RetrievalRoleArn")
 | 
				
			||||||
 | 
					        validators = self._get_param("Validators")
 | 
				
			||||||
 | 
					        _type = self._get_param("Type")
 | 
				
			||||||
 | 
					        tags = self._get_param("Tags")
 | 
				
			||||||
 | 
					        config_profile = self.appconfig_backend.create_configuration_profile(
 | 
				
			||||||
 | 
					            application_id=app_id,
 | 
				
			||||||
 | 
					            name=name,
 | 
				
			||||||
 | 
					            description=description,
 | 
				
			||||||
 | 
					            location_uri=location_uri,
 | 
				
			||||||
 | 
					            retrieval_role_arn=retrieval_role_arn,
 | 
				
			||||||
 | 
					            validators=validators,
 | 
				
			||||||
 | 
					            _type=_type,
 | 
				
			||||||
 | 
					            tags=tags,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return json.dumps(config_profile.to_json())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def delete_configuration_profile(self) -> str:
 | 
				
			||||||
 | 
					        app_id = self._get_param("ApplicationId")
 | 
				
			||||||
 | 
					        config_profile_id = self._get_param("ConfigurationProfileId")
 | 
				
			||||||
 | 
					        self.appconfig_backend.delete_configuration_profile(app_id, config_profile_id)
 | 
				
			||||||
 | 
					        return "{}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_configuration_profile(self) -> str:
 | 
				
			||||||
 | 
					        app_id = self._get_param("ApplicationId")
 | 
				
			||||||
 | 
					        config_profile_id = self._get_param("ConfigurationProfileId")
 | 
				
			||||||
 | 
					        config_profile = self.appconfig_backend.get_configuration_profile(
 | 
				
			||||||
 | 
					            app_id, config_profile_id
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return json.dumps(config_profile.to_json())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def update_configuration_profile(self) -> str:
 | 
				
			||||||
 | 
					        app_id = self._get_param("ApplicationId")
 | 
				
			||||||
 | 
					        config_profile_id = self._get_param("ConfigurationProfileId")
 | 
				
			||||||
 | 
					        name = self._get_param("Name")
 | 
				
			||||||
 | 
					        description = self._get_param("Description")
 | 
				
			||||||
 | 
					        retrieval_role_arn = self._get_param("RetrievalRoleArn")
 | 
				
			||||||
 | 
					        validators = self._get_param("Validators")
 | 
				
			||||||
 | 
					        config_profile = self.appconfig_backend.update_configuration_profile(
 | 
				
			||||||
 | 
					            application_id=app_id,
 | 
				
			||||||
 | 
					            config_profile_id=config_profile_id,
 | 
				
			||||||
 | 
					            name=name,
 | 
				
			||||||
 | 
					            description=description,
 | 
				
			||||||
 | 
					            retrieval_role_arn=retrieval_role_arn,
 | 
				
			||||||
 | 
					            validators=validators,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return json.dumps(config_profile.to_json())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def list_configuration_profiles(self) -> str:
 | 
				
			||||||
 | 
					        app_id = self._get_param("ApplicationId")
 | 
				
			||||||
 | 
					        profiles = self.appconfig_backend.list_configuration_profiles(app_id)
 | 
				
			||||||
 | 
					        return json.dumps({"Items": [p.to_json() for p in profiles]})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def list_tags_for_resource(self) -> str:
 | 
				
			||||||
 | 
					        arn = unquote(self.path.split("/tags/")[-1])
 | 
				
			||||||
 | 
					        tags = self.appconfig_backend.list_tags_for_resource(arn)
 | 
				
			||||||
 | 
					        return json.dumps({"Tags": tags})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def tag_resource(self) -> str:
 | 
				
			||||||
 | 
					        arn = unquote(self.path.split("/tags/")[-1])
 | 
				
			||||||
 | 
					        tags = self._get_param("Tags")
 | 
				
			||||||
 | 
					        self.appconfig_backend.tag_resource(arn, tags)
 | 
				
			||||||
 | 
					        return "{}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def untag_resource(self) -> str:
 | 
				
			||||||
 | 
					        arn = unquote(self.path.split("/tags/")[-1])
 | 
				
			||||||
 | 
					        tag_keys = self.querystring.get("tagKeys")
 | 
				
			||||||
 | 
					        self.appconfig_backend.untag_resource(arn, tag_keys)  # type: ignore[arg-type]
 | 
				
			||||||
 | 
					        return "{}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def create_hosted_configuration_version(self) -> Tuple[str, Dict[str, Any]]:
 | 
				
			||||||
 | 
					        app_id = self._get_param("ApplicationId")
 | 
				
			||||||
 | 
					        config_profile_id = self._get_param("ConfigurationProfileId")
 | 
				
			||||||
 | 
					        description = self.headers.get("Description")
 | 
				
			||||||
 | 
					        content = self.body
 | 
				
			||||||
 | 
					        content_type = self.headers.get("Content-Type")
 | 
				
			||||||
 | 
					        version_label = self.headers.get("VersionLabel")
 | 
				
			||||||
 | 
					        version = self.appconfig_backend.create_hosted_configuration_version(
 | 
				
			||||||
 | 
					            app_id=app_id,
 | 
				
			||||||
 | 
					            config_profile_id=config_profile_id,
 | 
				
			||||||
 | 
					            description=description,
 | 
				
			||||||
 | 
					            content=content,
 | 
				
			||||||
 | 
					            content_type=content_type,
 | 
				
			||||||
 | 
					            version_label=version_label,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return version.content, version.get_headers()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_hosted_configuration_version(self) -> Tuple[str, Dict[str, Any]]:
 | 
				
			||||||
 | 
					        app_id = self._get_param("ApplicationId")
 | 
				
			||||||
 | 
					        config_profile_id = self._get_param("ConfigurationProfileId")
 | 
				
			||||||
 | 
					        version_number = self._get_int_param("VersionNumber")
 | 
				
			||||||
 | 
					        version = self.appconfig_backend.get_hosted_configuration_version(
 | 
				
			||||||
 | 
					            app_id=app_id,
 | 
				
			||||||
 | 
					            config_profile_id=config_profile_id,
 | 
				
			||||||
 | 
					            version=version_number,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return version.content, version.get_headers()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def delete_hosted_configuration_version(self) -> str:
 | 
				
			||||||
 | 
					        app_id = self._get_param("ApplicationId")
 | 
				
			||||||
 | 
					        config_profile_id = self._get_param("ConfigurationProfileId")
 | 
				
			||||||
 | 
					        version_number = self._get_int_param("VersionNumber")
 | 
				
			||||||
 | 
					        self.appconfig_backend.delete_hosted_configuration_version(
 | 
				
			||||||
 | 
					            app_id=app_id,
 | 
				
			||||||
 | 
					            config_profile_id=config_profile_id,
 | 
				
			||||||
 | 
					            version=version_number,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return "{}"
 | 
				
			||||||
							
								
								
									
										22
									
								
								moto/appconfig/urls.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								moto/appconfig/urls.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					"""appconfig base URL and path."""
 | 
				
			||||||
 | 
					from .responses import AppConfigResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					url_bases = [
 | 
				
			||||||
 | 
					    r"https?://appconfig\.(.+)\.amazonaws\.com",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					response = AppConfigResponse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					url_paths = {
 | 
				
			||||||
 | 
					    "{0}/applications$": response.dispatch,
 | 
				
			||||||
 | 
					    "{0}/applications/(?P<app_id>[^/]+)$": response.dispatch,
 | 
				
			||||||
 | 
					    "{0}/applications/(?P<app_id>[^/]+)/configurationprofiles$": response.dispatch,
 | 
				
			||||||
 | 
					    "{0}/applications/(?P<app_id>[^/]+)/configurationprofiles/(?P<config_profile_id>[^/]+)$": response.dispatch,
 | 
				
			||||||
 | 
					    "{0}/applications/(?P<app_id>[^/]+)/configurationprofiles/(?P<config_profile_id>[^/]+)/hostedconfigurationversions$": response.dispatch,
 | 
				
			||||||
 | 
					    "{0}/applications/(?P<app_id>[^/]+)/configurationprofiles/(?P<config_profile_id>[^/]+)/hostedconfigurationversions/(?P<version>[^/]+)$": response.dispatch,
 | 
				
			||||||
 | 
					    "{0}/tags/(?P<app_id>.+)$": response.dispatch,
 | 
				
			||||||
 | 
					    "{0}/tags/(?P<arn_part_1>[^/]+)/(?P<app_id>[^/]+)$": response.tags,
 | 
				
			||||||
 | 
					    "{0}/tags/(?P<arn_part_1>[^/]+)/(?P<app_id>[^/]+)/configurationprofile/(?P<cp_id>[^/]+)$": response.tags,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -6,6 +6,7 @@ backend_url_patterns = [
 | 
				
			|||||||
    ("acm-pca", re.compile("https?://acm-pca\\.(.+)\\.amazonaws\\.com")),
 | 
					    ("acm-pca", re.compile("https?://acm-pca\\.(.+)\\.amazonaws\\.com")),
 | 
				
			||||||
    ("amp", re.compile("https?://aps\\.(.+)\\.amazonaws\\.com")),
 | 
					    ("amp", re.compile("https?://aps\\.(.+)\\.amazonaws\\.com")),
 | 
				
			||||||
    ("apigateway", re.compile("https?://apigateway\\.(.+)\\.amazonaws.com")),
 | 
					    ("apigateway", re.compile("https?://apigateway\\.(.+)\\.amazonaws.com")),
 | 
				
			||||||
 | 
					    ("appconfig", re.compile("https?://appconfig\\.(.+)\\.amazonaws\\.com")),
 | 
				
			||||||
    (
 | 
					    (
 | 
				
			||||||
        "applicationautoscaling",
 | 
					        "applicationautoscaling",
 | 
				
			||||||
        re.compile("https?://application-autoscaling\\.(.+)\\.amazonaws.com"),
 | 
					        re.compile("https?://application-autoscaling\\.(.+)\\.amazonaws.com"),
 | 
				
			||||||
 | 
				
			|||||||
@ -31,6 +31,12 @@ apigatewayv2:
 | 
				
			|||||||
  - TestAccAPIGatewayV2Model
 | 
					  - TestAccAPIGatewayV2Model
 | 
				
			||||||
  - TestAccAPIGatewayV2Route
 | 
					  - TestAccAPIGatewayV2Route
 | 
				
			||||||
  - TestAccAPIGatewayV2VPCLink
 | 
					  - TestAccAPIGatewayV2VPCLink
 | 
				
			||||||
 | 
					appconfig:
 | 
				
			||||||
 | 
					  - TestAccAppConfigConfigurationProfileDataSource_basic
 | 
				
			||||||
 | 
					  - TestAccAppConfigConfigurationProfile_
 | 
				
			||||||
 | 
					  - TestAccAppConfigConfigurationProfilesDataSource_basic
 | 
				
			||||||
 | 
					  - TestAccAppConfigApplication_
 | 
				
			||||||
 | 
					  - TestAccAppConfigHostedConfigurationVersion_
 | 
				
			||||||
autoscaling:
 | 
					autoscaling:
 | 
				
			||||||
  - TestAccAutoScalingAttachment
 | 
					  - TestAccAutoScalingAttachment
 | 
				
			||||||
  - TestAccAutoScalingGroupDataSource
 | 
					  - TestAccAutoScalingGroupDataSource
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										0
									
								
								tests/test_appconfig/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/test_appconfig/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										83
									
								
								tests/test_appconfig/test_appconfig_applications.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								tests/test_appconfig/test_appconfig_applications.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					"""Unit tests for appconfig-supported APIs."""
 | 
				
			||||||
 | 
					import boto3
 | 
				
			||||||
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from botocore.exceptions import ClientError
 | 
				
			||||||
 | 
					from moto import mock_appconfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# See our Development Tips on writing tests for hints on how to write good tests:
 | 
				
			||||||
 | 
					# http://docs.getmoto.org/en/latest/docs/contributing/development_tips/tests.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mock_appconfig
 | 
				
			||||||
 | 
					def test_create_application():
 | 
				
			||||||
 | 
					    client = boto3.client("appconfig", region_name="ap-southeast-1")
 | 
				
			||||||
 | 
					    post = client.create_application(Name="testapp", Description="blah")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert "Id" in post
 | 
				
			||||||
 | 
					    assert post["Name"] == "testapp"
 | 
				
			||||||
 | 
					    assert post["Description"] == "blah"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    get = client.get_application(ApplicationId=post["Id"])
 | 
				
			||||||
 | 
					    assert post["Id"] == get["Id"]
 | 
				
			||||||
 | 
					    assert post["Name"] == get["Name"]
 | 
				
			||||||
 | 
					    assert post["Description"] == get["Description"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    update = client.update_application(
 | 
				
			||||||
 | 
					        ApplicationId=post["Id"],
 | 
				
			||||||
 | 
					        Name="name2",
 | 
				
			||||||
 | 
					        Description="desc2",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    assert update["Name"] == "name2"
 | 
				
			||||||
 | 
					    assert update["Description"] == "desc2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.delete_application(ApplicationId=post["Id"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with pytest.raises(ClientError) as exc:
 | 
				
			||||||
 | 
					        client.get_application(ApplicationId=post["Id"])
 | 
				
			||||||
 | 
					    err = exc.value.response["Error"]
 | 
				
			||||||
 | 
					    assert err["Code"] == "ResourceNotFoundException"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mock_appconfig
 | 
				
			||||||
 | 
					def test_tag_application():
 | 
				
			||||||
 | 
					    client = boto3.client("appconfig", region_name="us-east-2")
 | 
				
			||||||
 | 
					    app_id = client.create_application(Name="testapp")["Id"]
 | 
				
			||||||
 | 
					    app_arn = f"arn:aws:appconfig:us-east-2:123456789012:application/{app_id}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tags = client.list_tags_for_resource(ResourceArn=app_arn)["Tags"]
 | 
				
			||||||
 | 
					    assert tags == {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.tag_resource(
 | 
				
			||||||
 | 
					        ResourceArn=app_arn,
 | 
				
			||||||
 | 
					        Tags={"k1": "v1"},
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tags = client.list_tags_for_resource(ResourceArn=app_arn)["Tags"]
 | 
				
			||||||
 | 
					    assert tags == {"k1": "v1"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ####
 | 
				
			||||||
 | 
					    # Check this flow works when creating an app with tags
 | 
				
			||||||
 | 
					    app_id = client.create_application(Name="testapp", Tags={"k1": "v1"})["Id"]
 | 
				
			||||||
 | 
					    app_arn = f"arn:aws:appconfig:us-east-2:123456789012:application/{app_id}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tags = client.list_tags_for_resource(ResourceArn=app_arn)["Tags"]
 | 
				
			||||||
 | 
					    assert tags == {"k1": "v1"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.tag_resource(
 | 
				
			||||||
 | 
					        ResourceArn=app_arn,
 | 
				
			||||||
 | 
					        Tags={"k2": "v2", "k3": "v3"},
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tags = client.list_tags_for_resource(ResourceArn=app_arn)["Tags"]
 | 
				
			||||||
 | 
					    assert tags == {"k1": "v1", "k2": "v2", "k3": "v3"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.untag_resource(ResourceArn=app_arn, TagKeys=["k2"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tags = client.list_tags_for_resource(ResourceArn=app_arn)["Tags"]
 | 
				
			||||||
 | 
					    assert tags == {"k1": "v1", "k3": "v3"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.untag_resource(ResourceArn=app_arn, TagKeys=["k1", "k3"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tags = client.list_tags_for_resource(ResourceArn=app_arn)["Tags"]
 | 
				
			||||||
 | 
					    assert tags == {}
 | 
				
			||||||
							
								
								
									
										134
									
								
								tests/test_appconfig/test_appconfig_config_profiles.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								tests/test_appconfig/test_appconfig_config_profiles.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,134 @@
 | 
				
			|||||||
 | 
					import boto3
 | 
				
			||||||
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from botocore.exceptions import ClientError
 | 
				
			||||||
 | 
					from moto import mock_appconfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mock_appconfig
 | 
				
			||||||
 | 
					def test_create_configuration_profile():
 | 
				
			||||||
 | 
					    client = boto3.client("appconfig", region_name="eu-north-1")
 | 
				
			||||||
 | 
					    app_id = client.create_application(Name="testapp")["Id"]
 | 
				
			||||||
 | 
					    resp = client.create_configuration_profile(
 | 
				
			||||||
 | 
					        ApplicationId=app_id,
 | 
				
			||||||
 | 
					        Name="config_name",
 | 
				
			||||||
 | 
					        Description="desc",
 | 
				
			||||||
 | 
					        LocationUri="luri",
 | 
				
			||||||
 | 
					        RetrievalRoleArn="rrarn:rrarn:rrarn:rrarn",
 | 
				
			||||||
 | 
					        Validators=[{"Type": "JSON", "Content": "c"}],
 | 
				
			||||||
 | 
					        Type="freeform",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    del resp["ResponseMetadata"]
 | 
				
			||||||
 | 
					    assert "Id" in resp
 | 
				
			||||||
 | 
					    config_profile_id = resp.pop("Id")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expected_response = {
 | 
				
			||||||
 | 
					        "ApplicationId": app_id,
 | 
				
			||||||
 | 
					        "Name": "config_name",
 | 
				
			||||||
 | 
					        "Description": "desc",
 | 
				
			||||||
 | 
					        "LocationUri": "luri",
 | 
				
			||||||
 | 
					        "RetrievalRoleArn": "rrarn:rrarn:rrarn:rrarn",
 | 
				
			||||||
 | 
					        "Validators": [{"Type": "JSON", "Content": "c"}],
 | 
				
			||||||
 | 
					        "Type": "freeform",
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert resp == expected_response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    resp = client.get_configuration_profile(
 | 
				
			||||||
 | 
					        ApplicationId=app_id,
 | 
				
			||||||
 | 
					        ConfigurationProfileId=config_profile_id,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    del resp["ResponseMetadata"]
 | 
				
			||||||
 | 
					    assert "Id" in resp
 | 
				
			||||||
 | 
					    resp.pop("Id")
 | 
				
			||||||
 | 
					    assert resp == expected_response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    profiles = client.list_configuration_profiles(ApplicationId=app_id)["Items"]
 | 
				
			||||||
 | 
					    assert profiles == [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "ApplicationId": app_id,
 | 
				
			||||||
 | 
					            "Id": config_profile_id,
 | 
				
			||||||
 | 
					            "Name": "config_name",
 | 
				
			||||||
 | 
					            "LocationUri": "luri",
 | 
				
			||||||
 | 
					            "Type": "freeform",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    update = client.update_configuration_profile(
 | 
				
			||||||
 | 
					        ApplicationId=app_id,
 | 
				
			||||||
 | 
					        ConfigurationProfileId=config_profile_id,
 | 
				
			||||||
 | 
					        Name="name2",
 | 
				
			||||||
 | 
					        Description="desc2",
 | 
				
			||||||
 | 
					        RetrievalRoleArn="rrarn:rrarn:rrarn:222",
 | 
				
			||||||
 | 
					        Validators=[],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    assert update["Name"] == "name2"
 | 
				
			||||||
 | 
					    assert update["RetrievalRoleArn"] == "rrarn:rrarn:rrarn:222"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.delete_configuration_profile(
 | 
				
			||||||
 | 
					        ApplicationId=app_id,
 | 
				
			||||||
 | 
					        ConfigurationProfileId=config_profile_id,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with pytest.raises(ClientError) as exc:
 | 
				
			||||||
 | 
					        client.get_configuration_profile(
 | 
				
			||||||
 | 
					            ApplicationId=app_id,
 | 
				
			||||||
 | 
					            ConfigurationProfileId=config_profile_id,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    err = exc.value.response["Error"]
 | 
				
			||||||
 | 
					    assert err["Code"] == "ResourceNotFoundException"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mock_appconfig
 | 
				
			||||||
 | 
					def test_tag_config_profile():
 | 
				
			||||||
 | 
					    client = boto3.client("appconfig", region_name="us-east-2")
 | 
				
			||||||
 | 
					    app_id = client.create_application(Name="testapp")["Id"]
 | 
				
			||||||
 | 
					    cp_id = client.create_configuration_profile(
 | 
				
			||||||
 | 
					        ApplicationId=app_id,
 | 
				
			||||||
 | 
					        Name="config_name",
 | 
				
			||||||
 | 
					        LocationUri="luri",
 | 
				
			||||||
 | 
					    )["Id"]
 | 
				
			||||||
 | 
					    cp_arn = f"arn:aws:appconfig:us-east-2:123456789012:application/{app_id}/configurationprofile/{cp_id}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tags = client.list_tags_for_resource(ResourceArn=cp_arn)["Tags"]
 | 
				
			||||||
 | 
					    assert tags == {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.tag_resource(
 | 
				
			||||||
 | 
					        ResourceArn=cp_arn,
 | 
				
			||||||
 | 
					        Tags={"k1": "v1"},
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tags = client.list_tags_for_resource(ResourceArn=cp_arn)["Tags"]
 | 
				
			||||||
 | 
					    assert tags == {"k1": "v1"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ####
 | 
				
			||||||
 | 
					    # Check this flow works when creating an app with tags
 | 
				
			||||||
 | 
					    app_id = client.create_application(Name="testapp")["Id"]
 | 
				
			||||||
 | 
					    cp_id = client.create_configuration_profile(
 | 
				
			||||||
 | 
					        ApplicationId=app_id,
 | 
				
			||||||
 | 
					        Name="config_name",
 | 
				
			||||||
 | 
					        LocationUri="luri",
 | 
				
			||||||
 | 
					        Tags={"k1": "v1"},
 | 
				
			||||||
 | 
					    )["Id"]
 | 
				
			||||||
 | 
					    cp_arn = f"arn:aws:appconfig:us-east-2:123456789012:application/{app_id}/configurationprofile/{cp_id}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tags = client.list_tags_for_resource(ResourceArn=cp_arn)["Tags"]
 | 
				
			||||||
 | 
					    assert tags == {"k1": "v1"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.tag_resource(
 | 
				
			||||||
 | 
					        ResourceArn=cp_arn,
 | 
				
			||||||
 | 
					        Tags={"k2": "v2", "k3": "v3"},
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tags = client.list_tags_for_resource(ResourceArn=cp_arn)["Tags"]
 | 
				
			||||||
 | 
					    assert tags == {"k1": "v1", "k2": "v2", "k3": "v3"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.untag_resource(ResourceArn=cp_arn, TagKeys=["k2"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tags = client.list_tags_for_resource(ResourceArn=cp_arn)["Tags"]
 | 
				
			||||||
 | 
					    assert tags == {"k1": "v1", "k3": "v3"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.untag_resource(ResourceArn=cp_arn, TagKeys=["k1", "k3"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tags = client.list_tags_for_resource(ResourceArn=cp_arn)["Tags"]
 | 
				
			||||||
 | 
					    assert tags == {}
 | 
				
			||||||
@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					import boto3
 | 
				
			||||||
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from botocore.exceptions import ClientError
 | 
				
			||||||
 | 
					from moto import mock_appconfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mock_appconfig
 | 
				
			||||||
 | 
					class TestHostedConfigurationVersions:
 | 
				
			||||||
 | 
					    def setup_method(self, *args):  # pylint: disable=unused-argument
 | 
				
			||||||
 | 
					        self.client = boto3.client("appconfig", region_name="us-west-1")
 | 
				
			||||||
 | 
					        self.app_id = self.client.create_application(Name="testapp")["Id"]
 | 
				
			||||||
 | 
					        self.config_profile_id = self.client.create_configuration_profile(
 | 
				
			||||||
 | 
					            ApplicationId=self.app_id,
 | 
				
			||||||
 | 
					            Name="config_name",
 | 
				
			||||||
 | 
					            Description="desc",
 | 
				
			||||||
 | 
					            LocationUri="luri",
 | 
				
			||||||
 | 
					            RetrievalRoleArn="rrarn:rrarn:rrarn:rrarn",
 | 
				
			||||||
 | 
					            Validators=[{"Type": "JSON", "Content": "c"}],
 | 
				
			||||||
 | 
					            Type="freeform",
 | 
				
			||||||
 | 
					        )["Id"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_create_hosted_configuration_version(self):
 | 
				
			||||||
 | 
					        resp = self.client.create_hosted_configuration_version(
 | 
				
			||||||
 | 
					            ApplicationId=self.app_id,
 | 
				
			||||||
 | 
					            ConfigurationProfileId=self.config_profile_id,
 | 
				
			||||||
 | 
					            Description="desc",
 | 
				
			||||||
 | 
					            Content=b"asdf",
 | 
				
			||||||
 | 
					            ContentType="text/xml",
 | 
				
			||||||
 | 
					            VersionLabel="vl",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        assert resp["ApplicationId"] == self.app_id
 | 
				
			||||||
 | 
					        assert resp["ConfigurationProfileId"] == self.config_profile_id
 | 
				
			||||||
 | 
					        assert resp["VersionNumber"] == 1
 | 
				
			||||||
 | 
					        assert resp["Description"] == "desc"
 | 
				
			||||||
 | 
					        assert resp["VersionLabel"] == "vl"
 | 
				
			||||||
 | 
					        assert resp["ContentType"] == "text/xml"
 | 
				
			||||||
 | 
					        assert resp["Content"].read() == b"asdf"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        resp = self.client.create_hosted_configuration_version(
 | 
				
			||||||
 | 
					            ApplicationId=self.app_id,
 | 
				
			||||||
 | 
					            ConfigurationProfileId=self.config_profile_id,
 | 
				
			||||||
 | 
					            Content=b"asdf",
 | 
				
			||||||
 | 
					            ContentType="text/xml",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        assert resp["VersionNumber"] == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_get_hosted_configuration_version(self):
 | 
				
			||||||
 | 
					        self.client.create_hosted_configuration_version(
 | 
				
			||||||
 | 
					            ApplicationId=self.app_id,
 | 
				
			||||||
 | 
					            ConfigurationProfileId=self.config_profile_id,
 | 
				
			||||||
 | 
					            Description="desc",
 | 
				
			||||||
 | 
					            Content=b"asdf",
 | 
				
			||||||
 | 
					            ContentType="text/xml",
 | 
				
			||||||
 | 
					            VersionLabel="vl",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        get = self.client.get_hosted_configuration_version(
 | 
				
			||||||
 | 
					            ApplicationId=self.app_id,
 | 
				
			||||||
 | 
					            ConfigurationProfileId=self.config_profile_id,
 | 
				
			||||||
 | 
					            VersionNumber=1,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        assert get["ApplicationId"] == self.app_id
 | 
				
			||||||
 | 
					        assert get["ConfigurationProfileId"] == self.config_profile_id
 | 
				
			||||||
 | 
					        assert get["Description"] == "desc"
 | 
				
			||||||
 | 
					        assert get["VersionLabel"] == "vl"
 | 
				
			||||||
 | 
					        assert get["ContentType"] == "text/xml"
 | 
				
			||||||
 | 
					        assert get["Content"].read() == b"asdf"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_delete_hosted_configuration_version(self):
 | 
				
			||||||
 | 
					        self.client.create_hosted_configuration_version(
 | 
				
			||||||
 | 
					            ApplicationId=self.app_id,
 | 
				
			||||||
 | 
					            ConfigurationProfileId=self.config_profile_id,
 | 
				
			||||||
 | 
					            Content=b"asdf",
 | 
				
			||||||
 | 
					            ContentType="text/xml",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.client.delete_hosted_configuration_version(
 | 
				
			||||||
 | 
					            ApplicationId=self.app_id,
 | 
				
			||||||
 | 
					            ConfigurationProfileId=self.config_profile_id,
 | 
				
			||||||
 | 
					            VersionNumber=1,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        with pytest.raises(ClientError) as exc:
 | 
				
			||||||
 | 
					            self.client.get_hosted_configuration_version(
 | 
				
			||||||
 | 
					                ApplicationId=self.app_id,
 | 
				
			||||||
 | 
					                ConfigurationProfileId=self.config_profile_id,
 | 
				
			||||||
 | 
					                VersionNumber=1,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        err = exc.value.response["Error"]
 | 
				
			||||||
 | 
					        assert err["Code"] == "ResourceNotFoundException"
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user