Skip to content

(DOCS) Define and document schema for resource manifest #90

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

Closed
wants to merge 1 commit into from
Closed

(DOCS) Define and document schema for resource manifest #90

wants to merge 1 commit into from

Conversation

michaeltlombardi
Copy link
Collaborator

PR Summary

This commit converts the type definitions in the dsc_lib\src\dscresources\resource_manifest.rs file into a minimal JSON schema.

PR Context

For users to be successful in implementing DSC Resources, they'll need both a JSON schema to validate their manifests and to refer to documentation for the resource manifest that goes beyond reading the JSON Schema.

The schema represents the current state of the type definitions, but raises a few questions for discussion. See the comments in the schema file.

The documentation for the schema is currently hand-authored and the structure is experimental, since we have no official support for documenting JSON schemas on the Learn platform.

For readability and referability, I recommend breaking the larger schema up into smaller schemas and referencing across them.

To be recognized by DSC, every command-based DSC Resource must have a DSC Resource manifest. The manifest must:

1. Be discoverable in the `PATH` environment variable.
1. Follow the naming convention `<name>.resource.json`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have guidance on <name>, since the <name> is not used as the type name (since it's in the manifest), we should probably recommend namespacing to avoid name collisions (which would only affect if in the same directory).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated with specific guidance:

### type
The value of this property must be the name of the DSC Resource in its namespace. This value must
use the following syntax:
```text
`<owner>[.<group>][.<area>]/<name>`
```
Each component must be string of alphanumeric characters and underscores. No other characters are
permitted. Every DSC Resource must define an `owner` and a `name`. Use the `group` and `area`
components to organize DSC Resources into related namespaces. For example:
- `Microsoft.SqlServer/Database`
- `Microsoft.SqlServer.Database/Role`
- `Microsoft.SqlServer.Database/User`
- `Microsoft.SqlServer/Endpoint`
- `Microsoft.SqlServer.Endpoint/Permission`
- `Microsoft.SqlServer/Login`
- `Microsoft.SqlServer/MaxDop`
```yaml
Type: string
Required: true
Pattern: ^\w+(\.\w+){0,2}\/\w+$
```

| Metadata Key | Metadata Value |
| :----------: | :-------------------------------------------------- |
| `$schema` | `https://json-schema.org/draft/2020-12/schema` |
| `$id` | `https://aka.ms/dsc/schemas/resource/manifest.yaml` |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there Microsoft precedent already for this type of URL?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure - I put it in as a placeholder until we have a canonical URI for the schema.

### type

The value of this property must be the name of the DSC Resource in its namespace. The name of the DSC Resource should be separated from its namespace by a forward slash (`/`). For example, a
resource for managing a SQLServer database might define its `type` as `SQLServer/Database`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there existing Microsoft/Nuget namespacing rules we can point them to? It should be something like <company>.[group.]<area>. So minimally the example here is Microsoft.SqlServer, but it could be Microsoft.SqlServer.Management.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll look into that and make sure our guidance aligns, if it exists, or write something to that effect.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no specific guidance on the format for these that I found with a quick search, but there is documentation on the process for preserving namespace prefixes on nuget.org, which we may want to adopt or adapt if we host a DSC Resource registry.


The `executable` property, defining the name of the command to call, is mandatory. The `args`
`input`, and `returns` properties are optional. For more information, see the
[Test method's schema documentation][03].
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I presume details of when they should implement test directly vs relying on dsc.exe synthetic test will be in the test method details?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct.


### validate

This property defines how to call the DSC Resource to validate an instance.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validate is only intended for group resources, although I guess it could be used by single resources but intent is for single resources to provide JSON schema so dsc.exe does the validation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have a separate schema for group resources? They can reuse shared definitions, but that might be easier for folks to reason about. Otherwise I can adjust the schema. If we only want a single schema for DSC Resources, we might want a distinguishing key for kind, unless resources can be both a group resource and direct resource.

Comment on lines 48 to 56
required:
- executable
properties:
executable:
$ref: "#/$defs/executable"
args:
$ref: "#/$defs/args"
input:
$ref: "#/$defs/input"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SteveL-MSFT I also noticed when I was looking at the type definition that input seems to be required for set and test, but not get - is that intentional?

/// How to pass optional input for a Get.
#[serde(skip_serializing_if = "Option::is_none")]
pub input: Option<InputKind>,

/// How to pass required input for a Set.
pub input: InputKind,

/// How to pass required input for a Test.
pub input: InputKind,

Relatedly, neither the ValidateMethod nor ListMethod structs seem to have an input field.

JSON schema.
- `embedded` - When you specify the `embedded` property, DSC uses the defined value as the JSON
schema.
- `url` - When you specify the `url` property, DSC fetches the JSON schema from the defined URL.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either command or embedded is required during runtime execution while url is intended to be used by tooling for authoring configuration.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated this section to match that information. The schema property is now documented in this file as part of the documentation decomposition:

https://github.com/PowerShell/DSC/pull/90/files#diff-75dd2fb3d50b3244e014d47a21e0b10c785da06be220f36d19fcdab112d268d6

This does raise a question for me: If a command-based DSC Resource needs to publish its schema to a URL for integrating tools, what's the benefit of specifying the command property over embedded/url, both of which can be fetched/used by integrating tools without having the DSC Resource installed locally?

The advantage that springs to mind for me is for development/testing speed, but it otherwise seems like a complication, especially since (without command), the property schema could be condensed to:

schema:
  title: Instance Schema
  description: >-
    Defines how DSC must validate a JSON blob representing an instance of the
    DSC Resource. Must be a valid JSON schema. To reference a remote schema,
    use the `$ref` keyword.
  type: object
  minProperties: 1

  examples:
    # Functionally schema.embedded
    - $schema: https://json-schema.org/draft/2020-12/schema
      $id: https://tailspintoys.com/schemas/dsc/gotstoy
      title: Golang TSToy Resource
      type: object
      required:
      - scope
      properties: # snipped for bevity

    # Functionally schema.url
    - $ref: https://tailspintoys.com/schemas/dsc/gotstoy

@@ -0,0 +1,253 @@
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you just convert this to YAML from retrieving the JSON schema from the tool?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this initial schema is hand-authored.

```yaml
Type: string
Required: true
Pattern: ^\w+(\.\w+){0,2}\/\w+$
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made the validation for the type strict - here it only allows:

  • <owner>/<name>
  • <owner>.<group|area>/<name>
  • <owner>.<group>.<area>/<name>

I can remove or increase the restriction on the group/area component count.

Comment on lines +35 to +41
```yaml
Type: string
Required: true
Valid Values:
- '1.0'
```
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't include the Pattern metadata here because the semver regex is very long, but maybe we should?

Comment on lines +152 to +165
properties:
executable:
$ref: "#/$defs/executable"
args:
$ref: "#/$defs/args"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the documentation, I noted that DSC Group Resources always get their input for the validate method over stdin because the input field wasn't defined on the struct - not sure if that's true or if the field was missing unintentionally.

Comment on lines +189 to +207
config:
title: Expected Configuration
description: >-
Defines whether the provider expects to receive a full and unprocessed
configuration as a single JSON blob over stdin or a sequence of JSON
Lines for each child resource's configurations.
type: string
enum:
- full
- sequence
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I correctly understood the difference between full and sequence, or the semantic importance of "full and unprocessed configuration" - when this value is full, does the DSC Resource Provider get the entire configuration, or the configuration for all of its child instances, or something else?

When this value is sequence, does the DSC Resource Provider get one resource at a time as JSON Lines, or is it invoked once per resource, or something else?

Comment on lines 110 to 113
The `preTest` property defines whether the DSC Resource tests the instance internally before enforcing the desired state. Set this property to `true` when the DSC Resource tests the instance. Set this property to `false` to ensure DSC determines tests the instance instead. The default value
is `false`.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my understanding of how DSC uses preTest, but I'm not sure, particularly when preTest is false - does DSC call test first, then set if test indicates it should?

Comment on lines +126 to +129
- `stateAndDiff` - Indicates that the DSC Resource returns the instance's final state and an array
of property names that the DSC Resource modified.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this required to follow a JSON Schema, or is it two separate blobs?

In other words, this:

{ "foo": 5, "bar": true }
["bar"]

or this (with different key names):

{"state": {"foo": 5, "bar": true}, "properties": ["bar"]}

Comment on lines +120 to +123
- `stateAndDiff` - Indicates that the DSC Resource returns the instance's actual state and an array
of property names that are out of the desired state.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this required to follow a JSON Schema, or is it two separate blobs?

In other words, this:

{ "foo": 5, "bar": true }
["bar"]

or this (with different key names):

{"state": {"foo": 5, "bar": true}, "properties": ["bar"]}

Comment on lines +3 to +5
DSC Group Resources must define the `validate` property in their DSC Resource manifest. This
property defines how DSC can call the DSC Group Resource to test whether instances in the group
have valid definitions.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I more-or-less guessed at the purpose of this keyword and how it's actually used. Is this wildly inaccurate?

Comment on lines +176 to +197
list:
title: List Command
description: >-
Defines how DSC must call the DSC Resource Provider to list its supported
DSC Resources.
type: object
required:
- executable
properties:
executable:
$ref: "#/$defs/executable"
args:
$ref: "#/$defs/args"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As with validate, the struct didn't define the input field.

This commit converts the type definitions in the
`dsc_lib\src\dscresources\resource_manifest.rs` file into a minimal
JSON schema. The schema represents the current state of the type
definitions, but raises a few questions for discussion.

The documentation for the schema is currently hand-authored and the
structure is experimental, since we have no official support for
documenting JSON schemas on the Learn platform.

For readability and referability, I recommend breaking the larger
schema up into smaller schemas and referencing across them.
@michaeltlombardi
Copy link
Collaborator Author

Closing in favor of #94

@michaeltlombardi michaeltlombardi deleted the docs/schemas branch August 3, 2023 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants