Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/adaptedresource/manifest.json",
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/adapted/manifest.json",
"type": "PSAdaptedTestClassResource/PSAdaptedTestClass",
"kind": "resource",
"version": "0.1.0",
Expand Down
54 changes: 34 additions & 20 deletions dsc/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use dsc_lib::{
extension_manifest::ExtensionManifest,
},
functions::FunctionDefinition,
schemas::dsc_repo::{DscRepoSchema, RecognizedSchemaVersion, SchemaForm, SchemaUriPrefix},
util::{
get_setting,
parse_input_to_json,
Expand Down Expand Up @@ -163,37 +164,37 @@ pub fn add_fields_to_json(json: &str, fields_to_add: &HashMap<String, String>) -
pub fn get_schema(schema: SchemaType) -> Schema {
match schema {
SchemaType::AdaptedDscResourceManifest => {
schema_for!(AdaptedDscResourceManifest)
repo_schema::<AdaptedDscResourceManifest>()
},
SchemaType::Configuration => {
schema_for!(Configuration)
repo_schema::<Configuration>()
},
SchemaType::ConfigurationExportResult => {
schema_for!(ConfigurationExportResult)
repo_schema::<ConfigurationExportResult>()
},
SchemaType::ConfigurationGetResult => {
schema_for!(ConfigurationGetResult)
repo_schema::<ConfigurationGetResult>()
},
SchemaType::ConfigurationSetResult => {
schema_for!(ConfigurationSetResult)
repo_schema::<ConfigurationSetResult>()
},
SchemaType::ConfigurationTestResult => {
schema_for!(ConfigurationTestResult)
repo_schema::<ConfigurationTestResult>()
},
SchemaType::DscResource => {
schema_for!(DscResource)
repo_schema::<DscResource>()
},
SchemaType::ExtensionDiscoverResult => {
schema_for!(DiscoverResult)
repo_schema::<DiscoverResult>()
},
SchemaType::ExtensionManifest => {
schema_for!(ExtensionManifest)
repo_schema::<ExtensionManifest>()
},
SchemaType::FunctionDefinition => {
schema_for!(FunctionDefinition)
repo_schema::<FunctionDefinition>()
},
SchemaType::GetResult => {
schema_for!(GetResult)
repo_schema::<GetResult>()
},
SchemaType::Include => {
schema_for!(Include)
Expand All @@ -202,35 +203,48 @@ pub fn get_schema(schema: SchemaType) -> Schema {
schema_for!(ManifestList)
},
SchemaType::ResolveResult => {
schema_for!(ResolveResult)
repo_schema::<ResolveResult>()
},
SchemaType::Resource => {
schema_for!(Resource)
repo_schema::<Resource>()
},
SchemaType::ResourceGetResult => {
schema_for!(ResourceGetResult)
repo_schema::<ResourceGetResult>()
},
SchemaType::ResourceSetResult => {
schema_for!(ResourceSetResult)
repo_schema::<ResourceSetResult>()
},
SchemaType::ResourceTestResult => {
schema_for!(ResourceTestResult)
repo_schema::<ResourceTestResult>()
},
SchemaType::ResourceManifest => {
schema_for!(ResourceManifest)
repo_schema::<ResourceManifest>()
},
SchemaType::RestartRequired => {
schema_for!(RestartRequired)
repo_schema::<RestartRequired>()
},
SchemaType::SetResult => {
schema_for!(SetResult)
repo_schema::<SetResult>()
},
SchemaType::TestResult => {
schema_for!(TestResult)
repo_schema::<TestResult>()
},
}
}

fn repo_schema<T: DscRepoSchema>() -> Schema {
let schema_form = if T::SCHEMA_SHOULD_BUNDLE {
SchemaForm::Bundled
} else {
SchemaForm::Canonical
};
T::generate_schema(
RecognizedSchemaVersion::default(),
schema_form,
SchemaUriPrefix::AkaDotMs
)
}

/// Write the JSON object to the console
///
/// # Arguments
Expand Down
2 changes: 1 addition & 1 deletion extensions/powershell/powershell.discover.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ BeforeAll {
$fakeManifest | ConvertTo-Json -Depth 10 | Set-Content -Path $manifestPath

$fakeAdaptedManifest = @{
'$schema' = "https://aka.ms/dsc/schemas/v3/bundled/adaptedresource/manifest.json"
'$schema' = "https://aka.ms/dsc/schemas/v3/bundled/resource/adapted/manifest.json"
type = "Test/FakeAdaptedResource"
kind = "resource"
version = "0.1.0"
Expand Down
2 changes: 1 addition & 1 deletion extensions/test/discover/discover.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ if ($Extensions) {
foreach ($extension in $Extensions.Split(',')) {
$resource = [pscustomobject]@{
manifestContent = @{
'$schema' = "https://aka.ms/dsc/schemas/v3/bundled/adaptedresource/manifest.json"
'$schema' = "https://aka.ms/dsc/schemas/v3/bundled/resource/adapted/manifest.json"
type = "TestDiscover/$count"
kind = "resource"
version = "1.0.0"
Expand Down
4 changes: 4 additions & 0 deletions lib/dsc-lib-jsonschema/locales/en-us.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ unrecognizedSchemaUri = "Unrecognized $schema URI"
validSchemaUrisAre = "Valid schema URIs are"
missingTranslation = "unable to retrieve translation for undefined key '#{key}'"

[dsc_repo.recognized_schema_version]
unrecognizedVersion = "Unrecognized schema version folder"
validVersionsAre = "Valid schema version folders are"

[transforms.idiomaticize_externally_tagged_enum]
applies_to = "invalid application of idiomaticize_externally_tagged_enum; missing 'oneOf' keyword in transforming schema: %{transforming_schema}"
oneOf_array = "invalid application of idiomaticize_externally_tagged_enum; 'oneOf' isn't an array in transforming schema: %{transforming_schema}"
Expand Down
1 change: 1 addition & 0 deletions lib/dsc-lib-jsonschema/src/dsc_repo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub use crate::schema_i18n;

mod recognized_schema_version;
pub use recognized_schema_version::RecognizedSchemaVersion;
pub use recognized_schema_version::UnrecognizedSchemaVersion;

mod schema_form;
pub use schema_form::SchemaForm;
Expand Down
52 changes: 52 additions & 0 deletions lib/dsc-lib-jsonschema/src/dsc_repo/recognized_schema_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,56 @@
//! checks the git tags for non-prerelease versions of DSC to generate the enum type with all of the
//! correct values. The enum can be used transparently throughout the rest of the libraries.

use rust_i18n::t;
use thiserror::Error;

include!(concat!(env!("OUT_DIR"), "/recognized_schema_version.rs"));

/// Defines the error when parsing a string that isn't a recognized schema version folder.
#[derive(Error, Debug, Clone, PartialEq)]
#[error(
"{t}: {0}. {t2}: {1:?}",
t = t!("dsc_repo.recognized_schema_version.unrecognizedVersion"),
t2 = t!("dsc_repo.recognized_schema_version.validVersionsAre")
)]
pub struct UnrecognizedSchemaVersion(pub String, pub Vec<String>);

impl std::str::FromStr for RecognizedSchemaVersion {
type Err = UnrecognizedSchemaVersion;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let candidate = s.trim();
Self::all()
.into_iter()
.find(|version| version.to_string().eq_ignore_ascii_case(candidate))
.ok_or_else(|| UnrecognizedSchemaVersion(
candidate.to_string(),
Self::all().iter().map(ToString::to_string).collect()
))
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn from_str_round_trips_every_recognized_version() {
for version in RecognizedSchemaVersion::all() {
let parsed: RecognizedSchemaVersion = version.to_string().parse().unwrap();
assert_eq!(parsed, version);
}
}

#[test]
fn from_str_is_case_insensitive_and_trims() {
let parsed: RecognizedSchemaVersion = " VNEXT ".parse().unwrap();
assert_eq!(parsed, RecognizedSchemaVersion::VNext);
}

#[test]
fn from_str_rejects_unrecognized_versions() {
assert!("v99.0.0".parse::<RecognizedSchemaVersion>().is_err());
assert!("not-a-version".parse::<RecognizedSchemaVersion>().is_err());
}
}
2 changes: 2 additions & 0 deletions lib/dsc-lib/locales/en-us.toml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ discoverResources = "Discovering '%{kind}' using filter: %{filter}"
progressSearching = "Searching for resources"
extensionSearching = "Searching for extensions"
foundManifest = "Found manifest: %{path}"
adaptedResourceDeprecatedSchemaUri = "Adapted resource manifest '%{path}' uses the deprecated schema URI '%{uri}'. Update the `$schema` value to '%{default_uri}'"
extensionFound = "Extension '%{extension}' version %{version} found"
adapterFound = "Resource adapter '%{adapter}' version %{version} found"
resourceFound = "Resource '%{resource}' version %{version} found"
Expand Down Expand Up @@ -255,6 +256,7 @@ resourceManifestSchemaTitle = "Resource manifest schema URI"
resourceManifestSchemaDescription = "Defines the JSON Schema the resource manifest adheres to."
adaptedResourceManifestSchemaTitle = "Adapted resource manifest schema URI"
adaptedResourceManifestSchemaDescription = "Defines the JSON Schema the adapted resource manifest adheres to."
adaptedResourceManifestDeprecatedSchemaUri = "This URI is deprecated for adapted resource manifests and only recognized for backwards compatibility. Update the `$schema` value to an adapted resource manifest schema URI, like the default: %{uri}"

[extensions.dscextension]
discoverNoResults = "No results returned for discovery extension '%{extension}'"
Expand Down
10 changes: 10 additions & 0 deletions lib/dsc-lib/src/discovery/command_discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::dscerror::DscError;
use crate::extensions::dscextension::{self, DscExtension, Capability as ExtensionCapability};
use crate::extensions::extension_manifest::ExtensionManifest;
use crate::progress::{ProgressBar, ProgressFormat};
use crate::schemas::dsc_repo::DscRepoSchema;
use crate::schemas::transforms::idiomaticize_externally_tagged_enum;
use rust_i18n::t;
use schemars::JsonSchema;
Expand Down Expand Up @@ -866,6 +867,15 @@ pub fn load_adapted_resource_manifest(path: &Path, manifest: &AdaptedDscResource
));
}

if AdaptedDscResourceManifest::is_deprecated_schema_uri(&manifest.schema_version) {
warn!("{}", t!(
"discovery.commandDiscovery.adaptedResourceDeprecatedSchemaUri",
path = path.to_string_lossy(),
uri = manifest.schema_version,
default_uri = AdaptedDscResourceManifest::default_schema_id_uri()
));
}

let mut resource = DscResource::new();
let directory = path.parent().unwrap();
match &manifest.path_or_content {
Expand Down
41 changes: 39 additions & 2 deletions lib/dsc-lib/src/dscresources/adapted_resource_manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub enum AdaptedPathOrContent {
#[serde(deny_unknown_fields, rename_all = "camelCase")]
#[dsc_repo_schema(
base_name = "manifest",
folder_path = "resource",
folder_path = "resource/adapted",
should_bundle = true,
schema_field(
name = schema_version,
Expand All @@ -36,7 +36,7 @@ pub enum AdaptedPathOrContent {
pub struct AdaptedDscResourceManifest {
/// The version of the resource manifest schema.
#[serde(rename = "$schema")]
#[schemars(schema_with = "ResourceManifest::recognized_schema_uris_subschema")]
#[schemars(schema_with = "AdaptedDscResourceManifest::recognized_schema_uris_with_deprecated_subschema")]
pub schema_version: String,
/// The namespaced name of the resource.
#[serde(rename="type")]
Expand Down Expand Up @@ -64,3 +64,40 @@ pub struct AdaptedDscResourceManifest {
/// The JSON Schema of the resource.
pub schema: Map<String, Value>,
}

impl AdaptedDscResourceManifest {
pub const LEGACY_SHIPPED_SCHEMA_URI: &'static str = "https://aka.ms/dsc/schemas/v3/bundled/adaptedresource/manifest.json";

#[must_use]
pub fn is_deprecated_schema_uri(uri: &String) -> bool {
uri.as_str() == Self::LEGACY_SHIPPED_SCHEMA_URI || ResourceManifest::is_recognized_schema_uri(uri)
}

fn recognized_schema_uris_with_deprecated_subschema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
let mut subschema = <Self as DscRepoSchema>::recognized_schema_uris_subschema(generator);
subschema.remove("enum");
let recognized_uris: Vec<Value> = Self::recognized_schema_uris()
.into_iter()
.map(Value::String)
.collect();
let deprecated_uris: Vec<Value> = ResourceManifest::recognized_schema_uris()
.into_iter()
.chain([Self::LEGACY_SHIPPED_SCHEMA_URI.to_string()])
.map(Value::String)
.collect();
subschema.insert("oneOf".to_string(), serde_json::json!([
{
"enum": recognized_uris,
},
{
"enum": deprecated_uris,
"deprecated": true,
"deprecationMessage": t!(
"dscresources.resource_manifest.adaptedResourceManifestDeprecatedSchemaUri",
uri = Self::default_schema_id_uri()
),
},
]));
subschema
}
}
2 changes: 1 addition & 1 deletion lib/dsc-lib/src/dscresources/invoke_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ pub struct DeleteResult {
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, DscRepoSchema)]
#[dsc_repo_schema(base_name = "delete", folder_path = "outputs/resource")]
#[dsc_repo_schema(base_name = "delete.whatIf", folder_path = "outputs/resource")]
#[serde(deny_unknown_fields)]
pub struct DeleteWhatIfResult {
#[serde(rename = "whatIf", skip_serializing_if = "Option::is_none")]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Adapted Registry resource for personalization settings defined in:
# https://learn.microsoft.com/en-us/windows/apps/develop/settings/settings-common#personalization---colors

$schema: https://aka.ms/dsc/schemas/v3/bundled/adaptedresource/manifest.json
$schema: https://aka.ms/dsc/schemas/v3/bundled/resource/adapted/manifest.json
type: Microsoft.Windows/Personalization
kind: resource
version: 1.0.0
Expand Down
2 changes: 1 addition & 1 deletion tools/dsctest/adaptedTest.dsc.adaptedResource.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/adaptedresource/manifest.json",
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/adapted/manifest.json",
"type": "Adapted/Three",
"kind": "resource",
"version": "1.0.0",
Expand Down
2 changes: 1 addition & 1 deletion tools/dsctest/deprecated/deprecated.dsc.manifests.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"adaptedResources": [
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/adaptedresource/manifest.json",
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/adapted/manifest.json",
"type": "Adapted/Deprecated",
"deprecationMessage": "This adapted resource is deprecated",
"kind": "resource",
Expand Down
4 changes: 2 additions & 2 deletions tools/dsctest/dsctest.dsc.manifests.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"adaptedResources": [
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/adaptedresource/manifest.json",
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/adapted/manifest.json",
"type": "Adapted/Two",
"kind": "resource",
"version": "2.0.0",
Expand Down Expand Up @@ -38,7 +38,7 @@
}
},
{
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/adaptedresource/manifest.json",
"$schema": "https://aka.ms/dsc/schemas/v3/bundled/resource/adapted/manifest.json",
"type": "Adapted/Four",
"kind": "resource",
"version": "1.0.0",
Expand Down
7 changes: 7 additions & 0 deletions xtask/locales/en-us.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
about = "xtask provides build helpers for the DSC rust project."
schemaAbout = "Commands for managing DSC repository schemas."
schemaExportAbout = "Export DSC schemas to disk."
schemaExportVersionHelp = "The schema version folder to export, like 'v3.2' or 'vNext'. May be specified multiple times. Defaults to 'vNext'."
schemaExportReleaseHelp = "A release version like '3.3.0'. Exports the patch, minor, and major version folders for the release, like 'v3.3.0', 'v3.3', and 'v3'."

[main]
invalidReleaseVersion = "Invalid release version; expected a full version like '3.3.0'"
unrecognizedReleaseFolder = "Schema version folder isn't recognized; if the release was just tagged, refresh 'lib/dsc-lib-jsonschema/.versions.json' by running '.versions.ps1' and rebuild"

[schemas.export]
serializationFailure = "Failed to serialize JSON Schema as string"
ioError = "Failed to export JSON Schema, IO error"
duplicatePath = "Multiple schemas export to the same path; check the `dsc_repo_schema` attributes for a `base_name`/`folder_path` collision"
Loading
Loading