Feature: Managed Prometheus (AMP) (#5441)
This commit is contained in:
parent
f23b44e256
commit
a2a1967ef8
@ -20,6 +20,33 @@
|
||||
- [ ] update_certificate_options
|
||||
</details>
|
||||
|
||||
## amp
|
||||
<details>
|
||||
<summary>61% implemented</summary>
|
||||
|
||||
- [ ] create_alert_manager_definition
|
||||
- [ ] create_logging_configuration
|
||||
- [X] create_rule_groups_namespace
|
||||
- [X] create_workspace
|
||||
- [ ] delete_alert_manager_definition
|
||||
- [ ] delete_logging_configuration
|
||||
- [X] delete_rule_groups_namespace
|
||||
- [X] delete_workspace
|
||||
- [ ] describe_alert_manager_definition
|
||||
- [ ] describe_logging_configuration
|
||||
- [X] describe_rule_groups_namespace
|
||||
- [X] describe_workspace
|
||||
- [X] list_rule_groups_namespaces
|
||||
- [X] list_tags_for_resource
|
||||
- [X] list_workspaces
|
||||
- [ ] put_alert_manager_definition
|
||||
- [X] put_rule_groups_namespace
|
||||
- [X] tag_resource
|
||||
- [X] untag_resource
|
||||
- [ ] update_logging_configuration
|
||||
- [X] update_workspace_alias
|
||||
</details>
|
||||
|
||||
## apigateway
|
||||
<details>
|
||||
<summary>65% implemented</summary>
|
||||
@ -6224,7 +6251,6 @@
|
||||
- account
|
||||
- acm-pca
|
||||
- alexaforbusiness
|
||||
- amp
|
||||
- amplify
|
||||
- amplifybackend
|
||||
- amplifyuibuilder
|
||||
|
75
docs/docs/services/amp.rst
Normal file
75
docs/docs/services/amp.rst
Normal file
@ -0,0 +1,75 @@
|
||||
.. _implementedservice_amp:
|
||||
|
||||
.. |start-h3| raw:: html
|
||||
|
||||
<h3>
|
||||
|
||||
.. |end-h3| raw:: html
|
||||
|
||||
</h3>
|
||||
|
||||
===
|
||||
amp
|
||||
===
|
||||
|
||||
.. autoclass:: moto.amp.models.PrometheusServiceBackend
|
||||
|
||||
|start-h3| Example usage |end-h3|
|
||||
|
||||
.. sourcecode:: python
|
||||
|
||||
@mock_amp
|
||||
def test_amp_behaviour:
|
||||
boto3.client("amp")
|
||||
...
|
||||
|
||||
|
||||
|
||||
|start-h3| Implemented features for this service |end-h3|
|
||||
|
||||
- [ ] create_alert_manager_definition
|
||||
- [ ] create_logging_configuration
|
||||
- [X] create_rule_groups_namespace
|
||||
|
||||
The ClientToken-parameter is not yet implemented
|
||||
|
||||
|
||||
- [X] create_workspace
|
||||
|
||||
The ClientToken-parameter is not yet implemented
|
||||
|
||||
|
||||
- [ ] delete_alert_manager_definition
|
||||
- [ ] delete_logging_configuration
|
||||
- [X] delete_rule_groups_namespace
|
||||
|
||||
The ClientToken-parameter is not yet implemented
|
||||
|
||||
|
||||
- [X] delete_workspace
|
||||
|
||||
The ClientToken-parameter is not yet implemented
|
||||
|
||||
|
||||
- [ ] describe_alert_manager_definition
|
||||
- [ ] describe_logging_configuration
|
||||
- [X] describe_rule_groups_namespace
|
||||
- [X] describe_workspace
|
||||
- [X] list_rule_groups_namespaces
|
||||
- [X] list_tags_for_resource
|
||||
- [X] list_workspaces
|
||||
- [ ] put_alert_manager_definition
|
||||
- [X] put_rule_groups_namespace
|
||||
|
||||
The ClientToken-parameter is not yet implemented
|
||||
|
||||
|
||||
- [X] tag_resource
|
||||
- [X] untag_resource
|
||||
- [ ] update_logging_configuration
|
||||
- [X] update_workspace_alias
|
||||
|
||||
The ClientToken-parameter is not yet implemented
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@ def lazy_load(module_name, element, boto3_name=None, backend=None):
|
||||
|
||||
|
||||
mock_acm = lazy_load(".acm", "mock_acm")
|
||||
mock_amp = lazy_load(".amp", "mock_amp")
|
||||
mock_apigateway = lazy_load(".apigateway", "mock_apigateway")
|
||||
mock_apigatewayv2 = lazy_load(".apigatewayv2", "mock_apigatewayv2")
|
||||
mock_appsync = lazy_load(".appsync", "mock_appsync")
|
||||
|
5
moto/amp/__init__.py
Normal file
5
moto/amp/__init__.py
Normal file
@ -0,0 +1,5 @@
|
||||
"""amp module initialization; sets value for base decorator."""
|
||||
from .models import amp_backends
|
||||
from ..core.models import base_decorator
|
||||
|
||||
mock_amp = base_decorator(amp_backends)
|
40
moto/amp/exceptions.py
Normal file
40
moto/amp/exceptions.py
Normal file
@ -0,0 +1,40 @@
|
||||
import json
|
||||
from moto.core.exceptions import JsonRESTError
|
||||
|
||||
|
||||
class AmpException(JsonRESTError):
|
||||
pass
|
||||
|
||||
|
||||
class ResourceNotFoundException(AmpException):
|
||||
def __init__(self, message, resource_id, resource_type):
|
||||
super().__init__("ResourceNotFoundException", message)
|
||||
self.description = json.dumps(
|
||||
{
|
||||
"resourceId": resource_id,
|
||||
"message": self.message,
|
||||
"resourceType": resource_type,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class WorkspaceNotFound(ResourceNotFoundException):
|
||||
code = 404
|
||||
|
||||
def __init__(self, workspace_id):
|
||||
super().__init__(
|
||||
"Workspace not found",
|
||||
resource_id=workspace_id,
|
||||
resource_type="AWS::APS::Workspace",
|
||||
)
|
||||
|
||||
|
||||
class RuleGroupNamespaceNotFound(ResourceNotFoundException):
|
||||
code = 404
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__(
|
||||
"RuleGroupNamespace not found",
|
||||
resource_id=name,
|
||||
resource_type="AWS::APS::RuleGroupNamespace",
|
||||
)
|
168
moto/amp/models.py
Normal file
168
moto/amp/models.py
Normal file
@ -0,0 +1,168 @@
|
||||
"""PrometheusServiceBackend class with methods for supported APIs."""
|
||||
|
||||
from moto.core import BaseBackend, BaseModel
|
||||
from moto.core.utils import BackendDict, unix_time
|
||||
from moto.utilities.paginator import paginate
|
||||
from moto.utilities.tagging_service import TaggingService
|
||||
from typing import Dict
|
||||
from uuid import uuid4
|
||||
from .exceptions import RuleGroupNamespaceNotFound, WorkspaceNotFound
|
||||
from .utils import PAGINATION_MODEL
|
||||
|
||||
|
||||
class RuleGroupNamespace(BaseModel):
|
||||
def __init__(self, account_id, region, workspace_id, name, data, tag_fn):
|
||||
self.name = name
|
||||
self.data = data
|
||||
self.tag_fn = tag_fn
|
||||
self.arn = f"arn:aws:aps:{region}:{account_id}:rulegroupsnamespace/{workspace_id}/{self.name}"
|
||||
self.created_at = unix_time()
|
||||
self.modified_at = self.created_at
|
||||
|
||||
def update(self, new_data):
|
||||
self.data = new_data
|
||||
self.modified_at = unix_time()
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"name": self.name,
|
||||
"arn": self.arn,
|
||||
"status": {"statusCode": "ACTIVE"},
|
||||
"createdAt": self.created_at,
|
||||
"modifiedAt": self.modified_at,
|
||||
"data": self.data,
|
||||
"tags": self.tag_fn(self.arn),
|
||||
}
|
||||
|
||||
|
||||
class Workspace(BaseModel):
|
||||
def __init__(self, account_id, region, alias, tag_fn):
|
||||
self.alias = alias
|
||||
self.workspace_id = f"ws-{uuid4()}"
|
||||
self.arn = f"arn:aws:aps:{region}:{account_id}:workspace/{self.workspace_id}"
|
||||
self.endpoint = f"https://aps-workspaces.{region}.amazonaws.com/workspaces/{self.workspace_id}/"
|
||||
self.status = {"statusCode": "ACTIVE"}
|
||||
self.created_at = unix_time()
|
||||
self.tag_fn = tag_fn
|
||||
self.rule_group_namespaces = dict()
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"alias": self.alias,
|
||||
"arn": self.arn,
|
||||
"workspaceId": self.workspace_id,
|
||||
"status": self.status,
|
||||
"createdAt": self.created_at,
|
||||
"prometheusEndpoint": self.endpoint,
|
||||
"tags": self.tag_fn(self.arn),
|
||||
}
|
||||
|
||||
|
||||
class PrometheusServiceBackend(BaseBackend):
|
||||
"""Implementation of PrometheusService APIs."""
|
||||
|
||||
def __init__(self, region_name, account_id):
|
||||
super().__init__(region_name, account_id)
|
||||
self.workspaces: Dict(str, Workspace) = dict()
|
||||
self.tagger = TaggingService()
|
||||
|
||||
def create_workspace(self, alias, tags):
|
||||
"""
|
||||
The ClientToken-parameter is not yet implemented
|
||||
"""
|
||||
workspace = Workspace(
|
||||
self.account_id,
|
||||
self.region_name,
|
||||
alias=alias,
|
||||
tag_fn=self.list_tags_for_resource,
|
||||
)
|
||||
self.workspaces[workspace.workspace_id] = workspace
|
||||
self.tag_resource(workspace.arn, tags)
|
||||
return workspace
|
||||
|
||||
def describe_workspace(self, workspace_id) -> Workspace:
|
||||
if workspace_id not in self.workspaces:
|
||||
raise WorkspaceNotFound(workspace_id)
|
||||
return self.workspaces[workspace_id]
|
||||
|
||||
def list_tags_for_resource(self, resource_arn):
|
||||
return self.tagger.get_tag_dict_for_resource(resource_arn)
|
||||
|
||||
def update_workspace_alias(self, alias, workspace_id):
|
||||
"""
|
||||
The ClientToken-parameter is not yet implemented
|
||||
"""
|
||||
self.workspaces[workspace_id].alias = alias
|
||||
|
||||
def delete_workspace(self, workspace_id):
|
||||
"""
|
||||
The ClientToken-parameter is not yet implemented
|
||||
"""
|
||||
self.workspaces.pop(workspace_id, None)
|
||||
|
||||
@paginate(pagination_model=PAGINATION_MODEL)
|
||||
def list_workspaces(self, alias):
|
||||
if alias:
|
||||
return [w for w in self.workspaces.values() if w.alias == alias]
|
||||
return list(self.workspaces.values())
|
||||
|
||||
def tag_resource(self, resource_arn, tags):
|
||||
tags = self.tagger.convert_dict_to_tags_input(tags)
|
||||
self.tagger.tag_resource(resource_arn, tags)
|
||||
|
||||
def untag_resource(self, resource_arn, tag_keys):
|
||||
self.tagger.untag_resource_using_names(resource_arn, tag_keys)
|
||||
|
||||
def create_rule_groups_namespace(
|
||||
self, data, name, tags, workspace_id
|
||||
) -> RuleGroupNamespace:
|
||||
"""
|
||||
The ClientToken-parameter is not yet implemented
|
||||
"""
|
||||
workspace = self.describe_workspace(workspace_id)
|
||||
group = RuleGroupNamespace(
|
||||
account_id=self.account_id,
|
||||
region=self.region_name,
|
||||
workspace_id=workspace_id,
|
||||
name=name,
|
||||
data=data,
|
||||
tag_fn=self.list_tags_for_resource,
|
||||
)
|
||||
workspace.rule_group_namespaces[name] = group
|
||||
self.tag_resource(group.arn, tags)
|
||||
return group
|
||||
|
||||
def delete_rule_groups_namespace(self, name, workspace_id) -> None:
|
||||
"""
|
||||
The ClientToken-parameter is not yet implemented
|
||||
"""
|
||||
ws = self.describe_workspace(workspace_id)
|
||||
ws.rule_group_namespaces.pop(name, None)
|
||||
|
||||
def describe_rule_groups_namespace(self, name, workspace_id) -> RuleGroupNamespace:
|
||||
ws = self.describe_workspace(workspace_id)
|
||||
if name not in ws.rule_group_namespaces:
|
||||
raise RuleGroupNamespaceNotFound(name=name)
|
||||
return ws.rule_group_namespaces[name]
|
||||
|
||||
def put_rule_groups_namespace(self, data, name, workspace_id) -> RuleGroupNamespace:
|
||||
"""
|
||||
The ClientToken-parameter is not yet implemented
|
||||
"""
|
||||
ns = self.describe_rule_groups_namespace(name=name, workspace_id=workspace_id)
|
||||
ns.update(data)
|
||||
return ns
|
||||
|
||||
@paginate(pagination_model=PAGINATION_MODEL)
|
||||
def list_rule_groups_namespaces(self, name, workspace_id):
|
||||
ws = self.describe_workspace(workspace_id)
|
||||
if name:
|
||||
return [
|
||||
ns
|
||||
for ns_name, ns in ws.rule_group_namespaces.items()
|
||||
if ns_name.startswith(name)
|
||||
]
|
||||
return list(ws.rule_group_namespaces.values())
|
||||
|
||||
|
||||
amp_backends = BackendDict(PrometheusServiceBackend, "amp")
|
141
moto/amp/responses.py
Normal file
141
moto/amp/responses.py
Normal file
@ -0,0 +1,141 @@
|
||||
"""Handles incoming amp requests, invokes methods, returns responses."""
|
||||
import json
|
||||
|
||||
from moto.core.responses import BaseResponse
|
||||
from .models import amp_backends, PrometheusServiceBackend
|
||||
from urllib.parse import unquote
|
||||
|
||||
|
||||
class PrometheusServiceResponse(BaseResponse):
|
||||
"""Handler for PrometheusService requests and responses."""
|
||||
|
||||
def tags(self, request, full_url, headers):
|
||||
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):
|
||||
super().__init__(service_name="amp")
|
||||
|
||||
@property
|
||||
def amp_backend(self) -> PrometheusServiceBackend:
|
||||
"""Return backend instance specific for this region."""
|
||||
return amp_backends[self.current_account][self.region]
|
||||
|
||||
def create_workspace(self):
|
||||
params = json.loads(self.body)
|
||||
alias = params.get("alias")
|
||||
tags = params.get("tags")
|
||||
workspace = self.amp_backend.create_workspace(alias=alias, tags=tags)
|
||||
return json.dumps(dict(workspace.to_dict()))
|
||||
|
||||
def describe_workspace(self):
|
||||
workspace_id = self.path.split("/")[-1]
|
||||
workspace = self.amp_backend.describe_workspace(workspace_id=workspace_id)
|
||||
return json.dumps(dict(workspace=workspace.to_dict()))
|
||||
|
||||
def list_tags_for_resource(self):
|
||||
resource_arn = unquote(self.path).split("tags/")[-1]
|
||||
tags = self.amp_backend.list_tags_for_resource(resource_arn=resource_arn)
|
||||
return json.dumps(dict(tags=tags))
|
||||
|
||||
def update_workspace_alias(self):
|
||||
params = json.loads(self.body)
|
||||
alias = params.get("alias")
|
||||
workspace_id = self.path.split("/")[-2]
|
||||
self.amp_backend.update_workspace_alias(alias=alias, workspace_id=workspace_id)
|
||||
return json.dumps(dict())
|
||||
|
||||
def delete_workspace(self):
|
||||
workspace_id = self.path.split("/")[-1]
|
||||
self.amp_backend.delete_workspace(workspace_id=workspace_id)
|
||||
return json.dumps(dict())
|
||||
|
||||
def list_workspaces(self):
|
||||
alias = self._get_param("alias")
|
||||
max_results = self._get_int_param("maxResults")
|
||||
next_token = self._get_param("nextToken")
|
||||
workspaces, next_token = self.amp_backend.list_workspaces(
|
||||
alias, max_results=max_results, next_token=next_token
|
||||
)
|
||||
return json.dumps(
|
||||
{"nextToken": next_token, "workspaces": [w.to_dict() for w in workspaces]}
|
||||
)
|
||||
|
||||
def tag_resource(self):
|
||||
params = json.loads(self.body)
|
||||
resource_arn = unquote(self.path).split("tags/")[-1]
|
||||
tags = params.get("tags")
|
||||
self.amp_backend.tag_resource(resource_arn=resource_arn, tags=tags)
|
||||
return json.dumps(dict())
|
||||
|
||||
def untag_resource(self):
|
||||
resource_arn = unquote(self.path).split("tags/")[-1]
|
||||
tag_keys = self.querystring.get("tagKeys", [])
|
||||
self.amp_backend.untag_resource(resource_arn=resource_arn, tag_keys=tag_keys)
|
||||
return json.dumps(dict())
|
||||
|
||||
def create_rule_groups_namespace(self):
|
||||
params = json.loads(self.body)
|
||||
data = params.get("data")
|
||||
name = params.get("name")
|
||||
tags = params.get("tags")
|
||||
workspace_id = unquote(self.path).split("/")[-2]
|
||||
rule_group_namespace = self.amp_backend.create_rule_groups_namespace(
|
||||
data=data,
|
||||
name=name,
|
||||
tags=tags,
|
||||
workspace_id=workspace_id,
|
||||
)
|
||||
return json.dumps(rule_group_namespace.to_dict())
|
||||
|
||||
def delete_rule_groups_namespace(self):
|
||||
name = unquote(self.path).split("/")[-1]
|
||||
workspace_id = unquote(self.path).split("/")[-3]
|
||||
self.amp_backend.delete_rule_groups_namespace(
|
||||
name=name,
|
||||
workspace_id=workspace_id,
|
||||
)
|
||||
return json.dumps(dict())
|
||||
|
||||
def describe_rule_groups_namespace(self):
|
||||
name = unquote(self.path).split("/")[-1]
|
||||
workspace_id = unquote(self.path).split("/")[-3]
|
||||
ns = self.amp_backend.describe_rule_groups_namespace(
|
||||
name=name, workspace_id=workspace_id
|
||||
)
|
||||
return json.dumps(dict(ruleGroupsNamespace=ns.to_dict()))
|
||||
|
||||
def put_rule_groups_namespace(self):
|
||||
params = json.loads(self.body)
|
||||
data = params.get("data")
|
||||
name = unquote(self.path).split("/")[-1]
|
||||
workspace_id = unquote(self.path).split("/")[-3]
|
||||
ns = self.amp_backend.put_rule_groups_namespace(
|
||||
data=data,
|
||||
name=name,
|
||||
workspace_id=workspace_id,
|
||||
)
|
||||
return json.dumps(ns.to_dict())
|
||||
|
||||
def list_rule_groups_namespaces(self):
|
||||
max_results = self._get_int_param("maxResults")
|
||||
next_token = self._get_param("nextToken")
|
||||
name = self._get_param("name")
|
||||
workspace_id = unquote(self.path).split("/")[-2]
|
||||
namespaces, next_token = self.amp_backend.list_rule_groups_namespaces(
|
||||
max_results=max_results,
|
||||
name=name,
|
||||
next_token=next_token,
|
||||
workspace_id=workspace_id,
|
||||
)
|
||||
return json.dumps(
|
||||
dict(
|
||||
nextToken=next_token,
|
||||
ruleGroupsNamespaces=[ns.to_dict() for ns in namespaces],
|
||||
)
|
||||
)
|
21
moto/amp/urls.py
Normal file
21
moto/amp/urls.py
Normal file
@ -0,0 +1,21 @@
|
||||
"""amp base URL and path."""
|
||||
from .responses import PrometheusServiceResponse
|
||||
|
||||
url_bases = [
|
||||
r"https?://aps\.(.+)\.amazonaws\.com",
|
||||
]
|
||||
|
||||
|
||||
response = PrometheusServiceResponse()
|
||||
|
||||
|
||||
url_paths = {
|
||||
"{0}/workspaces$": response.dispatch,
|
||||
"{0}/workspaces/(?P<workspace_id>[^/]+)$": response.dispatch,
|
||||
"{0}/workspaces/(?P<workspace_id>[^/]+)/alias$": response.dispatch,
|
||||
"{0}/workspaces/(?P<workspace_id>[^/]+)/rulegroupsnamespaces$": response.dispatch,
|
||||
"{0}/workspaces/(?P<workspace_id>[^/]+)/rulegroupsnamespaces/(?P<name>[^/]+)$": response.dispatch,
|
||||
"{0}/tags/(?P<resource_arn>[^/]+)$": response.dispatch,
|
||||
"{0}/tags/(?P<arn_prefix>[^/]+)/(?P<workspace_id>[^/]+)$": response.tags,
|
||||
"{0}/tags/(?P<arn_prefix>[^/]+)/(?P<workspace_id>[^/]+)/(?P<ns_name>[^/]+)$": response.tags,
|
||||
}
|
14
moto/amp/utils.py
Normal file
14
moto/amp/utils.py
Normal file
@ -0,0 +1,14 @@
|
||||
PAGINATION_MODEL = {
|
||||
"list_workspaces": {
|
||||
"input_token": "next_token",
|
||||
"limit_key": "max_results",
|
||||
"limit_default": 100, # This should be the sum of the directory limits
|
||||
"unique_attribute": "arn",
|
||||
},
|
||||
"list_rule_groups_namespaces": {
|
||||
"input_token": "next_token",
|
||||
"limit_key": "max_results",
|
||||
"limit_default": 100, # This should be the sum of the directory limits
|
||||
"unique_attribute": "name",
|
||||
},
|
||||
}
|
@ -3,6 +3,7 @@ import re
|
||||
|
||||
backend_url_patterns = [
|
||||
("acm", re.compile("https?://acm\\.(.+)\\.amazonaws\\.com")),
|
||||
("amp", re.compile("https?://aps\\.(.+)\\.amazonaws\\.com")),
|
||||
("apigateway", re.compile("https?://apigateway\\.(.+)\\.amazonaws.com")),
|
||||
(
|
||||
"applicationautoscaling",
|
||||
|
@ -1,5 +1,8 @@
|
||||
acm:
|
||||
- TestAccACMCertificateDataSource
|
||||
amp:
|
||||
- TestAccAMPWorkspace
|
||||
- TestAccAMPRuleGroupNamespace
|
||||
apigateway:
|
||||
- TestAccAPIGatewayGatewayResponse
|
||||
apigatewayv2:
|
||||
|
0
tests/test_amp/__init__.py
Normal file
0
tests/test_amp/__init__.py
Normal file
173
tests/test_amp/test_amp_rulegroupnamespaces.py
Normal file
173
tests/test_amp/test_amp_rulegroupnamespaces.py
Normal file
@ -0,0 +1,173 @@
|
||||
"""Unit tests for amp-supported APIs."""
|
||||
import boto3
|
||||
import pytest
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from moto import mock_amp
|
||||
|
||||
# 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_amp
|
||||
def test_create_rule_groups_namespace():
|
||||
client = boto3.client("amp", region_name="ap-southeast-1")
|
||||
workspace_id = client.create_workspace()["workspaceId"]
|
||||
resp = client.create_rule_groups_namespace(
|
||||
data=b"asdf", name="my first rule group", workspaceId=workspace_id
|
||||
)
|
||||
|
||||
resp.should.have.key("arn")
|
||||
resp.should.have.key("name").equals("my first rule group")
|
||||
resp.should.have.key("status")
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_delete_rule_groups_namespace():
|
||||
client = boto3.client("amp", region_name="us-east-2")
|
||||
workspace_id = client.create_workspace()["workspaceId"]
|
||||
client.create_rule_groups_namespace(
|
||||
data=b"asdf", name="myname", workspaceId=workspace_id
|
||||
)
|
||||
|
||||
client.delete_rule_groups_namespace(name="myname", workspaceId=workspace_id)
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
client.describe_rule_groups_namespace(name="myname", workspaceId=workspace_id)
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("ResourceNotFoundException")
|
||||
err["Message"].should.equal("RuleGroupNamespace not found")
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_describe_rule_groups_namespace():
|
||||
client = boto3.client("amp", region_name="us-east-2")
|
||||
|
||||
workspace_id = client.create_workspace()["workspaceId"]
|
||||
client.create_rule_groups_namespace(
|
||||
data=b"asdf", name="myname", workspaceId=workspace_id
|
||||
)
|
||||
|
||||
resp = client.describe_rule_groups_namespace(
|
||||
name="myname", workspaceId=workspace_id
|
||||
)
|
||||
resp.should.have.key("ruleGroupsNamespace")
|
||||
ns = resp["ruleGroupsNamespace"]
|
||||
|
||||
ns.should.have.key("arn")
|
||||
ns.should.have.key("createdAt")
|
||||
ns.should.have.key("data").equals(b"asdf")
|
||||
ns.should.have.key("modifiedAt")
|
||||
ns.should.have.key("name").equals("myname")
|
||||
ns.should.have.key("status")
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_put_rule_groups_namespace():
|
||||
client = boto3.client("amp", region_name="eu-west-1")
|
||||
|
||||
workspace_id = client.create_workspace()["workspaceId"]
|
||||
client.create_rule_groups_namespace(
|
||||
data=b"asdf", name="myname", workspaceId=workspace_id
|
||||
)
|
||||
|
||||
client.put_rule_groups_namespace(
|
||||
name="myname", workspaceId=workspace_id, data=b"updated"
|
||||
)
|
||||
|
||||
resp = client.describe_rule_groups_namespace(
|
||||
name="myname", workspaceId=workspace_id
|
||||
)
|
||||
resp.should.have.key("ruleGroupsNamespace")
|
||||
ns = resp["ruleGroupsNamespace"]
|
||||
|
||||
ns.should.have.key("arn")
|
||||
ns.should.have.key("createdAt")
|
||||
ns.should.have.key("data").equals(b"updated")
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_list_rule_groups_namespaces():
|
||||
client = boto3.client("amp", region_name="ap-southeast-1")
|
||||
w_id = client.create_workspace()["workspaceId"]
|
||||
for idx in range(15):
|
||||
client.create_rule_groups_namespace(
|
||||
data=b"a", name=f"ns{idx}", workspaceId=w_id
|
||||
)
|
||||
|
||||
resp = client.list_rule_groups_namespaces(workspaceId=w_id)
|
||||
resp.should.have.key("ruleGroupsNamespaces").length_of(15)
|
||||
resp.shouldnt.have.key("nextToken")
|
||||
|
||||
resp = client.list_rule_groups_namespaces(workspaceId=w_id, name="ns1")
|
||||
resp.should.have.key("ruleGroupsNamespaces").length_of(6)
|
||||
names = [ns["name"] for ns in resp["ruleGroupsNamespaces"]]
|
||||
set(names).should.equal({"ns10", "ns13", "ns1", "ns12", "ns11", "ns14"})
|
||||
|
||||
resp = client.list_rule_groups_namespaces(workspaceId=w_id, name="ns10")
|
||||
resp.should.have.key("ruleGroupsNamespaces").length_of(1)
|
||||
names = [ns["name"] for ns in resp["ruleGroupsNamespaces"]]
|
||||
set(names).should.equal({"ns10"})
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_list_rule_groups_namespaces__paginated():
|
||||
client = boto3.client("amp", region_name="ap-southeast-1")
|
||||
w_id = client.create_workspace()["workspaceId"]
|
||||
for idx in range(125):
|
||||
client.create_rule_groups_namespace(
|
||||
data=b"a", name=f"ns{idx}", workspaceId=w_id
|
||||
)
|
||||
|
||||
# default pagesize is 100
|
||||
page1 = client.list_rule_groups_namespaces(workspaceId=w_id)
|
||||
page1.should.have.key("ruleGroupsNamespaces").length_of(100)
|
||||
page1.should.have.key("nextToken")
|
||||
|
||||
# We can ask for a smaller pagesize
|
||||
page2 = client.list_rule_groups_namespaces(
|
||||
workspaceId=w_id, maxResults=15, nextToken=page1["nextToken"]
|
||||
)
|
||||
page2.should.have.key("ruleGroupsNamespaces").length_of(15)
|
||||
page2.should.have.key("nextToken")
|
||||
|
||||
page3 = client.list_rule_groups_namespaces(
|
||||
workspaceId=w_id, maxResults=15, nextToken=page2["nextToken"]
|
||||
)
|
||||
page3.should.have.key("ruleGroupsNamespaces").length_of(10)
|
||||
page3.shouldnt.have.key("nextToken")
|
||||
|
||||
# We could request all of them in one go
|
||||
full_page = client.list_rule_groups_namespaces(workspaceId=w_id, maxResults=150)
|
||||
full_page.should.have.key("ruleGroupsNamespaces").length_of(125)
|
||||
full_page.shouldnt.have.key("nextToken")
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_tag_resource():
|
||||
client = boto3.client("amp", region_name="us-east-2")
|
||||
|
||||
w_id = client.create_workspace()["workspaceId"]
|
||||
ns = client.create_rule_groups_namespace(
|
||||
data=b"a", name="ns", workspaceId=w_id, tags={"t": "v"}
|
||||
)
|
||||
|
||||
arn = ns["arn"]
|
||||
|
||||
client.tag_resource(resourceArn=arn, tags={"t1": "v1", "t2": "v2"})
|
||||
|
||||
client.list_tags_for_resource(resourceArn=arn)["tags"].should.equal(
|
||||
{"t": "v", "t1": "v1", "t2": "v2"}
|
||||
)
|
||||
client.describe_rule_groups_namespace(workspaceId=w_id, name="ns")[
|
||||
"ruleGroupsNamespace"
|
||||
]["tags"].should.equal({"t": "v", "t1": "v1", "t2": "v2"})
|
||||
|
||||
client.untag_resource(resourceArn=arn, tagKeys=["t1"])
|
||||
client.list_tags_for_resource(resourceArn=arn)["tags"].should.equal(
|
||||
{"t": "v", "t2": "v2"}
|
||||
)
|
||||
|
||||
client.untag_resource(resourceArn=arn, tagKeys=["t", "t2"])
|
||||
client.list_tags_for_resource(resourceArn=arn)["tags"].should.equal({})
|
149
tests/test_amp/test_amp_workspaces.py
Normal file
149
tests/test_amp/test_amp_workspaces.py
Normal file
@ -0,0 +1,149 @@
|
||||
import boto3
|
||||
import pytest
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from moto import mock_amp
|
||||
|
||||
# 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_amp
|
||||
def test_create_workspace():
|
||||
client = boto3.client("amp", region_name="ap-southeast-1")
|
||||
resp = client.create_workspace(alias="test", clientToken="mytoken")
|
||||
|
||||
resp.should.have.key("arn")
|
||||
resp.should.have.key("status").equals({"statusCode": "ACTIVE"})
|
||||
resp.should.have.key("workspaceId")
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_describe_workspace():
|
||||
client = boto3.client("amp", region_name="eu-west-1")
|
||||
workspace_id = client.create_workspace(alias="test", clientToken="mytoken")[
|
||||
"workspaceId"
|
||||
]
|
||||
|
||||
resp = client.describe_workspace(workspaceId=workspace_id)
|
||||
resp.should.have.key("workspace")
|
||||
|
||||
workspace = resp["workspace"]
|
||||
workspace.should.have.key("alias")
|
||||
workspace.should.have.key("arn")
|
||||
workspace.should.have.key("createdAt")
|
||||
workspace.should.have.key("prometheusEndpoint")
|
||||
workspace.should.have.key("status").equals({"statusCode": "ACTIVE"})
|
||||
workspace.should.have.key("workspaceId").equals(workspace_id)
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_list_workspaces():
|
||||
client = boto3.client("amp", region_name="ap-southeast-1")
|
||||
client.create_workspace(alias="test")
|
||||
client.create_workspace(alias="another")
|
||||
client.create_workspace()
|
||||
|
||||
resp = client.list_workspaces()
|
||||
resp.should.have.key("workspaces").length_of(3)
|
||||
resp.shouldnt.have.key("nextToken")
|
||||
|
||||
resp = client.list_workspaces(alias="another")
|
||||
resp.should.have.key("workspaces").length_of(1)
|
||||
resp["workspaces"][0].should.have.key("alias").equals("another")
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_list_workspaces__paginated():
|
||||
client = boto3.client("amp", region_name="ap-southeast-1")
|
||||
for _ in range(125):
|
||||
client.create_workspace()
|
||||
|
||||
# default pagesize is 100
|
||||
page1 = client.list_workspaces()
|
||||
page1.should.have.key("workspaces").length_of(100)
|
||||
page1.should.have.key("nextToken")
|
||||
|
||||
# We can ask for a smaller pagesize
|
||||
page2 = client.list_workspaces(maxResults=15, nextToken=page1["nextToken"])
|
||||
page2.should.have.key("workspaces").length_of(15)
|
||||
page2.should.have.key("nextToken")
|
||||
|
||||
page3 = client.list_workspaces(maxResults=15, nextToken=page2["nextToken"])
|
||||
page3.should.have.key("workspaces").length_of(10)
|
||||
page3.shouldnt.have.key("nextToken")
|
||||
|
||||
# We could request all of them in one go
|
||||
full_page = client.list_workspaces(maxResults=150)
|
||||
full_page.should.have.key("workspaces").length_of(125)
|
||||
full_page.shouldnt.have.key("nextToken")
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_list_tags_for_resource():
|
||||
client = boto3.client("amp", region_name="ap-southeast-1")
|
||||
arn = client.create_workspace(
|
||||
alias="test", clientToken="mytoken", tags={"t1": "v1", "t2": "v2"}
|
||||
)["arn"]
|
||||
|
||||
resp = client.list_tags_for_resource(resourceArn=arn)
|
||||
resp.should.have.key("tags").equals({"t1": "v1", "t2": "v2"})
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_update_workspace_alias():
|
||||
client = boto3.client("amp", region_name="ap-southeast-1")
|
||||
|
||||
workspace_id = client.create_workspace(alias="initial")["workspaceId"]
|
||||
|
||||
w = client.describe_workspace(workspaceId=workspace_id)["workspace"]
|
||||
w.should.have.key("alias").equals("initial")
|
||||
|
||||
client.update_workspace_alias(alias="updated", workspaceId=workspace_id)
|
||||
|
||||
w = client.describe_workspace(workspaceId=workspace_id)["workspace"]
|
||||
w.should.have.key("alias").equals("updated")
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_delete_workspace():
|
||||
client = boto3.client("amp", region_name="us-east-2")
|
||||
|
||||
workspace_id = client.create_workspace(alias="test", clientToken="mytoken")[
|
||||
"workspaceId"
|
||||
]
|
||||
|
||||
client.delete_workspace(workspaceId=workspace_id)
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
client.describe_workspace(workspaceId=workspace_id)
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("ResourceNotFoundException")
|
||||
err["Message"].should.equal("Workspace not found")
|
||||
|
||||
|
||||
@mock_amp
|
||||
def test_tag_resource():
|
||||
client = boto3.client("amp", region_name="us-east-2")
|
||||
|
||||
workspace = client.create_workspace(alias="test", tags={"t": "v"})
|
||||
arn = workspace["arn"]
|
||||
workspace_id = workspace["workspaceId"]
|
||||
|
||||
client.tag_resource(resourceArn=arn, tags={"t1": "v1", "t2": "v2"})
|
||||
|
||||
client.list_tags_for_resource(resourceArn=arn)["tags"].should.equal(
|
||||
{"t": "v", "t1": "v1", "t2": "v2"}
|
||||
)
|
||||
client.describe_workspace(workspaceId=workspace_id)["workspace"][
|
||||
"tags"
|
||||
].should.equal({"t": "v", "t1": "v1", "t2": "v2"})
|
||||
|
||||
client.untag_resource(resourceArn=arn, tagKeys=["t1"])
|
||||
client.list_tags_for_resource(resourceArn=arn)["tags"].should.equal(
|
||||
{"t": "v", "t2": "v2"}
|
||||
)
|
||||
|
||||
client.untag_resource(resourceArn=arn, tagKeys=["t", "t2"])
|
||||
client.list_tags_for_resource(resourceArn=arn)["tags"].should.equal({})
|
Loading…
Reference in New Issue
Block a user