You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As a contributor and maintainer,
I want to clearly understand which folders contain Rust crates, which folders contain resources, and so on,
so that I can quickly orient myself and more readily work on existing or new crates.
Currently, the repository is organized with crates at the top-level of the project folder (like dsc_lib) and in subfolders (like lib/osinfo_lib). It's difficult to get a mental map of what folders belong to what subproject and where to find or place new crates when needed.
Further, there's a mix of locations for resources. Some are defined in the resources folder, like resources/PSScript, while others are at the top-level, like wmi-adapter.
The current layout of the project and subprojects is difficult to understand without diving into every folder or asking a maintainer.
We should consider defining a layout structure and reorganizing the repository to follow it, so contributors can more easily navigate the project and so maintainers can place new subprojects in a defined location.
I propose reorganizing the project with hierarchical namespacing for resources and extensions, with all crates placed in a single crates folder and symlinked as needed in the other locations. I further propose we rename the crates and folders for consistency and clarity. While this work incurs a significant initial cost, I believe it will simplify maintenance and contribution as the project continues to grow, especially if we plan to continue developing DSC as a monorepo.
That being said, I think there are other options available, and I have laid them out in the remainder of this proposal.
Proposed structures
I have a few different proposals for the structure.
1. Semi-flat structure by programming language.
In this structure:
All rust crates are moved into a crates or rust folder.
All subprojects written in PowerShell are placed into a pwsh folder.
All subprojects written in Python are placed into a python folder.
All subprojects written in Bash are placed into a bash folder.
Language-agnostic folders (docs, schema, .config, etc) remain where they are currently located.
This is true for every proposed structure. The reorganization should affect folders defining projects or modules, not repository-level configuration or information.
Tree view of proposed structure
.
├── .cargo/ # Unchanged
├── .config/ # Unchanged
├── .github/ # Unchanged
├── .pipelines/ # Unchanged
├── .vscode/ # Unchanged
├── archive/ # Unchanged
├── configurations/ # Unchanged
├── docs/ # Unchanged
├── examples/ # Unchanged
├── packaging/ # Unchanged
├── rfc/ # Unchanged
├── schemas/ # Unchanged
├── bash/
│ ├── apt # moved from resources/
│ └── brew # moved from resources/
├── pwsh/
│ ├── Microsoft.DSC.Experimental # moved from resources/
│ ├── PSScript # moved from resources/
│ ├── reboot_pending # moved from top-level
│ ├── wmi-adapter # moved from top-level
│ └── powershell-adapter # moved from top-level
└── rust/
├── dsc/ # CLI, from top-level
├── dsc_lib/ # library, from top-level
├── dscecho/ # resource, from top-level
├── osinfo/ # resource, from top-level
├── osinfo_lib/ # library, from lib/
├── pal/ # library, from top-level
├── process/ # resource, from top-level
├── registry/ # resource, from top-level
├── registry_lib/ # library, from top-level
├── runcommandonset/ # resource, from top-level
├── security_context_lib/ # library, from top-level
├── sshdconfig/ # resource, from top-level
├── dsctest/ # resource, test-only, from tools/
├── test_group_resource/ # resource, test-only, from tools/
├── tree-sitter-dscexpression/ # library, grammar, from top-level
├── tree-sitter-ssh-server-config/ # library, grammarm from top-level
└── y2j/ # CLI, from top-level
2. Semi-flat structure by purpose.
In this structure:
All rust libraries are moved into a crates folder. This is also where the dsc CLI crate goes.
All non-adapter resources are moved into the resources folder, whether implemented in Rust or another language. For rust resources, only the CLI/resource crate goes in this folder. Library crates still go in crates.
We should consider keeping the CLI/resource crates in crates and creating a symlink in resources - that way the crates all live together, but you can quickly find which crates are for a specific resource, too.
All extensions are placed in the extensions folder (this seems to be the case for existing extensions already).
All adapters are placed in the adapters folder.
Tree view of proposed structure
.
├── .cargo/ # Unchanged
├── .config/ # Unchanged
├── .github/ # Unchanged
├── .pipelines/ # Unchanged
├── .vscode/ # Unchanged
├── archive/ # Unchanged
├── configurations/ # Unchanged
├── docs/ # Unchanged
├── examples/ # Unchanged
├── packaging/ # Unchanged
├── rfc/ # Unchanged
├── schemas/ # Unchanged
├── adapters/
│ ├── powershell-adapter # moved from top-level
│ └── wmi-adapter # moved from top-level
├── crates/
│ ├── dsc/ # CLI, from top-level
│ ├── dsc_lib/ # library, from top-level
│ ├── dscecho/ # resource, from top-level
│ ├── osinfo/ # resource, from top-level
│ ├── osinfo_lib/ # library, from lib/
│ ├── pal/ # library, from top-level
│ ├── process/ # resource, from top-level
│ ├── registry/ # resource, from top-level
│ ├── registry_lib/ # library, from top-level
│ ├── runcommandonset/ # resource, from top-level
│ ├── security_context_lib/ # library, from top-level
│ ├── sshdconfig/ # resource, from top-level
│ ├── dsctest/ # resource, test-only, from tools/
│ ├── test_group_resource/ # resource, test-only, from tools/
│ ├── tree-sitter-dscexpression/ # library, grammar, from top-level
│ ├── tree-sitter-ssh-server-config/ # library, grammarm from top-level
│ └── y2j/ # CLI, from top-level
├── extensions/
│ ├── appx/ # Unchanged
│ ├── bicep/ # Unchanged
│ └── test/ # Unchanged
└── resources/
├── apt/ # Unchanged
├── brew/ # Unchanged
├── Microsoft.DSC.Experimental/ # Unchanged
├── PSScript/ # Unchanged
├── dscecho # symlink to crates/dscecho
├── osinfo # symlink to crates/osinfo
├── process # symlink to crates/process
├── registry # symlink to crates/registry
├── runcommandonset # symlink to crates/runcommandonset
├── sshdconfig # symlink to crates/sshdconfig
├── dsctest # symlink to crates/dsctest
└── test_group_resource # symlink to crates/test_group_resource
3. Hierarchical structure by namespace for resources/extensions.
This structure is similar to the semi-flat structure by purpose, except that we clearly indicate resource and extension namespacing in the folder hierarchy:
Tree view of proposed structure
.
├── .cargo/ # Unchanged
├── .config/ # Unchanged
├── .github/ # Unchanged
├── .pipelines/ # Unchanged
├── .vscode/ # Unchanged
├── archive/ # Unchanged
├── configurations/ # Unchanged
├── docs/ # Unchanged
├── examples/ # Unchanged
├── packaging/ # Unchanged
├── rfc/ # Unchanged
├── schemas/ # Unchanged
├── adapters/
│ ├── powershell # moved from top-level powershell-adapter
│ └── wmi # moved from top-level wmi-adapter
├── crates/
│ ├── dsc/ # CLI, from top-level
│ ├── dsc_lib/ # library, from top-level
│ ├── dscecho/ # resource, from top-level
│ ├── osinfo/ # resource, from top-level
│ ├── osinfo_lib/ # library, from lib/
│ ├── pal/ # library, from top-level
│ ├── process/ # resource, from top-level
│ ├── registry/ # resource, from top-level
│ ├── registry_lib/ # library, from top-level
│ ├── runcommandonset/ # resource, from top-level
│ ├── security_context_lib/ # library, from top-level
│ ├── sshdconfig/ # resource, from top-level
│ ├── dsctest/ # resource, test-only, from tools/
│ ├── test_group_resource/ # resource, test-only, from tools/
│ ├── tree-sitter-dscexpression/ # library, grammar, from top-level
│ ├── tree-sitter-ssh-server-config/ # library, grammarm from top-level
│ └── y2j/ # CLI, from top-level
├── extensions/
│ ├── Microsoft.Windows.Appx/
│ │ └── discover/ # moved from extensions/appx
│ ├── Microsoft.DSC.Extension/
│ │ └── bicep/ # moved from extensions/bicep
│ └── test/ # Unchanged
└── resources/
├── DSC.PackageManagement/
│ ├── apt/ # moved from resources/apt
│ └── brew/ # moved from resources/brew
├── Microsoft.DSC.Debug/
│ └── dscecho # symlink to crates/dscecho
├── Microsoft.DSC.Experimental/ # Unchanged
├── Microsoft.DSC.Transitional/
│ ├── PSScript/ # moved from resources/PSScript
│ └── runcommandonset # symlink to crates/runcommandonset
├── Microsoft/
│ ├── osinfo # symlink to crates/osinfo
│ └── process # symlink to crates/process
├── Microsoft.Windows/
│ └── registry # symlink to crates/registry
├── Microsoft.OpenSSH.SSHD/
│ └── sshdconfig # symlink to crates/sshdconfig
└── Test/
├── dsctest # symlink to crates/dsctest
└── test_group_resource # symlink to crates/test_group_resource
Renaming folders
A restructuring would also be a good time to standardize and revise our naming conventions. For the Rust crates, the conventional naming is kebab-case for crates, following the convention <project>-<area>-<subarea>, like dsc-lib. If we don't plan to publish the resource crates separately - if they're only going to be available through DSC itself, or if that's the only supported use - we should consider renaming those crates like dsc-resource-registry and dsc-resource-echo.
Even without moving the folders, renaming the crates would make it much easier to understand at a glance which crate is used for what purpose. Consider the following renames for existing crates:
.
├── dsc/ # CLI / main package, unchanged.
├── dsc-lib/ # library, from `dsc_lib` †
├── dsc-lib-osinfo/ # library, from `lib/osinfo_lib`
├── dsc-lib-pal/ # library, from `pal`
├── dsc-lib-registry/ # library, from `registry_lib`
├── dsc-lib-security_context/ # library, from `security_context_lib`
├── dsc-resource-echo/ # resource, from `dscecho`
├── dsc-resource-osinfo/ # resource, from `osinfo`
├── dsc-resource-process/ # resource, from `process`
├── dsc-resource-registry/ # resource, from `registry`
├── dsc-resource-runcommandonset/ # resource, from `runcommandonset`
├── dsc-resource-sshdconfig/ # resource, from `sshdconfig`
├── dsc-resource-test # resource, test-only, from `tools/dsctest`
├── dsc-resource-test_group/ # resource, test-only, from `tools/test_group_resource`
├── tree-sitter-dsc-expression/ # library, grammar, from `tree-sitter-dscexpression`
├── tree-sitter-ssh-server-config/ # library, grammar, unchanged.
└── y2j/ # CLI, unchanged.
Note
† - Even though we change the crate name from dsc_lib to dsc-lib, only the dependency name changes. The items from that crate are still referenced in snake case like dsc_lib::foo. This won't affect the code that depends on this package, unlike the other library renames.
Regardless of whether we move the folders, renaming the crates to a standardized convention makes it much easier to understand the purpose of code without needing to inspect the implementations.
Recommended structure
This is my final recommended structure:
Moving all crates into the crates folder and renaming the crates.
Moving the adapter folders into adapters without the -adapter suffix on the subfolders.
Moving the extensions into namespaced subfolders.
Moving all non-rust resources into namespaced subfolders under resources and symlinking the resources implemented in Rust.
Tree view of proposed structure
.
├── .cargo/ # Unchanged
├── .config/ # Unchanged
├── .github/ # Unchanged
├── .pipelines/ # Unchanged
├── .vscode/ # Unchanged
├── archive/ # Unchanged
├── configurations/ # Unchanged
├── adapters/ # new folder
│ ├── powershell # moved from `powershell-adapter`
│ └── wmi # moved from `wmi-adapter`
├── crates/ # new folder
│ ├── dsc/ # CLI / main package, from `dsc`.
│ ├── dsc-lib/ # library, from `dsc_lib`
│ ├── dsc-resource-echo/ # resource, from `dscecho`
│ ├── dsc-resource-osinfo/ # resource, from `osinfo`
│ ├── dsc-lib-osinfo/ # library, from `lib/osinfo_lib`
│ ├── dsc-lib-pal/ # library, from `pal`
│ ├── dsc-resource-process/ # resource, from `process`
│ ├── dsc-resource-registry/ # resource, from `registry`
│ ├── dsc-resource-registry-lib/ # library, from `registry_lib`‡
│ ├── dsc-resource-run_command_on_set/ # resource, from `runcommandonset`
│ ├── dsc-lib-security_context/ # library, from `security_context_lib`
│ ├── dsc-resource-sshdconfig/ # resource, from `sshdconfig`
│ ├── dsc-resource-test # resource, test-only, from `tools/dsctest`
│ ├── dsc-resource-test_group/ # resource, test-only, from `tools/test_group_resource`
│ ├── tree-sitter-dsc-expression/ # library, grammar, from `tree-sitter-dscexpression`
│ ├── tree-sitter-ssh-server-config/ # library, grammar, unchanged.
│ └── y2j/ # CLI, from top-level
├── docs/ # Unchanged
├── examples/ # Unchanged
├── extensions/ # Unchanged
│ ├── Microsoft.Windows.Appx/ # new subfolder
│ │ └── Discover/ # moved from `extensions/appx`
│ ├── Microsoft.DSC.Extension/ # new subfolder
│ │ └── Bicep/ # moved from `extensions/bicep`
│ └── test/ # Unchanged
│ ├── discover/ # Unchanged
│ └── secret/ # Unchanged
├── packaging/ # Unchanged
├── resources/ # Unchanged
│ ├── DSC.PackageManagement/ # new subfolder
│ │ ├── Apt/ # moved from `resources/apt`
│ │ └── Brew/ # moved from `resources/brew`
│ ├── Microsoft.DSC.Debug/ # new subfolder
│ │ └── Echo # symlink to `crates/dsc-resource-echo`
│ ├── Microsoft.DSC.Experimental/ # Unchanged
│ ├── Microsoft.DSC.Transitional/ # new subfolder
│ │ ├── PowerShellScript/ # moved from `resources/PSScript`
│ │ └── RunCommandOnSet/ # symlink to `crates/dsc-resource-run_command_on_set`
│ ├── Microsoft/ # new subfolder
│ │ ├── osinfo # symlink to `crates/dsc-resource-osinfo`
│ │ └── process # symlink to `crates/dsc-resource-process`
│ ├── Microsoft.Windows/ # new subfolder
│ │ └── registry # symlink to `crates/dsc-resource-registry`
│ ├── Microsoft.OpenSSH.SSHD/ # new subfolder
│ │ └── sshdconfig # symlink to `crates/dsc-resource-sshdconfig`
│ └── Test/ # new subfolder
│ ├── dsctest # symlink to `crates/dsc-resource-test`
│ └── test_group_resource # symlink to `crates/dsc-resource-test_group`
├── rfc/ # Unchanged
└── schemas/ # Unchanged
Summary of the new feature / enhancement
Currently, the repository is organized with crates at the top-level of the project folder (like
dsc_lib) and in subfolders (likelib/osinfo_lib). It's difficult to get a mental map of what folders belong to what subproject and where to find or place new crates when needed.Further, there's a mix of locations for resources. Some are defined in the
resourcesfolder, likeresources/PSScript, while others are at the top-level, likewmi-adapter.The current layout of the project and subprojects is difficult to understand without diving into every folder or asking a maintainer.
We should consider defining a layout structure and reorganizing the repository to follow it, so contributors can more easily navigate the project and so maintainers can place new subprojects in a defined location.
Proposed technical implementation details (optional)
Summary
I propose reorganizing the project with hierarchical namespacing for resources and extensions, with all crates placed in a single
cratesfolder and symlinked as needed in the other locations. I further propose we rename the crates and folders for consistency and clarity. While this work incurs a significant initial cost, I believe it will simplify maintenance and contribution as the project continues to grow, especially if we plan to continue developing DSC as a monorepo.That being said, I think there are other options available, and I have laid them out in the remainder of this proposal.
Proposed structures
I have a few different proposals for the structure.
1. Semi-flat structure by programming language.
In this structure:
All rust crates are moved into a
cratesorrustfolder.All subprojects written in PowerShell are placed into a
pwshfolder.All subprojects written in Python are placed into a
pythonfolder.All subprojects written in Bash are placed into a
bashfolder.Language-agnostic folders (
docs,schema,.config, etc) remain where they are currently located.This is true for every proposed structure. The reorganization should affect folders defining projects or modules, not repository-level configuration or information.
Tree view of proposed structure
2. Semi-flat structure by purpose.
In this structure:
All rust libraries are moved into a
cratesfolder. This is also where thedscCLI crate goes.All non-adapter resources are moved into the
resourcesfolder, whether implemented in Rust or another language. For rust resources, only the CLI/resource crate goes in this folder. Library crates still go incrates.We should consider keeping the CLI/resource crates in
cratesand creating a symlink inresources- that way the crates all live together, but you can quickly find which crates are for a specific resource, too.All extensions are placed in the
extensionsfolder (this seems to be the case for existing extensions already).All adapters are placed in the
adaptersfolder.Tree view of proposed structure
3. Hierarchical structure by namespace for resources/extensions.
This structure is similar to the semi-flat structure by purpose, except that we clearly indicate resource and extension namespacing in the folder hierarchy:
Tree view of proposed structure
Renaming folders
A restructuring would also be a good time to standardize and revise our naming conventions. For the Rust crates, the conventional naming is
kebab-casefor crates, following the convention<project>-<area>-<subarea>, likedsc-lib. If we don't plan to publish the resource crates separately - if they're only going to be available through DSC itself, or if that's the only supported use - we should consider renaming those crates likedsc-resource-registryanddsc-resource-echo.Even without moving the folders, renaming the crates would make it much easier to understand at a glance which crate is used for what purpose. Consider the following renames for existing crates:
Note
†- Even though we change the crate name fromdsc_libtodsc-lib, only the dependency name changes. The items from that crate are still referenced in snake case likedsc_lib::foo. This won't affect the code that depends on this package, unlike the other library renames.Regardless of whether we move the folders, renaming the crates to a standardized convention makes it much easier to understand the purpose of code without needing to inspect the implementations.
Recommended structure
This is my final recommended structure:
cratesfolder and renaming the crates.adapterswithout the-adaptersuffix on the subfolders.resourcesand symlinking the resources implemented in Rust.Tree view of proposed structure