File: test_cloudwatch_expressions.py

package info (click to toggle)
python-moto 5.1.18-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 116,520 kB
  • sloc: python: 636,725; javascript: 181; makefile: 39; sh: 3
file content (132 lines) | stat: -rw-r--r-- 4,299 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from datetime import datetime, timedelta, timezone
from time import sleep
from uuid import uuid4

import boto3
import pytest
from botocore.exceptions import ClientError

from moto import mock_aws
from moto.core.utils import utcnow
from tests.test_cloudwatch import cloudwatch_aws_verified


@mock_aws
def test_get_metric_data__no_metric_data_or_expression():
    utc_now = datetime.now(tz=timezone.utc)
    cloudwatch = boto3.client("cloudwatch", "eu-west-1")
    with pytest.raises(ClientError) as exc:
        cloudwatch.get_metric_data(
            MetricDataQueries=[{"Id": "result1", "Label": "e1"}],
            StartTime=utc_now - timedelta(minutes=5),
            EndTime=utc_now,
            ScanBy="TimestampDescending",
        )
    err = exc.value.response["Error"]
    assert err["Code"] == "ValidationError"
    assert (
        err["Message"]
        == "The parameter MetricDataQueries.member.1.MetricStat is required.\n"
    )


@mock_aws
def test_get_metric_data_with_simple_expression():
    utc_now = datetime.now(tz=timezone.utc)
    cloudwatch = boto3.client("cloudwatch", "eu-west-1")
    namespace = "my_namespace/"
    cloudwatch.put_metric_data(
        Namespace=namespace,
        MetricData=[
            {
                "MetricName": "metric",
                "Value": 25,
                "Unit": "Bytes",
            },
        ],
    )
    # get_metric_data 1
    results = cloudwatch.get_metric_data(
        MetricDataQueries=[
            {
                "Id": "result1",
                "Expression": "totalBytes",
                "Label": "e1",
            },
            {
                "Id": "totalBytes",
                "MetricStat": {
                    "Metric": {"Namespace": namespace, "MetricName": "metric"},
                    "Period": 60,
                    "Stat": "Sum",
                    "Unit": "Bytes",
                },
                "ReturnData": False,
            },
        ],
        StartTime=utc_now - timedelta(minutes=5),
        EndTime=utc_now + timedelta(minutes=5),
        ScanBy="TimestampDescending",
    )["MetricDataResults"]
    #
    assert len(results) == 1
    assert results[0]["Id"] == "result1"
    assert results[0]["Label"] == "e1"
    assert results[0]["Values"] == [25.0]


@cloudwatch_aws_verified
@pytest.mark.aws_verified
def test_get_metric_data_with_expressive_expression():
    cloudwatch = boto3.client("cloudwatch", "eu-west-1")
    my_namespace = f"Test/FakeNamespace_{str(uuid4())[0:6]}"
    cloudwatch.put_metric_data(
        Namespace=my_namespace,
        MetricData=[
            {
                "MetricName": "ApiResponse",
                "Dimensions": [
                    {"Name": "Path", "Value": "/my/path"},
                    {"Name": "Audience", "Value": "my audience"},
                ],
                "Timestamp": utcnow(),
                "StatisticValues": {
                    "Maximum": 10,
                    "Minimum": 0,
                    "Sum": 10,
                    "SampleCount": 10,
                },
            }
        ],
    )

    expression = f"SELECT SUM(ApiResponse) FROM \"{my_namespace}\" WHERE Path = '/my/path' GROUP BY Audience"
    start_time = utcnow() - timedelta(hours=1)
    end_time = utcnow() + timedelta(hours=1)

    for _ in range(60):
        result = cloudwatch.get_metric_data(
            StartTime=start_time,
            EndTime=end_time,
            MetricDataQueries=[
                {
                    "Id": "query",
                    "Period": 60,
                    "Expression": expression,
                }
            ],
        )["MetricDataResults"]
        if result:
            assert len(result) == 1
            assert result[0]["Id"] == "query"
            # If the Label is not supplied, AWS uses:
            #     the group value as the query name, if the query contains a GROUP BY clause
            #     the Id if no GROUP BY clause exists
            # But Moto doesn't understand expressions, so we always use the Id
            assert result[0]["Label"]
            assert result[0]["Values"] == [10.0]
            assert result[0]["StatusCode"] == "Complete"
            return
        else:
            sleep(5)
    raise AssertionError("Should have found metrics within 5 minutes")