fix(cloudwatch): reject PutMetricData datums without a MetricName (#6072)
* fix(cloudwatch): reject PutMetricData datums without a MetricName MetricName is the one required member of MetricDatum. The JSON handler stored a nameless datum under an empty name, and the Query handler treated a member without MetricName as the end of the list, silently dropping it and every later datum while still storing the earlier ones. Both handlers now reject a missing or empty MetricName in top-level MetricData and in EntityMetricData[].MetricData with MissingParameter (400), the error PutMetricData declares for a missing required input, naming the offending member. A whitespace name is still accepted, since AWS constrains MetricName only to 1 to 255 characters. Every datum is validated before any is stored, so a rejected request leaves no state behind. On Query, a member index with no keys at all still ends that MetricData list. * fix(cloudwatch): return MissingRequiredParameterException on JSON and CBOR CloudWatch is awsQueryCompatible. MissingParameter is the awsQueryError code of the MissingRequiredParameterException shape, so it belongs in the Query <Code> and the x-amzn-query-error header, while a JSON 1.0 or CBOR body's __type names the shape. With the code in __type the AWS SDK v2 raised a generic CloudWatchException instead of the modelled one. A package-private CloudWatchMetricsException keeps the Query code as its error code and overrides jsonType() with the shape name, the same split SwfException makes. The shared query-code table in AwsException is left alone because SQS reports MissingParameter as its JSON type. (cherry picked from commit b8d87df05413ea8c4f9497fa05f388c19d4124ec)
This commit is contained in:
@@ -233,4 +233,20 @@ class CloudWatchTest {
|
||||
assertThat(stats.datapoints()).hasSize(1);
|
||||
assertThat(stats.datapoints().get(0).sum()).isEqualTo(6.5);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("PutMetricData without MetricName throws MissingRequiredParameterException")
|
||||
void testPutMetricDataWithoutMetricNameIsRejected() {
|
||||
String namespace = "JavaTestMissingMetricName";
|
||||
|
||||
assertThatThrownBy(() -> cloudWatchClient.putMetricData(request -> request
|
||||
.namespace(namespace)
|
||||
.entityMetricData(entityMetricData -> entityMetricData
|
||||
.metricData(MetricDatum.builder().value(1.0).build()))))
|
||||
.isInstanceOf(MissingRequiredParameterException.class)
|
||||
.satisfies(e -> assertThat(((MissingRequiredParameterException) e).awsErrorDetails().errorCode())
|
||||
.isEqualTo("MissingParameter"));
|
||||
|
||||
assertThat(cloudWatchClient.listMetrics(request -> request.namespace(namespace)).metrics()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user