Skip to content

Commit

Permalink
Allowed Nested reference for TagProperty (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
ammokhov committed May 9, 2024
1 parent 92bda29 commit 7db1488
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,15 @@ public void validateTaggingMetadata(final boolean containUpdateHandler, final Sc
throw new ValidationException("Invalid tagUpdatable value since update handler is missing", "tagging",
"#/tagging/tagUpdatable");
}
final String propertyName = this.tagProperty.toString().substring(this.tagProperty.toString().lastIndexOf('/') + 1);

final String propertiesPrefix = "/properties/";
if (!this.tagProperty.toString().startsWith(propertiesPrefix)) {
final String errorMessage = String.format("Invalid tagProperty value %s must start with \"/properties\"",
this.tagProperty.toString());
throw new ValidationException(errorMessage, "tagging", "#/tagging/tagProperty");
}

final String propertyName = this.tagProperty.toString().substring(propertiesPrefix.length());
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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ public class ResourceTypeSchemaTest {
private static final String SCHEMA_WITH_ANYOF = "/valid-with-anyof-schema.json";
private static final String SCHEMA_WITH_ALLOF = "/valid-with-allof-schema.json";
private static final String SCHEMA_WITH_TAGGING = "/valid-with-tagging-schema.json";
private static final String SCHEMA_WITH_TAGGING_NESTED_PROPERTY = "/valid-with-tagging-nested-property-schema.json";

private static final String SCHEMA_WITH_TAGGING_MISSING_PROPERTY = "/valid-with-tagging-missing-tagProperty-schema.json";

private static final String SCHEMA_WITH_INVALID_TAGGING_BAD_POINTER = "/invalid-with-tagging-bad-pointer-schema.json";

private static final String SCHEMA_WITH_INVALID_TAGGING_BAD_REFERENCE = "/invalid-with-tagging-bad-reference-schema.json";

private static final String SCHEMA_WITH_NON_TAGGABLE = "/valid-with-non-taggable-schema.json";
private static final String INVALID_SCHEMA_WITH_UPDATE_TAGS = "/invalid-update-tagging-schema.json";
private static final String INVALID_SCHEMA_WITH_TAG_PROPERTY = "/invalid-tagProperty-schema.json";
Expand Down Expand Up @@ -430,6 +438,46 @@ public void schemaWithTagging_withValidConfiguration() {
assertThat(schema.getTagging().getTagPermissions()).contains("test:permission");
}

@Test
public void schemaWithTaggingNestedTagProperty_withValidConfiguration() {
JSONObject resourceDefinition = loadJSON(SCHEMA_WITH_TAGGING_NESTED_PROPERTY);
ResourceTypeSchema schema = ResourceTypeSchema.load(resourceDefinition);

assertThat(schema.getTagging().isTaggable()).isEqualTo(true);
assertThat(schema.getTagging().isTagOnCreate()).isEqualTo(true);
assertThat(schema.getTagging().isTagUpdatable()).isEqualTo(false);
assertThat(schema.getTagging().isCloudFormationSystemTags()).isEqualTo(false);
assertThat(schema.getTagging().getTagProperty()).asString().isEqualTo("/properties/propertyC/Tags");
assertThat(schema.getTagging().getTagPermissions()).contains("test:permission");
}

@Test
public void schemaWithTaggingMissingTagProperty_withValidConfiguration() {
JSONObject resourceDefinition = loadJSON(SCHEMA_WITH_TAGGING_MISSING_PROPERTY);
ResourceTypeSchema schema = ResourceTypeSchema.load(resourceDefinition);

assertThat(schema.getTagging().isTaggable()).isEqualTo(true);
assertThat(schema.getTagging().isTagOnCreate()).isEqualTo(true);
assertThat(schema.getTagging().isTagUpdatable()).isEqualTo(false);
assertThat(schema.getTagging().isCloudFormationSystemTags()).isEqualTo(false);
assertThat(schema.getTagging().getTagProperty()).asString().isEqualTo("/properties/Tags");
assertThat(schema.getTagging().getTagPermissions()).isEmpty();
}

@Test
public void schemaWithTaggingBadPointerTagProperty_withValidConfiguration() {
JSONObject resourceDefinition = loadJSON(SCHEMA_WITH_INVALID_TAGGING_BAD_POINTER);
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> ResourceTypeSchema.load(resourceDefinition))
.withMessage("a JSON pointer should start with '/' or '#/'");
}

@Test
public void schemaWithTaggingBadReferenceTagProperty_withValidConfiguration() {
JSONObject resourceDefinition = loadJSON(SCHEMA_WITH_INVALID_TAGGING_BAD_REFERENCE);
assertThatExceptionOfType(ValidationException.class).isThrownBy(() -> ResourceTypeSchema.load(resourceDefinition))
.withMessage("Invalid tagProperty value /propertyB must start with \"/properties\"");
}

/**
* validate that tagging metadata are processed and will throw exception
* when tagUpdatable is true but update handler is missing
Expand Down
31 changes: 31 additions & 0 deletions src/test/resources/invalid-with-tagging-bad-pointer-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"typeName": "AWS::Test::TestModel",
"description": "A test schema for unit tests.",
"properties": {
"propertyA": {
"type": "boolean"
},
"propertyB": {
"description": "A list of tags to apply to the resource.",
"type": "array",
"uniqueItems": true,
"arrayType": "Standard",
"insertionOrder": false
}
},
"primaryIdentifier": [
"/properties/propertyA"
],
"replacementStrategy": "delete_then_create",
"tagging": {
"taggable": true,
"tagOnCreate": true,
"tagUpdatable": false,
"cloudFormationSystemTags": false,
"tagProperty": "propertyB",
"permissions": [
"test:permission"
]
},
"additionalProperties": false
}
31 changes: 31 additions & 0 deletions src/test/resources/invalid-with-tagging-bad-reference-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"typeName": "AWS::Test::TestModel",
"description": "A test schema for unit tests.",
"properties": {
"propertyA": {
"type": "boolean"
},
"propertyB": {
"description": "A list of tags to apply to the resource.",
"type": "array",
"uniqueItems": true,
"arrayType": "Standard",
"insertionOrder": false
}
},
"primaryIdentifier": [
"/properties/propertyA"
],
"replacementStrategy": "delete_then_create",
"tagging": {
"taggable": true,
"tagOnCreate": true,
"tagUpdatable": false,
"cloudFormationSystemTags": false,
"tagProperty": "/propertyB",
"permissions": [
"test:permission"
]
},
"additionalProperties": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"typeName": "AWS::Test::TestModel",
"description": "A test schema for unit tests.",
"definitions": {
"Tag": {
"type": "object",
"additionalProperties": false,
"properties": {
"Key": {
"description": "The key name of the tag",
"type": "string"
},
"Value": {
"description": "The value for the tag",
"type": "string"
}
},
"required": [
"Value",
"Key"
]
}
},
"properties": {
"propertyA": {
"type": "boolean"
},
"Tags": {
"type": "array",
"items": {
"$ref": "#/definitions/Tag"
}
}
},
"primaryIdentifier": [
"/properties/propertyA"
],
"replacementStrategy": "delete_then_create",
"tagging": {
"taggable": true,
"tagOnCreate": true,
"tagUpdatable": false,
"cloudFormationSystemTags": false
},
"additionalProperties": false
}
61 changes: 61 additions & 0 deletions src/test/resources/valid-with-tagging-nested-property-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"typeName": "AWS::Test::TestModel",
"description": "A test schema for unit tests.",
"definitions": {
"propertyC": {
"type": "object",
"properties": {
"Tags": {
"description": "An array of arbitrary tags (key-value pairs) to associate with the stage.",
"type": "array",
"uniqueItems": false,
"insertionOrder": false,
"items": {
"$ref": "#/definitions/Tag"
}
}
}
},
"Tag": {
"type": "object",
"additionalProperties": false,
"properties": {
"Key": {
"description": "The key name of the tag",
"type": "string"
},
"Value": {
"description": "The value for the tag",
"type": "string"
}
},
"required": [
"Value",
"Key"
]
}
},
"properties": {
"propertyA": {
"type": "boolean"
},
"propertyC": {
"$ref": "#/definitions/propertyC"
}
},
"primaryIdentifier": [
"/properties/propertyA"
],
"replacementStrategy": "delete_then_create",
"tagging": {
"taggable": true,
"tagOnCreate": true,
"tagUpdatable": false,
"cloudFormationSystemTags": false,
"tagProperty": "/properties/propertyC/Tags",
"permissions": [
"test:permission"
]
},
"additionalProperties": false
}

0 comments on commit 7db1488

Please sign in to comment.