Skip to content
Open
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
44 changes: 44 additions & 0 deletions aip/general/0156/aip.md.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# 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' %}

{% tab oas %}

{% sample 'singleton.oas.yaml', 'paths' %}

{% endtabs %}
7 changes: 7 additions & 0 deletions aip/general/0156/aip.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
id: 156
state: approved
created: 2019-05-12
placement:
category: resource-design
order: 70
57 changes: 57 additions & 0 deletions aip/general/0156/singleton.oas.yaml
Original file line number Diff line number Diff line change
@@ -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.
75 changes: 75 additions & 0 deletions aip/general/0156/singleton.proto
Original file line number Diff line number Diff line change
@@ -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;
}