Skip to content

Latest commit

 

History

History
71 lines (62 loc) · 7.24 KB

adding-an-endpoint.adoc

File metadata and controls

71 lines (62 loc) · 7.24 KB

Adding an Endpoint to Nexus

Adding new endpoints cuts across many concepts in Nexus, from the HTTP interface, authorization, the database, and several tests. This guide attempts to act as a "check-list" when adding new resources.

Note
This guide is not intended to be exhaustive, or even particularly detailed. For that, refer to the documentation which exists in the codebase — this document should act as a jumping-off point.

1. HTTP

  • Add endpoints for either the internal or external API

    • The External API is customer-facing, and provides interfaces for both developers and operators

    • The Internal API is internal, and provides interfaces for services on the Oxide rack (such as the Sled Agent) to call

    • Register endpoints in the register_endpoints method (Example)

    • These endpoints typically call into the Application layer, and do not access the database directly

  • Inputs and Outputs

2. Lookup & Authorization

  • Declare a new resource-to-be-looked-up via lookup_resource! in lookup.rs (Example)

    • This defines a new struct named after your resource, with some auto-generated methods, including lookup_for (look up the authz object), fetch_for (look up and return the object), and more

  • Add helper functions to LookupPath to make it possible to fetch the resource by either UUID or name (Example)

    • These are often named pub fn <my_resource>_name, or pub fn <my_resource>_id

  • Use the authz_resource! macro to define a new authz::…​ structure, which is returned from the Lookup functions (Example)

    • If you define polar_snippet = InProject (for developer resources) or polar_snippet = FleetChild (for operator resources), most of the polar policy is automatically defined for you

    • If you define polar_snippet = Custom, you should edit the omicron.polar file to describe the authorization policy for your object (Example)

  • Either way, you should add reference the new resource when constructing the Oso structure

3. Application

  • Add any "business logic" for the resource to the app directory

  • This layer bridges the gap between the database and external services.

  • If your application logic involes any multi-step operations which would be interrupted by Nexus stopping mid-execution (due to reboot, crash, failure, etc), it is recommended to use a saga to define the operations durably.

4. Database

5. Testing

  • Authorization

    • There exists a policy test which compares all Oso objects against an expected policy. New resources are usually added to resources.rs to get coverage.

  • openapi

    • Nexus generates a new openapi spec from the dropshot endpoints. If you modify endpoints, you’ll need to update openapi JSON files.

      • The following commands may be used to update APIs:

        $ cargo run -p omicron-nexus --bin nexus -- -I nexus/examples/config.toml > openapi/nexus-internal.json
        $ cargo run -p omicron-nexus --bin nexus -- -O nexus/examples/config.toml > openapi/nexus.json
        $ cargo run -p omicron-sled-agent --bin sled-agent -- openapi > openapi/sled-agent.json
      • Alternative, you can run:

        $ EXPECTORATE=overwrite cargo test_nexus_openapi test_nexus_openapi_internal test_sled_agent_openapi_sled
  • Integration Tests

    • Nexus' integration tests are used to cross the HTTP interface for testing. Typically, one file is used "per-resource".

      • These tests use a simulated Sled Agent, and keep the "Nexus" object in-process, so it can still be accessed and modified for invasive testing.

  • Saga Tests

    • Sagas are implictly tested through most integration tests, but they are also subject to more scrutiny, since they must fulfill certain properties (such as idempotency and an ability to unwind). These properties are typically tested in the same file as the saga definition (Example)