Resource type handler contract
The resource type handler contract specifies the expected and required behavior to
            which a resource must adhere in each given event handler. It defines a set of specific,
            unambiguous rules with which create, read,
            update, delete and list resource handlers must
            comply. Following the contract will allow customers to interact with all resource types
            under a uniform set of behaviors and expectations, and prevents creation of unintended
            or duplicate resources.
A resource implementation MUST pass all resource contract tests to be registered.
Assuming no other concurrent interaction on the resource, the handlers must comply with the following contract.
All terminology in the handler contract requirements adheres to the RFC 2119 specification
Create handlers
CloudFormation invokes the create handler when the resource is created during a stack create operation.
Input assumptions
The create handler can make the following assumptions about input
                    submitted to it:
- 
                        The input to a createhandler MUST be valid against the resource schema.
Output requirements
The create handler must adhere to the following requirements
                    regarding its output:
- 
                        A createhandler MUST always return a ProgressEvent object within 60 seconds. For more information, see ProgressEvent Object Schema.In every ProgressEvent object, the createhandler MUST return a model which conforms to the shape of the resource schema. For more information, see Returned models must conform to the shape of the schema.Every model MUST include the primaryIdentifier. The only exception is if the first progress event is FAILED, and the resource hasn't yet been created. In this case, a subsequentreadcall MUST returnNotFound.
- 
                        A createhandler MUST NOT returnSUCCESSuntil it has applied all properties included in thecreaterequest. For more information, see Update, create, and delete handlers must satisfy desired-state stabilization.- 
                                A createhandler MUST return IN_PROGRESS if it hasn't yet reached the desired-state.A createhandler SHOULD return a model containing all properties set so far and nothing more during each IN_PROGRESS event.
- 
                                A createhandler MUST return FAILED progress event if it can't reach the desired-state within the timeout specified in the resource schema.The progress event MUST return an error message and the most applicable error code. For more information, see Handler error codes. 
- 
                                A createhandler MAY return SUCCESS once it reaches the desired-state.Once the desired state has been reached, a createhandler MAY perform runtime-state stabilization. For more information, see Update and create handlers should satisfy runtime-state stabilization.When the createhandler returns SUCCESS, it MUST return a ProgressEvent object containing a model that satisfies the following requirements:- 
                                        All properties specified in the createrequest MUST be present in the model returned, and they MUST match exactly, with the exception of properties defined as writeOnlyProperties in the resource schema.
- 
                                        The model MUST contain all properties that have values, including any properties that have default values, and any readOnlyProperties as defined in the resource schema. 
- 
                                        The model MUST NOT return any properties that are null or don't have values. 
 
- 
                                        
 
- 
                                
- 
                        After a createoperation returns SUCCESS, a subsequentreadrequest MUST succeed when passed in the primaryIdentifier or any additionalIdentifiers associated with the provisioned resource instance.
- 
                        After a createoperation returns SUCCESS, a subsequentlistoperation MUST return the primaryIdentifier associated with the provisioned resource instance.If the listoperation is paginated, the entirelistoperation is defined as alllistrequests until thenextTokenisnull.
- 
                        A createhandler MUST be idempotent. Acreatehandler MUST NOT create multiple resources given the same idempotency token.
- 
                        A createhandler MUST return FAILED with an AlreadyExists error code if the resource already existed before the create request.
Update handlers
CloudFormation invokes the update handler when the resource is updated during an update operation.
Input assumptions
The update handler can make the following assumptions about input
                    submitted to it:
- 
                        The input to an updatehandler MUST be valid against the resource schema.
- 
                        Any createOnlyPropertiesspecified in update handler input MUST NOT be different from their previous state.
- 
                        The input to an updatehandler MUST contain either theprimaryIdentifieror anadditionalIdentifier.
Output requirements
The update handler must adhere to the following
                    requirements:
- 
                        An updatehandler MUST always return a ProgressEvent object within 60 seconds. For more information, see ProgressEvent Object Schema.In every ProgressEvent object, the updatehandler MUST return a model which conforms to the shape of the resource schema. For more information, see Returned models must conform to the shape of the schema.Every model MUST include the primaryIdentifier. The primaryIdentifier returned in every progress event must match the primaryIdentifier passed into the request. 
- 
                        An updatehandler MUST NOT returnSUCCESSuntil it has applied all properties included in theupdaterequest. For more information, see Update, create, and delete handlers must satisfy desired-state stabilization.- 
                                An updatehandler MUST return IN_PROGRESS if it hasn't yet reached the desired-state.An updatehandler SHOULD return a model containing all properties set so far and nothing more during each IN_PROGRESS event.
- 
                                An updatehandler MUST return FAILED progress event if it can't reach the desired-state within the timeout specified in the resource schema.The progress event MUST return an error message and the most applicable error code. For more information, see Handler error codes. 
- 
                                An updatehandler MAY return SUCCESS once it reaches the desired-state.Once the desired state has been reached, an updatehandler MAY perform runtime-state stabilization. For more information, see Update and create handlers should satisfy runtime-state stabilization.When the updatehandler returns SUCCESS, it MUST return a ProgressEvent object containing a model that satisfies the following requirements:- 
                                        All properties specified in the updaterequest MUST be present in the model returned, and they MUST match exactly, with the exception of properties defined as writeOnlyProperties in the resource schema.
- 
                                        The model MUST contain all properties that have values, including any properties that have default values, and any readOnlyProperties as defined in the resource schema. 
- 
                                        The model MUST NOT return any properties that are null or don't have values. 
 
- 
                                        
 All list or collection properties MUST be applied in full. The successful outcome MUST be replacement of the previous properties, if any. 
- 
                                
- 
                        An updatehandler MUST return FAILED with aNotFounderror code if the resource didn't exist before theupdaterequest.
- 
                        An updatehandler MUST NOT create a new physical resource.
Delete handlers
CloudFormation invokes the delete handler when the resource, or entire stack, is deleted during a stack delete operation.
Input assumptions
The delete handler can make the following assumptions about input
                    submitted to it:
- 
                        The input to a deletehandler MUST contain either theprimaryIdentifieror anadditionalIdentifier. Any other properties MAY NOT be included in the request.
Output requirements
The delete handler must adhere to the following
                    requirements:
- 
                        A deletehandler MUST always return a ProgressEvent object within 60 seconds. For more information, see ProgressEvent Object Schema.
- 
                        A deletehandler MUST NOT returnSUCCESSuntil the resource has reached the desired state for deletion. For more information, see Update, create, and delete handlers must satisfy desired-state stabilization.- 
                                A deletehandler MUST return IN_PROGRESS if it hasn't yet reached the desired state.
- 
                                A deletehandler MUST return FAILED progress event if it can't reach the desired-state within the timeout specified in the resource schema.The progress event MUST return an error message and the most applicable error code. For more information, see Handler error codes. 
- 
                                A deletehandler MUST return SUCCESS once it reaches the desired state. (This is because there is no runtime-state stabilization for delete requests.)When the deletehandler returns SUCCESS, the ProgressEvent object MUST NOT contain a model.
 
- 
                                
- 
                        A deletehandler MUST return FAILED with aNotFounderror code if the resource didn't exist before the delete request.
- 
                        Once a deleteoperation successfully completes, any subsequentupdate,delete, orreadrequest for the deleted resource instance MUST returnFAILEDwith aNotFounderror code.
- 
                        Once a deleteoperation successfully completes, any subsequentlistoperation MUST NOT return the primaryIdentifier associated with the deleted resource instance.If the listoperation is paginated, the 'list operation' is defined as alllistcalls until thenextTokenisnull.
- 
                        Once a deleteoperation successfully completes, a subsequentcreaterequest with the same primaryIdentifier or additionalIdentifiers MUST NOT returnFAILEDwith anAlreadyExistserror code.
- 
                        Once a deleteoperation successfully completes, the resource SHOULD NOT be billable to the client.
Read handlers
CloudFormation invokes the read handler when detailed information about the resource needed during a stack update operation.
Input assumptions
The read handler can make the following assumptions about input
                    submitted to it:
- 
                        The input to a readhandler MUST contain either theprimaryIdentifieror anadditionalIdentifier. Any other properties MAY NOT be included in the request.
Output requirements
The read handler must adhere to the following requirements
                    regarding its output:
- 
                        A readhandler MUST always return a ProgressEvent object within 30 seconds. For more information, see ProgressEvent Object Schema.A readhandler MUST always return a status ofSUCCESSorFAILED; it MUST NOT return a status ofIN_PROGRESS.
- 
                        A readhandler MUST return a model representation that conforms to the shape of the resource schema.- 
                                The model MUST contain all properties that have values, including any properties that have default values and any readOnlyPropertiesas defined in the resource schema.
- 
                                The model MUST NOT return any properties that are null or don't have values. 
 
- 
                                
- 
                        A readhandler MUST returnFAILEDwith aNotFounderror code if the resource doesn't exist.
List handlers
CloudFormation invokes the list handler when summary information about multiple resources of this resource type is required.
- 
                    A listhandler MUST always return a ProgressEvent object within 30 seconds. For more information, see ProgressEvent Object Schema.A listhandler MUST always return a status ofSUCCESSorFAILED; it MUST NOT return a status ofIN_PROGRESS.
- 
                    A listhandler MUST return an array of primary identifiers.When passed in a readrequest, eachprimaryIdentifierMUST NOT returnFAILEDwithNotFounderror code.
- 
                    A listrequest MUST support pagination by returning aNextToken.The NextTokenreturned MUST be able to be used in a subsequentlistrequest to retrieve the next set of results from the service.The NextTokenMUST be null when all results have been returned.
- 
                    A listrequest MUST return an empty array if there are no resources found.
- 
                    A listhandler MAY accept a set of properties conforming to the shape of the resource schema as filter criteria.The filter should use AND(&)when multiple properties are passed in.
Additional requirements
The following requirements also apply to resource handlers.
Returned models must conform to the shape of the schema
A model returned in a ProgressEvent object MUST always conform to the shape of the resource schema. This means that each property that's returned MUST adhere to its own individual restrictions: correct data type, regex, length, etc. However, the model returned MAY NOT contain all properties defined as required in the json-schema.
More specifically, contract tests validate models based on json-schema Validation keywords
- 
                        ALL Validation Keywords for the following MUST be observed: - 
                                Any Instance Type (Section 6.1) 
- 
                                Numeric Instances (Section 6.2) 
- 
                                Strings (Section 6.3) 
- 
                                Arrays (Section 6.4) 
 
- 
                                
- 
                        All Validation Keywords for Objects (Section 6.5) MUST be observed EXCEPT for: - 
                                required (Section 6.5.3) 
- 
                                dependencies (Section 6.5.7) 
- 
                                propertyNames (Section 6.5.8) 
 
- 
                                
- 
                        Contract tests won't validate Validation Keywords for: - 
                                Applying Subschemas Conditionally (Section 6.6) 
- 
                                Applying Subschemas With Boolean Logic (Section 6.7) 
 
- 
                                
Update, create, and delete handlers must satisfy desired-state stabilization
Stabilization is the process of waiting for a resource to be in a particular state. Note that reaching the desired-state is mandatory for all handlers before returning SUCCESS.
Create and update handlers
For Create and Update handlers, desired-state stabilization is satisfied when all properties specified in the request are applied as requested. This is verified by calling the Read handler.
In many cases, the desired-state is reached immediately upon completion of a Create/Update API call. However, in some cases, multiple API calls and or wait periods may be required in order to reach this state.
Eventual consistency in desired-state stabilization
Eventual consistency means that the result of an API command you run might not be immediately visible to all subsequent commands you run. Handling API eventual consistency is required as part of desired-state stabilization. This is because a subsequent Read call might fail with a NotFound error code.
Amazon EC2 resources are a great example of this. For more information, see Eventual Consistency in the Amazon Elastic Compute Cloud API Reference.
Examples of desired-state stabilization
For a simple example of desired-state stabilization, consider the
                            implementation of the create handler for the
                                AWS::Logs::MetricFilter resource: immediately after the
                            handler code completes the call to the PutMetricFilter
                            method, the AWS::Logs::MetricFilter has achieved its
                            desired state. You can examine the code for this resource in its
                            open-source repository at github.com/aws-cloudformation/aws-cloudformation-resource-providers-logs
A more complex example is the implementation of the
                                update handler for the
                                AWS::Kinesis::Stream resource. The update
                            handler must make multiple API calls during an update, including
                                AddTagsToStream or RemoveTagsFromStream,
                                UpdateShardCount, IncreaseRetentionPeriod
                            or DecreaseRetentionPeriod, and
                                StartStreamEncryption or
                                StopStreamEncryption. Meanwhile, each API call will set
                            the StreamStatus to UPDATING, during which
                            time other API operations can't be performed or the API will throw a
                                ResourceInUseException. Therefore, to reach the desired
                            state, the handler will need to wait for the StreamStatus
                            to become ACTIVE in between each API operation.
Delete handlers
Usually, the definition of deleted is
                        obvious. A delete API operation will result in the resource
                        being purged from the database, and the resource is no longer describable to
                        the user.
However, sometimes, a deletion will result in the resource leaving an
                            audit trail, in which the resource can still be
                        described by service API operations, but can no longer be interacted with by
                        the user. For example, when you delete a CloudFormation stack, it's assigned a
                        status of DELETE_COMPLETE, but it can still be returned from a
                                DescribeStacks API call. For resources like this,
                        the desired-state for deletion is when the resource has reached a
                            terminal, inoperable, and irrecoverable state. If
                        the resource can continue to be mutated by the user through another API
                        call, then it isn't deleted, it's
                            updated.
There is no difference between desired-state stabilization and
                        runtime-state stabilization for a delete handler. By definition, once a
                        resource has reached the desired-state for deletion, a subsequent
                            read call MUST return FAILED with a
                            NotFound error code, and a subsequent create
                        call with the same primaryIdentifier or additionalIdentifiers MUST NOT
                        return FAILED with an AlreadyExists error code.
                        Additional restrictions are defined in the contract above.
So in the case of a CloudFormation stack, a read handler MUST
                        return FAILED with a NotFound error code if the
                        stack is DELETE_COMPLETE, even though it's audit trail can
                        still be accessed by the DescribeStacks API.
Update and create handlers should satisfy runtime-state stabilization
Runtime-state stabilization is a process of waiting for the resource to be "ready" to use. Generally, runtime-state stabilization is done by continually describing the resource until it reaches a particular state, though it can take many forms.
Runtime-state stabilization can mean different things for different resources, but the following are common requirements:
- 
                        Additional mutating API calls can be made on the resource Some resources can't be modified while they're in a particular state. 
- 
                        Dependent resources can consume the resource There may be other resources which need to consume the resource in some way, but can't until it is in a particular state. 
- 
                        Users can interact with the resource Customers may not be able to use the resource until it is in a particular status. This usually overlaps with the dependent resources requirement, although there could be different qualifications, depending on the resources. 
While desired-state stabilization is mandatory, runtime-state stabilization is optional but encouraged. Users have come to expect that once a resource is COMPLETE, they will be able to use it.
Examples of run-time stabilization
For a simple example of run-time stabilization, consider the
                        implementation of the create handler for the
                            AWS::KinesisFirehose::DeliveryStream resource. The
                            create handler invokes only a single API,
                            CreateDeliveryStream, in order for the resource to reach
                        its desired state. Immediately after this API call is made, a
                            read request will return the correct desired state.
                        However, the resource still has not reached run-time stabilization because
                        it can't be used by the customer or downstream resources until the
                            DeliveryStreamStatus is ACTIVE.
For a more complex example, consider the implementation of the
                            update handler for the AWS::Kinesis::Stream
                        resource once again. Once the update handler has made its final
                        call, to StartStreamEncryption or
                            StopStreamEncryption as described in Examples of desired-state stabilization, the resource has
                        reached its desired state. However, like the other API calls on the Kinesis
                        resource, the StreamStatus will again be set to
                            UPDATING. During this period, it has reached its desired
                        state, and customers can even continue using the stream. But it hasn't yet
                        achieved runtime-stabilization, because additional API calls cannot be made
                        on the resource until the StreamStatus gets set to
                            ACTIVE.
Handlers must not leak resources
Resource leaking refers to when a handler loses track of the existence of a resource. This happens most often in the following cases:
- 
                        A createhandler isn't idempotent. Re-invoking the handler with the same idempotencyToken will cause another resource to be created, and the handler is only tracking a single resource.
- 
                        A createhandler creates the resource, but is unable to communicate an identifier for that resource back to CloudFormation. A subsequentdeletecall doesn't have enough information to delete the resource.
- 
                        A bug in the deletehandler causes the resource to not actually be deleted, but thedeletehandler reports that the resource was successfully deleted.