From fc5998f31a6fc7eff5ea8ab170033299f02f9b9e Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Wed, 9 Sep 2020 18:29:15 -0700 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20AIP-156=20=E2=80=93=20Singleton=20r?= =?UTF-8?q?esources?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aip/general/0156/aip.md.j2 | 40 +++++++++++++++++ aip/general/0156/aip.yaml | 7 +++ aip/general/0156/singleton.proto | 75 ++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 aip/general/0156/aip.md.j2 create mode 100644 aip/general/0156/aip.yaml create mode 100644 aip/general/0156/singleton.proto diff --git a/aip/general/0156/aip.md.j2 b/aip/general/0156/aip.md.j2 new file mode 100644 index 00000000..74a9fa38 --- /dev/null +++ b/aip/general/0156/aip.md.j2 @@ -0,0 +1,40 @@ +# Singleton resources + +APIs sometimes need to represent a resource where exactly one instance of the +resource always exists within any given parent. A common use case for this is +for a configuration object, with distinct permissions from the parent resource. + +## Guidance + +An API **may** define _singleton resources_. A singleton resource **must** +always exist by virtue of the existence of its parent, with one and exactly one +per parent. + +```http +GET /v1/publishers/{publisher}/config HTTP/2 +Host: library.googleapis.com +Accept: application/json +``` + +- Singleton resources **must not** have a user-provided or system-generated ID; + their canonical URI includes the name of their parent followed by one + static-segment. + - Example: `publishers/lacroix/config` +- Singleton resources **should** define a `GET` operation, which **must** + correspond to `GET` for individual resources (AIP-131), and **not** `GET` for + collections (AIP-132). +- Singleton resources **should** define a `PATCH` operation, which **must** + correspond to a standard update (AIP-134). +- Singleton resources **must not** define operations to create (AIP-133) or + delete (AIP-135) the resource. + - The service **should** reply with an HTTP 405 (Method Not Allowed) error if + the user sends a `POST` or `DELETE` request. +- Singleton resources **may** define custom methods as appropriate. + +## Interface Definitions + +{% tab proto %} + +{% sample 'singleton.proto', 'rpc GetConfig', 'rpc UpdateConfig' %} + +{% endtabs %} diff --git a/aip/general/0156/aip.yaml b/aip/general/0156/aip.yaml new file mode 100644 index 00000000..4da7d390 --- /dev/null +++ b/aip/general/0156/aip.yaml @@ -0,0 +1,7 @@ +--- +id: 156 +state: approved +created: 2019-05-12 +placement: + category: resource-design + order: 70 diff --git a/aip/general/0156/singleton.proto b/aip/general/0156/singleton.proto new file mode 100644 index 00000000..3cb1ef37 --- /dev/null +++ b/aip/general/0156/singleton.proto @@ -0,0 +1,75 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License 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. + +syntax = "proto3"; + +import "google/api/annotations.proto"; +import "google/api/client.proto"; +import "google/api/resource.proto"; +import "google/protobuf/field_mask.proto"; + +service Library { + // Get the configuration for a author. + rpc GetConfig(GetConfigRequest) returns (Config) { + option (google.api.http) = { + get: "/v1/{name=authors/*/config}" + }; + option (google.api.method_signature) = "name"; + } + + // Update the configuration for a author. + rpc UpdateConfig(UpdateConfigRequest) returns (Config) { + option (google.api.http) = { + patch: "/v1/{config.name=authors/*/config}" + body: "config" + }; + option (google.api.method_signature) = "config,update_mask"; + } +} + +// Request message to get a author's config. +message GetConfigRequest { + // The name of the config. + // Format: authors/{author}/config + string name = 1 [(google.api.resource_reference) = { + type: "library.googleapis.com/Config" + }]; +} + +// Request message to update a author's config. +message UpdateConfigRequest { + // The new config object. + Config config = 1; + + // The list of fields to be updated. + google.protobuf.FieldMask update_mask = 2; +} + +// The configuration options for a author. +message Config { + option (google.api.resource) = { + type: "library.googleapis.com/Config" + pattern: "authors/{author}/config" + }; + + // The name of the config. + // Format: authors/{author}/config + string name = 1; + + // The author's preferred language. + string language_code = 2; + + // The time zone where the author resides. + string time_zone = 3; +} From 729bb81368088e27db8d261fc57b5735c85356af Mon Sep 17 00:00:00 2001 From: Mike Kistler Date: Sun, 30 Oct 2022 08:38:00 -0500 Subject: [PATCH 2/2] Add oas example of singleton resource --- aip/general/0156/aip.md.j2 | 4 ++ aip/general/0156/singleton.oas.yaml | 57 +++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 aip/general/0156/singleton.oas.yaml diff --git a/aip/general/0156/aip.md.j2 b/aip/general/0156/aip.md.j2 index 74a9fa38..0c0a7d19 100644 --- a/aip/general/0156/aip.md.j2 +++ b/aip/general/0156/aip.md.j2 @@ -37,4 +37,8 @@ Accept: application/json {% sample 'singleton.proto', 'rpc GetConfig', 'rpc UpdateConfig' %} +{% tab oas %} + +{% sample 'singleton.oas.yaml', 'paths' %} + {% endtabs %} diff --git a/aip/general/0156/singleton.oas.yaml b/aip/general/0156/singleton.oas.yaml new file mode 100644 index 00000000..92b4aa3d --- /dev/null +++ b/aip/general/0156/singleton.oas.yaml @@ -0,0 +1,57 @@ +openapi: 3.0.3 +info: + title: Library + version: 1.0.0 +paths: + /authors/{author}/config: + parameters: + - name: author + in: path + description: The id of the author. + required: true + schema: + type: string + get: + operationId: getConfig + description: Get the configuration for a author. + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Config' + + patch: + operationId: updateConfig + description: Get the configuration for a author. + requestBody: + content: + 'application/json': + schema: + $ref: '#/components/schemas/Config' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Config' +components: + schemas: + Config: + description: The configuration options for a author. + type: object + properties: + name: + type: string + description: | + The name of the config. + Format: authors/{author}/config + languageCode: + type: string + description: | + The author's preferred language. + timeZone: + type: string + description: TThe time zone where the author resides.