Distributed Configuration via Namespace

Overview

In contrast to the "Multple Interface" approach, the idea here is to use standard interfaces and extend OKAPI to support the concept of a namespace to act as the discriminator.  

Namespace-scoped Interface Support

The changes required here include generic support for namespace-scoped interfaces:

Module Descriptor

  • Add a new field "namespace" - this serves as the discriminator in the case when an interface which have already been defined with the same name.
    • Optional
    • String
  • Applies to both the provides and requires sections of the Module Descriptor

Example (Provider)

{
  "id": "mod-hello-foo-1.0.0",
  "name": "Hello foo module",
  "provides": [{
    "id": "distributed_configuration",
    "version": "1.0",
    "namespace": "foo",
    "handlers": [{
      "methods": [ "GET" ],
      "pathPattern": "/configurations/entries",
      "permissionsRequired": [ "foo.configuration.entries.collection.get" ]
    },
    {
      "methods": [ "GET" ],
      "pathPattern": "/configurations/entries/{id}",
      "permissionsRequired": [ "foo.configuration.entries.item.get" ]
    },
    {
      "methods": [ "POST" ],
      "pathPattern": "/configurations/entries",
      "permissionsRequired": [ "foo.configuration.entries.item.post" ]
    },
    {
      "methods": [ "PUT" ],
      "pathPattern": "/configurations/entries/{id}",
      "permissionsRequired": [ "foo.configuration.entries.item.put" ]
    },
    {
      "methods": [ "DELETE" ],
      "pathPattern": "/configurations/entries/{id}",
      "permissionsRequired": [ "foo.configuration.entries.item.delete" ]
    }]
  }],
  "requires": [],
  "launchDescriptor": {
    "exec": "node hello_foo.js"
  }
}

Example (Consumer)

"requires": [
  {
    "id": "distributed_configuration",
    "version": "1.0"
    "namespace": "foo"
  }
]

OKAPI

Distributed Configuration Support

The work required to implement the distributed_configuration (namespace-scoped) interface:

RAML/OpenAPI

At least one user story is needed in the OKAPI project to handle the following:

  • Create shared/common interface description for the distributed_configuration API.
    • Incorporate the namespace query arg or path prefix (depends on the approach we take - see above)
    • Should be easy to pull in and use by modules (like existing shared RAML traits, etc.)

raml-module-builder / folio-spring-base

  • Create default implementations of the distributed_configuration interface
    • Similar to what's currently provided by mod-configuration - probably just handles persistence, no fancy business logic required
    • Can be easily overridden if desired.  

Stripes Changes

Pros/Cons

Pros

  • Doesn't require use of additional X-Okapi-* headers
  • Allows modules to depend on the interface
  • It's use is completely optional
  • Clients are not required to know/determine the module Id in order to call a specific implementation of the interface.

Cons

  • More complex logic that Okapi, front-end and back-end need to support
  • Using namespace
      "id": "distributed_configuration", "namespace": "foo", "pathPattern": "/configurations/entries"
    doesn't have advantages over the existing path solution
      "id": "foo_configuration", "pathPattern": "/foo/configurations/entries"

Other Considerations

  1. Do we want/need to incorporate version into the discriminator too?  This is something that came up in the JIRA comments here.
  2. Do we even want to support RAML?  If OpenAPI is the way forward, maybe we skip defining it in RAML...
    1. Has a way of sharing common API definitions/traits been sorted out yet on the OpenAPI side of things?
    2. Is the expectation that all modules will eventually move towards OpenAPI?  Even those which currently use RAML?

JIRAs