Skip to content

Commit

Permalink
feat(resource-types): add resource-types (#76)
Browse files Browse the repository at this point in the history
Porting the resource types AEP from google.aip.dev.

Specific changes:

- Rename from resource name to resource path, to be consistent with
  aeps.
- Instead of introducing new terminology within the AEP, updating
  /glossary instead.
- using kebab-case instead of upperCamelCase, to be consistent with other AEPs.

Co-authored-by: Richard Frankel <[email protected]>
Co-authored-by: Richard Gibson <[email protected]>
  • Loading branch information
3 people authored Jan 26, 2024
1 parent 2eb0c24 commit 575d888
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 7 deletions.
25 changes: 18 additions & 7 deletions aep/general/0003/aep.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ The following terminology **must** be used consistently throughout AEPs.
Application Programming Interface. This can be a local interface (such as an
SDK) or a Network API (defined below).

APIs define one or more operations upon resource types.

### API Backend

A set of servers and related infrastructure that implements the business logic
Expand All @@ -33,36 +35,45 @@ Examples of clients include the following:

### API Definition

A well-structured representation of an API Service.
A well-structured representation of an API.

### API Endpoint

Refers to a network address that an API Service uses to handle incoming API
Requests. One API Service may have multiple API Service Endpoints, such as
`https://pubsub.example.com` and `https://content-pubsub.example.com`.
Refers to a network address that an API uses to handle incoming requests. One
API may have multiple endpoints, such as `https://pubsub.example.com` and
`https://content-pubsub.example.com`.

### API Gateway

One or more services that together provide common functionality across API
Services, such as load balancing and authentication.
services, such as load balancing and authentication.

### API Method

An individual operation within an API. It is typically represented in Protocol
Buffers by an `rpc` definition, or in HTTP via a `method` and a `path`.

### API Name

The name by which to refer to an API.

### API Request

A single invocation of an API Method. It is often used as the unit for billing,
logging, monitoring, and rate limiting.

### API Resource

An object upon which one or more API methods operate.
An entity upon which one or more methods can operate.

### API Resource Type

An API resource type represents a category of that consumes and API,
The type of a API resource. It is globally unique within an API.

### API Service

An implementation of an API, exposing API methods on one or more network
addresses.

### Consumer

Expand Down
138 changes: 138 additions & 0 deletions aep/general/0004/aep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# Resource types

Most APIs expose _resources_ (their primary nouns) which users are able to
create, retrieve, and manipulate. APIs are allowed to name their resource types
as they see fit, and are only required to ensure uniqueness within that API.
This means that it is possible (and often desirable) for different APIs to use
the same type name. For example, a Memcache and Redis API would both want to
use `Instance` as a type name.

When mapping the relationships between APIs and their resources, however, it
becomes important to have a single, globally-unique type name. Additionally,
tools such as Kubernetes or GraphQL interact with APIs from multiple providers.

## Guidance

APIs **must** define a resource type for each resource in the API, according to
the following pattern: `{API Name}/{Type Name}`. The type name:

- **must** Only contain ASCII alphanumeric characters.
- **must** Start with a lowercase letter.
- **must** Be of the singular form of the noun.
- **must** Use kebab case.
- For Kubernetes, the type name when converted to UpperCamelCase **must** match
the [object][] name.
- For OpenAPI, the type name when converted to UpperCamelCase **must** match
the name of the schema representing the object.
- For protobuf, the type name when converted to UpperCamelCase **must** match
the name of the protobuf message.

### Examples

Examples of resource types include:

- `networking.istio.io/instance`
- `pubsub.example.com/topic`
- `pubsub.example.com/subscription`
- `spanner.example.com/database`
- `spanner.example.com/instance`
- `apis.example.com/user/user-event`

### Annotating resource types

APIs **must** annotate the resource types for each resource in the API

{% tab proto %}

For protobuf, use the [`google.api.resource`][resource] annotation:

```proto
// A representation of a user event.
message Topic {
option (google.api.resource) = {
type: "user.example.com/user-event"
singular: "user-event"
plural: "user-events"
// define one or more patterns, e.g. if a resource has more than one parent.
pattern: "projects/{project}/user-events/{user-event}"
pattern: "folder/{folder}/user-events/{user-event}"
pattern: "users/{user}/events/{user-event}"
};
// Name and other fields...
```

{% tab oas %}

For OpenAPI 3.0, use the `x-aep-resource` extension:

```json
{
"type": "object",
"x-aep-resource": {
"singular": "user-event",
"plural": "user-events",
"patterns": [
"projects/{project}/user-events/{user-event}",
"folder/{folder}/user-events/{user-event}",
"users/{user}/events/{user-event}"
]
}
}
```

{% endtabs %}

- The `singular` field **must** be the kebab-case singular type name.
- The `plural` field **must** be the kebab-case plural of the singular.

The `pattern` field **must** match the `pattern` rule in the following grammar,
expressed as [EBNF][EBNF]:

```ebnf
pattern = element, { "/", element };
element = variable | literal;
variable = "{", literal, "}";
```

Where `literal` matches the regex `[a-z][a-z0-9\-]*[a-z0-9]`.

- Patterns **must** match the possible [resource paths][resource-paths] of the
resource.
- Pattern variables (the segments within braces) **must** match the singular of
the resource whose id is being matched by that value.

#### Pattern uniqueness

If multiple patterns are defined within a resource, the patterns defined **must
not** overlap in the set of resource paths that they can match. In other words,
a resource path may match at most one of the patterns.

For example, the following two patterns would not be valid for the same
resource:

- `user/{user}`
- `user/{user_part_1}~{user_part_2}`

## Rationale

### Singular and Plural

Well-defined singular and plurals of a resource enable clients to determine the
proper name to use in code and documentation.

google.aip.dev uses UpperCamelCase for resource types, while aep.dev uses
kebab-case. This is to enforce better consistency in the representation of
various multipart strings, as collection identifiers use kebab case.

<!-- prettier-ignore-start -->
[resource-paths]: /resource-paths
[API Group]: https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-groups
[nested collections]: ./0122.md#collection-identifiers
[Object]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#types-kinds
[resource]: https://github.com/googleapis/googleapis/blob/master/google/api/resource.proto
[service configuration]: https://github.com/googleapis/googleapis/blob/master/google/api/service.proto
[EBNF]: https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form
<!-- prettier-ignore-end -->

## Changelog
7 changes: 7 additions & 0 deletions aep/general/0004/aep.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
id: 4
slug: resource-types
state: approved
created: 2023-11-15
placement:
category: resources
31 changes: 31 additions & 0 deletions common-components/json_schema/x-aep-resource.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
$schema: https://json-schema.org/draft/2020-12/schema
$id: https://aep.dev/common-components/json_schema/x-aep-resource.yaml
title: AEP Resource
description: |
Describes a resource exposed by an API.
type: object
required:
- type
- singular
- plural
- pattern
additionalProperties: false
properties:
type:
type: string
description: |
A string that describes the resource type.
singular:
type: string
description: |
The singular of the resource.
plural:
type: string
description: |
The plural of the resource.
pattern:
description: |
A list of possible resource paths that are used to identify the resource.
type: array
items:
type: string

0 comments on commit 575d888

Please sign in to comment.