Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
greggroth opened this issue Mar 25, 2022 · 2 comments
Labels
proposal Still under discussion, collecting feedback

Comments

@greggroth
Copy link

greggroth commented Mar 25, 2022

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"
@bamurtaugh
Copy link
Member

How does this experience differ from #22? Both seem to allow referencing / building off of another devcontainer.json, perhaps with this proposal allowing for referencing a specific property rather than entire file.

@greggroth
Copy link
Author

They solve basically the same problem, but in different ways. #22 uses a single top-level "extends" keyword to a file that is treated as a "parent" document with while this approach is more flexible, but consequently more complicated. I opened up separate issues for them since they aren't incompatible with one another.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal Still under discussion, collecting feedback
Projects
None yet
Development

No branches or pull requests

3 participants