Skip to content

Commit

Permalink
Merge pull request #52 from hashicorp/f-06-23-2023-provider.definitio…
Browse files Browse the repository at this point in the history
…n.schema-update

06/23/2023 AWS CloudFormation Resource Provider Definition Schema
  • Loading branch information
ewbankkit authored Jun 23, 2023
2 parents aa899d0 + 42dce43 commit ca81df0
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## v0.21.0 (Unreleased)

Support [`handlers.handlerSchema`](https://github.com/aws-cloudformation/cloudformation-resource-schema#handlers).

## v0.20.0 (December 19, 2022)

Support [`arrayType`](https://github.com/aws-cloudformation/cloudformation-resource-schema#arraytype).
Expand Down
5 changes: 3 additions & 2 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const (
)

type Handler struct {
Permissions []string `json:"permissions,omitempty"`
TimeoutInMinutes int `json:"timeoutInMinutes,omitempty"`
HandlerSchema *HandlerSchema `json:"handlerSchema,omitempty"`
Permissions []string `json:"permissions,omitempty"`
TimeoutInMinutes int `json:"timeoutInMinutes,omitempty"`
}
12 changes: 12 additions & 0 deletions handler_schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package cfschema

type HandlerSchema struct {
AllOf []*PropertySubschema `json:"allOf,omitempty"`
AnyOf []*PropertySubschema `json:"anyOf,omitempty"`
OneOf []*PropertySubschema `json:"oneOf,omitempty"`
Properties map[string]*Property `json:"properties,omitempty"`
Required []string `json:"required,omitempty"`
}
75 changes: 75 additions & 0 deletions handler_schema_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package cfschema_test

import (
"path/filepath"
"testing"

cfschema "github.com/hashicorp/aws-cloudformation-resource-schema-sdk-go"
)

func TestHandlerSchema(t *testing.T) {
testCases := []struct {
TestDescription string
MetaSchemaPath string
ResourceSchemaPath string
ExpectError bool
ExpectedHandlerSchema int
}{
{
TestDescription: "no handlerSchema",
MetaSchemaPath: "provider.definition.schema.v1.json",
ResourceSchemaPath: "AWS_CloudWatch_MetricStream.json",
},
{
TestDescription: "list handlerSchema",
MetaSchemaPath: "provider.definition.schema.v1.json",
ResourceSchemaPath: "AWS_NetworkManager_TransitGatewayRegistration.json",
ExpectedHandlerSchema: 1,
},
}

for _, testCase := range testCases {
testCase := testCase

t.Run(testCase.TestDescription, func(t *testing.T) {
metaSchema, err := cfschema.NewMetaJsonSchemaPath(filepath.Join("testdata", testCase.MetaSchemaPath))

if err != nil {
t.Fatalf("unexpected NewMetaJsonSchemaPath() error: %s", err)
}

resourceSchema, err := cfschema.NewResourceJsonSchemaPath(filepath.Join("testdata", testCase.ResourceSchemaPath))

if err != nil {
t.Fatalf("unexpected NewResourceJsonSchemaPath() error: %s", err)
}

err = metaSchema.ValidateResourceJsonSchema(resourceSchema)

if err != nil {
t.Fatalf("unexpected ValidateResourceJsonSchema() error: %s", err)
}

resource, err := resourceSchema.Resource()

if err != nil {
t.Fatalf("unexpected Resource() error: %s", err)
}

got := 0

for _, handler := range resource.Handlers {
if handler.HandlerSchema != nil {
got++
}
}

if actual, expected := got, testCase.ExpectedHandlerSchema; actual != expected {
t.Errorf("expected %d handlerSchema elements, got: %d", expected, actual)
}
})
}
}
2 changes: 2 additions & 0 deletions resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ type Resource struct {
DeprecatedProperties PropertyJsonPointers `json:"deprecatedProperties,omitempty"`
Description *string `json:"description,omitempty"`
Handlers map[string]*Handler `json:"handlers,omitempty"`
NonPublicDefinitions PropertyJsonPointers `json:"nonPublicDefinitions,omitempty"`
NonPublicProperties PropertyJsonPointers `json:"nonPublicProperties,omitempty"`
OneOf []*PropertySubschema `json:"oneOf,omitempty"`
PrimaryIdentifier PropertyJsonPointers `json:"primaryIdentifier,omitempty"`
Properties map[string]*Property `json:"properties,omitempty"`
Expand Down
1 change: 1 addition & 0 deletions tagging.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ type Tagging struct {
TagUpdatable *bool `json:"tagUpdatable,omitempty"`
CloudFormationSystemTags *bool `json:"cloudFormationSystemTags,omitempty"`
TagProperty *PropertyJsonPointer `json:"tagProperty,omitempty"`
Permissions []string `json:"permissions,omitempty"`
}
62 changes: 62 additions & 0 deletions testdata/AWS_NetworkManager_TransitGatewayRegistration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"typeName": "AWS::NetworkManager::TransitGatewayRegistration",
"description": "The AWS::NetworkManager::TransitGatewayRegistration type registers a transit gateway in your global network. The transit gateway can be in any AWS Region, but it must be owned by the same AWS account that owns the global network. You cannot register a transit gateway in more than one global network.",
"sourceUrl": "https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-networkmanager.git",
"properties": {
"GlobalNetworkId": {
"description": "The ID of the global network.",
"type": "string"
},
"TransitGatewayArn": {
"description": "The Amazon Resource Name (ARN) of the transit gateway.",
"type": "string"
}
},
"taggable": false,
"additionalProperties": false,
"required": [
"GlobalNetworkId",
"TransitGatewayArn"
],
"createOnlyProperties": [
"/properties/GlobalNetworkId",
"/properties/TransitGatewayArn"
],
"primaryIdentifier": [
"/properties/GlobalNetworkId",
"/properties/TransitGatewayArn"
],
"handlers": {
"create": {
"permissions": [
"networkmanager:RegisterTransitGateway"
],
"timeoutInMinutes": 30
},
"read": {
"permissions": [
"networkmanager:GetTransitGatewayRegistrations"
]
},
"list": {
"handlerSchema": {
"properties": {
"GlobalNetworkId": {
"$ref": "resource-schema.json#/properties/GlobalNetworkId"
}
},
"required": ["GlobalNetworkId"]
},
"permissions": [
"networkmanager:GetTransitGatewayRegistrations"
]
},
"delete": {
"permissions": [
"networkmanager:DeregisterTransitGateway"
],
"timeoutInMinutes": 30
}
}
}

68 changes: 67 additions & 1 deletion testdata/provider.definition.schema.v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,57 @@
"title": "CloudFormation Resource Provider Definition MetaSchema",
"description": "This schema validates a CloudFormation resource provider definition.",
"definitions": {
"handlerSchema": {
"type": "object",
"properties": {
"properties": {
"$ref": "file://./base.definition.schema.v1.json#/properties/properties"
},
"required": {
"$ref": "file://./base.definition.schema.v1.json#/properties/required"
},
"allOf": {
"$ref": "file://./base.definition.schema.v1.json#/definitions/schemaArray"
},
"anyOf": {
"$ref": "file://./base.definition.schema.v1.json#/definitions/schemaArray"
},
"oneOf": {
"$ref": "file://./base.definition.schema.v1.json#/definitions/schemaArray"
}
},
"required": [
"properties"
],
"additionalProperties": false
},
"handlerDefinitionWithSchemaOverride": {
"description": "Defines any execution operations which can be performed on this resource provider",
"type": "object",
"properties": {
"handlerSchema": {
"$ref": "#/definitions/handlerSchema"
},
"permissions": {
"type": "array",
"items": {
"type": "string"
},
"additionalItems": false
},
"timeoutInMinutes": {
"description": "Defines the timeout for the entire operation to be interpreted by the invoker of the handler. The default is 120 (2 hours).",
"type": "integer",
"minimum": 2,
"maximum": 2160,
"default": 120
}
},
"additionalProperties": false,
"required": [
"permissions"
]
},
"handlerDefinition": {
"description": "Defines any execution operations which can be performed on this resource provider",
"type": "object",
Expand Down Expand Up @@ -145,6 +196,13 @@
"description": "A reference to the Tags property in the schema.",
"$ref": "http://json-schema.org/draft-07/schema#/properties/$ref",
"default": "/properties/Tags"
},
"permissions": {
"type": "array",
"items": {
"type": "string"
},
"additionalItems": false
}
},
"required": [
Expand Down Expand Up @@ -183,7 +241,7 @@
"$ref": "#/definitions/handlerDefinition"
},
"list": {
"$ref": "#/definitions/handlerDefinition"
"$ref": "#/definitions/handlerDefinitionWithSchemaOverride"
}
},
"additionalProperties": false
Expand All @@ -204,6 +262,14 @@
"description": "A list of JSON pointers for properties that can only be updated under certain conditions. For example, you can upgrade the engine version of an RDS DBInstance but you cannot downgrade it. When updating this property for a resource in a CloudFormation stack, the resource will be replaced if it cannot be updated.",
"$ref": "file://./base.definition.schema.v1.json#/definitions/jsonPointerArray"
},
"nonPublicProperties": {
"description": "A list of JSON pointers for properties that are hidden. These properties will still be used but will not be visible",
"$ref": "file://./base.definition.schema.v1.json#/definitions/jsonPointerArray"
},
"nonPublicDefinitions": {
"description": "A list of JSON pointers for definitions that are hidden. These definitions will still be used but will not be visible",
"$ref": "file://./base.definition.schema.v1.json#/definitions/jsonPointerArray"
},
"createOnlyProperties": {
"description": "A list of JSON pointers to properties that are only able to be specified by the customer when creating a resource. Conversely, any property *not* in this list can be applied to an Update request.",
"$ref": "file://./base.definition.schema.v1.json#/definitions/jsonPointerArray"
Expand Down

0 comments on commit ca81df0

Please sign in to comment.