Skip to content

Addition of "$ref" property to enable flexible configuration composition #23

Open
@greggroth

Description

@greggroth

Problem

Multiple teams collaborating on a common codebase may have different dependency or setup needs and currently this is done by sharing a single devcontainer.json configuration with all of their individual needs combined. #6 describes support for multiple configuration files, but there isn't set a way to consolidate the shared configuration into a single file.

A simpler approach to solving this problem is proposed in #22 while this aims to be a more complete solution. However, it's unclear if this level of support is truly necessary.

Proposed Solution

Taking influence from JSON Schema and the Open API 3.0 specs, a special property named "$ref" would allow importing all or part of a referenced document. Here is an example:

Given a file "defaults.json":

// .devcontainer/defaults.json
{
    "name": "microsoft/foo",
    "extensions": [
        "/root/hello-githug.vsix"
    ],
    "forwardPorts": [80, 5432]
    "hostRequirements": {
        "storage": "64gb",
        "memory": "32gb"
    },
    "portsAttributes": {
        "80": {
            "label": "web"
        },
        "5432": {
            "label": "postgres"
        }
    }
}

If a team would like to introduce a team-specific configuration that adds ports for Redis, they can add a new configuration:

// .devcontainer/redis-team.json
{
    "$ref": "defaults", 
    "extensions": [],
    "forwardPorts": [ { "$ref": "defaults#/forwardPorts" }, 6379], // Explicit merge behavior
    "hostRequirements": {
        "memory": "64gb"    // Require more memory
    },
    "portAttributes": {
        "$ref": "defaults#/portAttributes",                        // Explicit merge behavior
        "6379": {
            "label": "redis"
        }
    }
}

Resulting in a final configuration:

{
    "name": "microsoft/foo",
    "extensions": [],				
    "forwardPorts": [80, 5432, 6379],
    "hostRequirements": {
        "storage": "64gb",
        "memory": "64gb"
    },
    "portAttributes": {
        "80": {
            "label": "web"
        },
        "5432": {
            "label": "postgres"
        }
        "6379": {
            "label": "redis"
        }
    }
}

Allowed Values for $ref

The value of a $ref contains a file and optionally a JSON Pointer path separated by a "#"

  • Import an entire document: "default", "ports.json",
  • Import the "forwardPorts" value: "defaults.json#/forwardPorts"

See here for more examples of JSON Pointer paths.

Remote Reference:

  • File in the same directory, extension optional: "document"
  • File in the same directory with extension: "document.json"
  • File in a subdirectory: "defaults/ports.json"
  • File in a parent directory: "../other/defaults.json"

URL Reference:

  • File at a URI: "https://github.com/microsoft/foo/blob/master/.devcontainer/devcontainer.json"
  • File at a URI: "https://example.com/configuration.json"

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalStill under discussion, collecting feedback

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions