Skip to content

opensearch: the control plane is not routed, so no domain can be created through the API #1212

Description

@scttfrdmn

What

OpenSearch's control plane is not routed at all. POST /2021-01-01/opensearch/domain — the published
URI for CreateDomain — is split by substrate's router into a service index of 2021-01-01 and
refused with the engine's own route_not_found at 404, in substrate's internal envelope with no AWS
error Code. The same is true of every other control-plane operation: DescribeDomain,
DescribeDomains, ListDomainNames, UpdateDomainConfig, DeleteDomain, and the rest.

So a consumer cannot create a domain through the API. The only way a domain exists in substrate is
through a CloudFormation stack, and that path is a stub which the data plane cannot see (covered by the
CFN-stubs issue in this batch), so in practice no observable domain object exists anywhere.

What the data plane does instead

The data plane — index, document, search, bulk, scroll — is routed and functional, keyed on index name
with no domain in the key at all (covered by the unscoped-state-keys issue in this batch). It accepts
any host. So the shape of the service today is: a working search engine with no domains, addressed by
a URL whose domain part is ignored.

Why the refusal is the wrong shape too

Even granting that the control plane is unimplemented, the refusal should be substrate's published
unknown-operation answer for the service, not the engine's internal route_not_found. AWS publishes,
for every OpenSearch Service control-plane operation, a common-errors set including
ResourceNotFoundException/409 and ValidationException/400, and an unrouted path under a recognised
service should land on the service's own vocabulary. route_not_found is an internal token that
appears in no AWS reference and tells a consumer nothing about whether the operation exists.

The routing cause is worth stating precisely

Substrate derives the service from the first path segment for REST-routed plugins. OpenSearch's
control plane publishes its API version date as the first segment (/2021-01-01/opensearch/…),
which is a shape no other service in the tree uses — the version is normally in a header, a target
prefix, or a Version parameter. So this is not a missing handler; it is a path form the router has
no rule for, which is why the failure is a 404 from the engine rather than an
UnknownOperationException from the plugin.

Why this matters

The docs section this issue accompanies has to tell a consumer that the service whose name is
"OpenSearch" cannot create an OpenSearch domain, and that is worth an issue on its own. A consumer's
IaC provisions a domain and then indexes into it; against substrate the provisioning step fails with
a 404 carrying no AWS error code, which reads as a substrate outage rather than as an unimplemented
operation — and a consumer debugging it has nothing to search for, because route_not_found appears in
no AWS documentation.

The second-order effect is that every OpenSearch data-plane finding in this batch is currently
reachable only by a consumer who skips provisioning entirely. The data plane works, so a test that
indexes into an index that was never created passes — which is itself a divergence, and one a consumer
would never write deliberately.

Acceptance criteria

  • The router recognises the API-version-date first segment, so /2021-01-01/opensearch/… resolves
    to the OpenSearch plugin rather than to a service named 2021-01-01. State in the doc comment
    that this path shape is unique in the tree, since it is the reason a general rule did not cover
    it.
  • CreateDomain, DescribeDomain, DescribeDomains, ListDomainNames, UpdateDomainConfig and
    DeleteDomain are routed, with their published request and response shapes, or each is
    explicitly declined with a recorded reason. Routing them is the position consistent with Twelve services have a coverage-matrix row and no docs/services.md section, covering 92 routed operations #1093's
    premise that a documented service is a usable one; declining them is defensible only if written
    down.
  • An unrouted path under the OpenSearch prefix answers a code the service publishes, in the AWS
    error envelope, not route_not_found in substrate's internal envelope.
  • A created domain is visible to the data plane — a domain created through CreateDomain and one
    deployed through AWS::OpenSearchService::Domain must be the same object. Cross-reference the
    CFN-stubs and state-key issues in this batch; this criterion is what connects the three, and
    whichever lands last must satisfy it.
  • Indexing into an index on a domain that does not exist is refused, since it currently succeeds.
  • A test creates a domain, indexes a document, searches it, and deletes the domain — the smallest
    end-to-end path a consumer would actually write. It cannot pass today at step one.
  • docs/services.md's OpenSearch section states which surfaces are routed, and what a
    control-plane call answers.

Provenance

The published URI POST /2021-01-01/opensearch/domain and the request and response shapes of each
control-plane operation are from the Amazon OpenSearch Service API Reference —
API_CreateDomain, API_DescribeDomain, API_DescribeDomains, API_ListDomainNames,
API_UpdateDomainConfig, API_DeleteDomain — whose Request Syntax lines carry the version-dated
prefix. ResourceNotFoundException/409 and ValidationException/400 are from those pages' Errors
sections.

In-tree: emulator/opensearch_plugin.go (the data-plane routing, which has no control-plane arm) and
the router's service-from-first-segment derivation. route_not_found is the engine's own token and
appears in no AWS reference. Line citations are from the tree at the commit this issue was filed
against.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions