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

Exposing Deployment Information #53

Open
kylef opened this issue Nov 21, 2018 · 7 comments
Open

Exposing Deployment Information #53

kylef opened this issue Nov 21, 2018 · 7 comments

Comments

@kylef
Copy link
Member

kylef commented Nov 21, 2018

This is an issue to propose / discuss how we should expose information on where a particular API is deployed.

Current Support

API Blueprint

The API Blueprint does not include any support for describing the deployment information. API Blueprint does allow metadata at the top of an API Blueprint. Many tools use the metadata HOST which can be a URL to where the API may be deployed.

HOST: https://example.com/v2/

This is translated to metadata attribute for an API Category in API Elements:

{
  "element": "member",
  "meta": {
    "classes": {
      "element": "array",
      "content": [
        {
          "element": "string",
          "content": "user"
        }
      ]
    }
  },
  "content": {
    "key": {
      "element": "string",
      "content": "HOST"
    },
    "value": {
      "element": "string",
      "content": "https://example.com/v2/"
    }
  }
}

Swagger 2

Swagger 2 provides support for deployment information with schemes (array) host and basePath. Our adapter takes the first schema and host and places that in the same metadata section as API Blueprint so that the value is in a format that is already used by tooling and didn't require tooling updates.

schemes: [https]
host: example.com
basePath: /v2/

The above Swagger 2 structure would result in a HOST metadata of https://example.com and basePath would be prepended into every href found in the parse result which perhaps isn't the most ideal way to handle it. The problem is that the basePath may be supplied without a host and thus couldn't be exposed as HOST metadata.

{
  "element": "member",
  "meta": {
    "classes": {
      "element": "array",
      "content": [
        {
          "element": "string",
          "content": "user"
        }
      ]
    }
  },
  "content": {
    "key": {
      "element": "string",
      "content": "HOST"
    },
    "value": {
      "element": "string",
      "content": "https://example.com"
    }
  }
}
basePath: /v2/
paths:
  /user
{
  "element": "resource",
  "attributes": {
    "href": {
      "element": "string",
      "content": "/v2/user"
    }
  },
  "content": [...]
}

OpenAPI 3

In OpenAPI 3 a lot of server information including server variables may be described. See https://github.com/OAI/OpenAPI-Specification/blob/50c152549263cda0f05608d514ba78546b390d0e/versions/3.0.0.md#server-object or more details.

@kylef
Copy link
Member Author

kylef commented Dec 5, 2018

I was thinking we could introduce a concept of "Server" into API Elements which is similiar to OpenAPI 3. A server could contain a href, and optionally hrefVariables. The href is a URI template (template href). For example a simple OAS3 server would map to a server element:

element: server
meta:
  description: Production
attributes:
  href: https://example.com/

Templated variables may look as follows:

element: server
attributes:
  href: {scheme}://example.com/
  hrefVariables:
    element: object
    content:
      - element: member
        content:
          key: scheme
          value:
            element: enum
            attributes:
              enumerations:
                - http
                - https

A server MAY be inside a resource, or inside an API Category. The API Category may contain a "servers" category to group all available servers.

Tools such as API Documentation, API Consoles SHOULD make use of this information. Tools like API Gateways MAY utilise this information.

It should be possible to supply the server information at run-time to tooling, for example a console or documentation renderer should allow me to inject certain server information. The use-case is that it can inject mock-servers, or other tooling for example a configured API Gateway can populate server information to documentation renderer.

Mapping to other formats

API Blueprint

API Blueprint doesn't contain deployment information and thus does not emit any server elements.

NOTE, some have defined semantics for HOST as a metadata in API Blueprint. This will stay as-is, this is NOT a feature of API Blueprint and we want to keep the seperation of deployment information out of the API Blueprint language. It will not be mapped to servers object. HOST is NOT a feature of API Blueprint.

Swagger 2

The schemes, host, basePath is mapped into a server object similiar to the following:

element: server
attributes:
  href: {scheme}://{host}/{basePath}
  hrefVariables:
    element: object
    content:
      - element: member
        content:
          key: scheme
      - element: member
        content:
          key: host
      - element: member
        content:
          key: basePath

As some of these fields are optional in Swagger 2, they may not have a value. schemes will be mapped to either a fixed value or a enumeration of values. Similiary host and basePath will be mapped to variables in the server object.

OpenAPI 3

There is direct mapping between OAS 'Server Object' and server API Element.

@kylef
Copy link
Member Author

kylef commented Jun 11, 2019

Following some discussions in OpenAPI, there is some consensus that servers is perhaps a poor name (https://open-api.slack.com/archives/C1137F8HF/p1559929905003800), and hosts, backends or similiar may be a better fit.

@klokane
Copy link
Contributor

klokane commented Jun 11, 2019

What about ability set uri templates part in depencies on type of enviroment eg.

  • production:
    • scheme: https
  • dev:
    • scheme: http
    • tld: local

@kylef
Copy link
Member Author

kylef commented Jun 13, 2019

@klokane I think this can be solved with 'One Of', and enum, for example the MSON-pseudo code, the hrefVariables can be represented using selection:

  • One Of
    • (object) - Production
      • schema: https (fixed)
      • host: example.com (fixed)
    • (object) - Development
      • schema: http (fixed)
      • host: dev.example.com (fixed)

I think you can imagine how that could be reproduced in the above element structure (didn't want to write extend/select API Elements by hand).

There can also simpler variant with enum, providing it is only one value that is changed:

element: server
attributes:
  href: https://{environment}/
  hrefVariables:
    element: object
    content:
      - element: member
        content:
          key: environment
          value:
            type: enum
            attributes:
              enumerations:
                - element: string
                  meta:
                    title:
                      element: string
				      content: Development
                  content: dev.example.com
                - element: string
                  meta:
                    title:
                      element: string
				      content: Production
                  content: example.com

@klokane
Copy link
Contributor

klokane commented Jun 13, 2019

Nice idea, maybe we should introduce standardized way howto place this into Blueprint to allow tooling work with. In relation to enviroment variables, it can be good idea for dredd (cc @honzajavorek)

kylef added a commit to apiaryio/api-elements.js that referenced this issue Jun 18, 2019
@kylef
Copy link
Member Author

kylef commented Jun 18, 2019

There's a proof of concept implementation for OpenAPI 2 parser at apiaryio/api-elements.js@50dc494.

kylef added a commit to apiaryio/api-elements.js that referenced this issue Jul 4, 2019
@kylef
Copy link
Member Author

kylef commented Mar 23, 2020

I had some discussions with @tjanc who proposed we should re-use the "resource" element because it already contains href and hrefVariables. Semantically, a server IS a resource. Therefore we can use the existing Resource Element instead of introducing a new element. To be able to differentiate the resource element from other resources, we can add an additional classifier of host to represent it is a host.

element: resource
meta:
  classes:
    - host
attributes:
  href: {scheme}://example.com/
  hrefVariables:
    element: hrefVariables
    content:
      - element: member
        content:
          key: scheme
          value:
            element: enum
            attributes:
              enumerations:
                - http
                - https

In terms of a category of these types of resources, we can have a hosts category which looks as follows:

element: category
meta:
  classes:
    - hosts
content:
  - element: resource
    meta:
      classes:
        - host
    attributes:
      href: {scheme}://example.com/
      hrefVariables:
        element: hrefVariables
        content:
          - element: member
            content:
              key: scheme
              value:
                element: enum
                attributes:
                  enumerations:
                    - http
                    - https

OpenAPI 3 also supports attaching a set of "Server Object"s to a resource (Path Item Object) or a transition (Operation Object). As such, in this case we can introduce a hosts attribute to "Resource Element" and "Transition Element" as follows:

element: resource
attributes:
  href: /foo
  hosts:
    element: category
    content:
      - element: resource
        meta:
          classes:
            - host
        attributes:
          href: {scheme}://example.com/
          hrefVariables:
            element: hrefVariables
            content:
              - element: member
                content:
                  key: scheme
                  value:
                    element: enum
                    attributes:
                      enumerations:
                        - http
                        - https

The existing API Elements referencing is also possible, thus:

element: resource
meta:
  id:
    element: string
    content: productionServer

can be referenced:

element: productionServer

To summarise, API Element may offer the following:

  • New "Resource" classification host
  • New "Category" classification hosts
  • New property hosts on Resource and Transition elements to contain Category of hosts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants