From bd635936cc948145de15a61b70af093ba72ffae5 Mon Sep 17 00:00:00 2001 From: Anton Mokhovikov Date: Tue, 1 Oct 2024 15:15:34 -0700 Subject: [PATCH 1/2] [BugFix] Fix for TagProperty Validation --- .../resource/ResourceTagging.java | 3 +- .../resource/ResourceTypeSchemaTest.java | 17 +++ .../resources/test-nested-tagging-schema.json | 128 ++++++++++++++++++ 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/test-nested-tagging-schema.json diff --git a/src/main/java/software/amazon/cloudformation/resource/ResourceTagging.java b/src/main/java/software/amazon/cloudformation/resource/ResourceTagging.java index 2033f01..eb314a2 100644 --- a/src/main/java/software/amazon/cloudformation/resource/ResourceTagging.java +++ b/src/main/java/software/amazon/cloudformation/resource/ResourceTagging.java @@ -72,7 +72,8 @@ public void validateTaggingMetadata(final boolean containUpdateHandler, final Sc throw new ValidationException(errorMessage, "tagging", "#/tagging/tagProperty"); } - final String propertyName = this.tagProperty.toString().substring(propertiesPrefix.length()); + final String propertyName = this.tagProperty.toString().substring(propertiesPrefix.length()).replaceAll("/\\*/", "/0/"); + if (this.taggable && !schema.definesProperty(propertyName)) { final String errorMessage = String.format("Invalid tagProperty value since %s not found in schema", propertyName); throw new ValidationException(errorMessage, "tagging", "#/tagging/tagProperty"); diff --git a/src/test/java/software/amazon/cloudformation/resource/ResourceTypeSchemaTest.java b/src/test/java/software/amazon/cloudformation/resource/ResourceTypeSchemaTest.java index 7599e58..c0b9383 100644 --- a/src/test/java/software/amazon/cloudformation/resource/ResourceTypeSchemaTest.java +++ b/src/test/java/software/amazon/cloudformation/resource/ResourceTypeSchemaTest.java @@ -16,6 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static software.amazon.cloudformation.resource.ValidatorTest.loadJSON; import java.util.List; @@ -23,12 +24,14 @@ import org.everit.json.schema.PublicJSONPointer; import org.json.JSONObject; +import org.json.JSONPointer; import org.junit.jupiter.api.Test; import software.amazon.cloudformation.resource.exceptions.ValidationException; public class ResourceTypeSchemaTest { private static final String TEST_SCHEMA_PATH = "/test-schema.json"; + private static final String TEST_NESTED_TAGGING_SCHEMA_PATH = "/test-nested-tagging-schema.json"; private static final String TEST_SCHEMA_WITH_EMPTY_WRITE_ONLY_PATH = "/test-schema-with-empty-write-only.json"; private static final String EMPTY_SCHEMA_PATH = "/empty-schema.json"; private static final String SINGLETON_SCHEMA_PATH = "/singleton-test-schema.json"; @@ -68,6 +71,20 @@ public void getProperties() { assertThat(schema.getUnprocessedProperties()).isEmpty(); } + @Test + public void getProperties2() { + JSONPointer tagProperty = new JSONPointer("/properties/NestedTagProperty/TagSpecifications/*/Tags"); + JSONObject o = loadJSON(TEST_NESTED_TAGGING_SCHEMA_PATH); + final ResourceTypeSchema schema = ResourceTypeSchema.load(o); + + assertThat(schema.getDescription()).isEqualTo("A test schema for unit tests."); + assertThat(schema.getSourceUrl()).isEqualTo("https://mycorp.com/my-repo.git"); + assertThat(schema.getTypeName()).isEqualTo("AWS::Test::TestModel"); + assertThat(schema.isTaggable()).isTrue(); + assertThat(schema.getTagging().getTagProperty().toString()).isEqualTo(tagProperty.toString()); + assertDoesNotThrow(() -> schema.getTagging().validateTaggingMetadata(true, schema.getSchema())); + } + @Test public void getConditionalCreateOnlyProperties() { JSONObject o = loadJSON(TEST_SCHEMA_PATH); diff --git a/src/test/resources/test-nested-tagging-schema.json b/src/test/resources/test-nested-tagging-schema.json new file mode 100644 index 0000000..455b733 --- /dev/null +++ b/src/test/resources/test-nested-tagging-schema.json @@ -0,0 +1,128 @@ +{ + "typeName": "AWS::Test::TestModel", + "description": "A test schema for unit tests.", + "sourceUrl": "https://mycorp.com/my-repo.git", + "definitions": { + "NestedDefinition": { + "type": "object", + "additionalProperties": false, + "properties": { + "TagSpecifications": { + "type": "array", + "uniqueItems": true, + "items": { + "$ref": "#/definitions/TagSpecificationDefinition" + } + } + } + }, + "TagSpecificationDefinition": { + "type": "object", + "additionalProperties": false, + "properties": { + "Tags": { + "type": "array", + "uniqueItems": false, + "items": { + "$ref": "#/definitions/Tag" + } + } + } + }, + "Tag": { + "type": "object", + "additionalProperties": false, + "properties": { + "Key": { + "type": "string" + }, + "Value": { + "type": "string" + } + }, + "required": [ + "Value", + "Key" + ] + } + }, + "properties": { + "propertyA": { + "type": "string" + }, + "propertyB": { + "type": "array", + "arrayType": "AttributeList", + "items": { + "type": "integer" + } + }, + "propertyC": { + "type": "string" + }, + "propertyD": { + "type": "boolean" + }, + "propertyE": { + "type": "object", + "properties": { + "nestedProperty": { + "type": "string" + }, + "writeOnlyArray": { + "type": "string" + } + } + }, + "propertyF": { + "type": "string" + }, + "NestedTagProperty": { + "$ref": "#/definitions/NestedDefinition" + } + }, + "tagging": { + "taggable": true, + "tagOnCreate": true, + "tagUpdatable": false, + "cloudFormationSystemTags": true, + "tagProperty": "/properties/NestedTagProperty/TagSpecifications/*/Tags", + "permissions": [ + "permission:AddTags" + ] + }, + "propertyTransform": { + "/properties/propertyA": "$join([$string(test), propertyA])", + "/properties/propertyB": "$count(propertyB) = 0 ? null : propertyB" + }, + "required": [ + "propertyB" + ], + "conditionalCreateOnlyProperties": [ + "/properties/propertyF" + ], + "createOnlyProperties": [ + "/properties/propertyA", + "/properties/propertyD" + ], + "deprecatedProperties": [ + "/properties/propertyC" + ], + "readOnlyProperties": [ + "/properties/propertyB" + ], + "writeOnlyProperties": [ + "/properties/propertyC", + "/properties/propertyE/nestedProperty" + ], + "primaryIdentifier": [ + "/properties/propertyA" + ], + "additionalIdentifiers": [ + [ + "/properties/propertyB" + ] + ], + "replacementStrategy": "create_then_delete", + "additionalProperties": false +} \ No newline at end of file From e02f859f252d4b292ba051c8fc07738661a24856 Mon Sep 17 00:00:00 2001 From: Anton Mokhovikov Date: Tue, 15 Oct 2024 11:28:36 -0700 Subject: [PATCH 2/2] fix pre-commit --- .../amazon/cloudformation/resource/ResourceTypeSchema.java | 1 + src/test/resources/test-nested-tagging-schema.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/software/amazon/cloudformation/resource/ResourceTypeSchema.java b/src/main/java/software/amazon/cloudformation/resource/ResourceTypeSchema.java index c05a7f7..1d30e61 100644 --- a/src/main/java/software/amazon/cloudformation/resource/ResourceTypeSchema.java +++ b/src/main/java/software/amazon/cloudformation/resource/ResourceTypeSchema.java @@ -300,6 +300,7 @@ public boolean definesProperty(String field) { .filter(subschema -> subschema instanceof ObjectSchema) .findFirst().get() : schema; + return schemaToCheck.definesProperty(field); } diff --git a/src/test/resources/test-nested-tagging-schema.json b/src/test/resources/test-nested-tagging-schema.json index 455b733..b6e2f65 100644 --- a/src/test/resources/test-nested-tagging-schema.json +++ b/src/test/resources/test-nested-tagging-schema.json @@ -125,4 +125,4 @@ ], "replacementStrategy": "create_then_delete", "additionalProperties": false -} \ No newline at end of file +}