Skip to content

[FEATURE] Extensions in Score Schema #213

Description

@joeljeske

Detailed description

Score does not aim to support every option of the underlying service specs, rather a common subset. Patch templates are expected to fill in the gaps of what cannot be expressed in Score. However, Score's workload schema is closed (additionalProperties: false) on every object except metadata. So the only place to attach platform-specific extension data is metadata — either annotations (stringly-typed) or a nested map. That forces extension data far from the thing it describes: "give this container a longer startup budget" (Score has no probe-timing fields at all), or "this container runs as uid 101", has to live in a top-level metadata map keyed by container name, instead of inline on the container it applies to. It's awkward to author, awkward to read, and the link between the extension and its target survives only by convention (matching names).

Context

This would allow consumers to supply additional rich information within Score without resorting to distant metadata or annotations.

Possible implementation

Adopt OpenAPI-style specification extensions (x- prefixed fields), allowed at any object level within the service and containers schemas, and preserved through to consumers. Three parts:

  1. Schema (spec): permit x- keys anywhere in the service/container subtrees while keeping the core closed — i.e. add patternProperties: { "^x-": {} } alongside the existing additionalProperties: false. Non-x- unknown keys are still rejected, so the portability guarantee is intact and extension data is clearly marked as extension rather than mistaken for core spec.
  2. Preservation (score-go): keep x- fields through parsing instead of dropping them, so they re-emit inline where the author placed them.
  3. Exposure (consumers, e.g. score-k8s): surface them in the patch-template context (.Workloads) so a patch can read an inline x- field and act on it.

How they're used in patch templates

Probe timing is a good motivating case: Score's container probes carry only host/scheme/path/port/httpHeaders — there is no initialDelaySeconds, periodSeconds, failureThreshold, or startupProbe. A platform that needs those today has to hardcode one budget for every workload in a patch, with no way for an author to tune it. An x- extension lets the author set it inline, right on the container:

apiVersion: score.dev/v1b1
metadata:
  name: web
containers:
  main:
    image: myapp:latest
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        x-initial-delay-seconds: 30   # Score has no probe-timing fields

A patch template is capable of reading this field, either through a new top level .Extensions or some other mechanism in the template.

The extension lives where it belongs, is clearly namespaced as an extension, and the patch reads it inline — instead of the current pattern where a platform patch hardcodes one probe budget for every workload with no author control. (Note the x- keys are read with dig/index, not dot access, since a hyphen isn't a valid Go-template field selector.)

Additional information

  • x- is the OpenAPI Specification Extensions convention (older name: "vendor extensions"); Docker Compose calls the same thing extension fields. It's widely understood and signals "clearly-marked extension data", not "arbitrary unknown keys".

Alternatives:

  • metadata annotations / a nested metadata map (the status quo) — works, but decouples extension data from its target, is stringly-typed, and reads awkwardly.
  • Forking score-go / score-k8s — would let us preserve fields today, but means carrying a fork of actively developed projects and re-syncing every release.

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

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions