Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add noReplace trait #351

Merged
merged 1 commit into from
Apr 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 79 additions & 2 deletions docs/source/spec/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1954,6 +1954,17 @@ The following snippet defines the ``PutForecast`` operation.
chanceOfRain: Float
}

The semantics of a ``put`` lifecycle operation are similar to the semantics
of an `HTTP PUT method`_:

The PUT method requests that the state of the target resource be
created or replaced ...

The :ref:`noReplace-trait` can be applied to resources that define a
``put`` lifecycle operation to indicate that a resource cannot be
replaced using the ``put`` operation.


.. _create-lifecycle:

Create lifecycle
Expand All @@ -1966,6 +1977,7 @@ identifiers created by the service.

- Create operations MUST NOT be marked with :ref:`readonly-trait`.
- Create operations MUST form valid :ref:`collection operations <collection-operations>`.
- The ``create`` operation MAY be marked with :ref:`idempotent-trait`.

The following snippet defines the ``CreateForecast`` operation.

Expand All @@ -1988,8 +2000,6 @@ The following snippet defines the ``CreateForecast`` operation.
chanceOfRain: Float,
}

The ``create`` operation MAY be marked with :ref:`idempotent-trait`


.. _read-lifecycle:

Expand Down Expand Up @@ -4578,6 +4588,71 @@ to request additional results from the operation.
Resource traits
===============

.. _noReplace-trait:

``noReplace`` trait
-------------------

Summary
Indicates that the :ref:`put lifecycle <put-lifecycle>` operation of a
resource can only be used to create a resource and cannot replace an
existing resource.
Trait selector
``resource:test(-[put]->)``

*A resource with a put lifecycle operation*
Value type
Annotation trait.

By default, ``put`` lifecycle operations are assumed to both create and
replace an existing resource. Some APIs, however, do not support this
behavior and require that a resource is first deleted before it can be
replaced.

For example, this is the behavior of Amazon DynamoDB's CreateTable_
operation. The "Table" resource identifier, "TableName", is provided by the
client, making it appropriate to model in Smithy as a ``put`` lifecycle
operation. However, ``UpdateTable`` is used to update a table and attempting
to call ``CreateTable`` on a table that already exists will return an error.

.. tabs::

.. code-tab:: smithy

@noReplace
resource Table {
put: CreateTable
}

@idempotent
operation CreateTable {
// ...
}

.. code-tab:: json

{
"smithy": "0.5.0",
"shapes": {
"smithy.example#Table": {
"type": "resource",
"put": {
"target": "smithy.example#CreateTable"
},
"traits": {
"smithy.api#noReplace": true
}
},
"smithy.example#CreateTable": {
"type": "operation",
"traits": {
"smithy.api#idempotent": true
}
}
}
}


.. _references-trait:

``references`` trait
Expand Down Expand Up @@ -6228,3 +6303,5 @@ model:
.. _RFC 3986 Host: https://tools.ietf.org/html/rfc3986#section-3.2.2
.. _CommonMark: https://spec.commonmark.org/
.. _ubiquitous language: https://martinfowler.com/bliki/UbiquitousLanguage.html
.. _CreateTable: https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateTable.html
.. _HTTP PUT method: https://tools.ietf.org/html/rfc7231#section-4.3.4
9 changes: 5 additions & 4 deletions docs/themes/smithy/static/default.css_t
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
/* ----- Layout ------ */

html {
font-family: 'Open Sans', sans-serif;
font-family: {{ theme_regular_font }};
background-color: #f7f7f5;
}

/* Base scaffolding taken from Markswatch theme */
body {
color: #24292e;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial,
sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
font-family: {{ theme_regular_font }};
font-size: 18px;
line-height: 1.5;
-ms-text-size-adjust: 100%;
Expand All @@ -35,6 +34,8 @@ blockquote {
margin: 0 2rem 1rem 0;
color: #777;
border-left: 0.5rem solid #eee;
font-family: {{ theme_code_font }};
font-size: 1rem;
}

.width-wrapper {
Expand Down Expand Up @@ -513,7 +514,7 @@ pre {
}

code, pre {
font-family: "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace;
font-family: {{ theme_code_font }};
}

pre a {
Expand Down
2 changes: 2 additions & 0 deletions docs/themes/smithy/theme.conf
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ light_accent = #eee8d5
secondary_background = #382e2e
link_color = #005cc5
toc_column_color = #efebe9
regular_font = -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'
code_font = "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import software.amazon.smithy.model.traits.JsonNameTrait;
import software.amazon.smithy.model.traits.LengthTrait;
import software.amazon.smithy.model.traits.MediaTypeTrait;
import software.amazon.smithy.model.traits.NoReplaceTrait;
import software.amazon.smithy.model.traits.OptionalAuthTrait;
import software.amazon.smithy.model.traits.PaginatedTrait;
import software.amazon.smithy.model.traits.PatternTrait;
Expand Down Expand Up @@ -169,6 +170,7 @@ public final class Prelude {
IdempotentTrait.ID,
JsonNameTrait.ID,
LengthTrait.ID,
NoReplaceTrait.ID,
MediaTypeTrait.ID,
PaginatedTrait.ID,
PatternTrait.ID,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package software.amazon.smithy.model.traits;

import software.amazon.smithy.model.SourceLocation;
import software.amazon.smithy.model.shapes.ShapeId;

/**
* Indicates that the put lifecycle operation of a resource
* can only be used to create a resource and cannot replace
* an existing resource.
*/
public final class NoReplaceTrait extends BooleanTrait {
public static final ShapeId ID = ShapeId.from("smithy.api#noReplace");

public NoReplaceTrait(SourceLocation sourceLocation) {
super(ID, sourceLocation);
}

public NoReplaceTrait() {
this(SourceLocation.NONE);
}

public static final class Provider extends BooleanTrait.Provider<NoReplaceTrait> {
public Provider() {
super(ID, NoReplaceTrait::new);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ software.amazon.smithy.model.traits.IdRefTrait$Provider
software.amazon.smithy.model.traits.JsonNameTrait$Provider
software.amazon.smithy.model.traits.LengthTrait$Provider
software.amazon.smithy.model.traits.MediaTypeTrait$Provider
software.amazon.smithy.model.traits.NoReplaceTrait$Provider
software.amazon.smithy.model.traits.PaginatedTrait$Provider
software.amazon.smithy.model.traits.PatternTrait$Provider
software.amazon.smithy.model.traits.PrivateTrait$Provider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,12 @@ structure xmlNamespace {
@length(min: 1)
string NonEmptyString

/// Indicates that the put lifecycle operation of a resource
/// can only be used to create a resource and cannot replace
/// an existing resource.
@trait(selector: "resource:test(-[put]->)")
structure noReplace {}

/// Describes the contents of a blob shape using a media type as defined by
/// RFC 6838 (e.g., "video/quicktime").
@trait(selector: ":each(blob, string)")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[ERROR] ns.foo#InvalidResource: Trait `noReplace` cannot be applied to `ns.foo#InvalidResource`. This trait may only be applied to shapes that match the following selector: resource:test(-[put]->) | TraitTarget
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"smithy": "0.5.0",
"shapes": {
"ns.foo#Service": {
"type": "service",
"version": "2019-06-27",
"resources": [
{
"target": "ns.foo#ValidResource"
},
{
"target": "ns.foo#InvalidResource"
}
]
},
"ns.foo#ValidResource": {
"type": "resource",
"put": {
"target": "ns.foo#PutValidResource"
},
"traits": {
"smithy.api#noReplace": true
}
},
"ns.foo#PutValidResource": {
"type": "operation",
"traits": {
"smithy.api#idempotent": true
}
},
"ns.foo#InvalidResource": {
"type": "resource",
"traits": {
"smithy.api#noReplace": true
}
}
}
}