From 231395449bc296f07b81a2dfcbad511c762f8b3d Mon Sep 17 00:00:00 2001 From: Alitzel Mendez Bustillo Date: Wed, 27 Nov 2024 15:41:36 -0800 Subject: [PATCH 1/7] [WIP] Add @armCustomResourceDecorator --- .../typespec-azure-resource-manager/README.md | 18 +++ .../generated-defs/Azure.ResourceManager.ts | 9 ++ .../lib/decorators.tsp | 8 ++ .../src/lib.ts | 6 + .../src/operations.ts | 10 +- .../src/private.decorators.ts | 2 + .../src/resource.ts | 30 ++++- .../src/rules/utils.ts | 8 ++ .../src/state.ts | 1 + .../src/tsp-index.ts | 2 + .../test/resource.test.ts | 125 ++++++++++++++++++ .../reference/decorators.md | 17 +++ .../reference/index.mdx | 1 + 13 files changed, 233 insertions(+), 4 deletions(-) diff --git a/packages/typespec-azure-resource-manager/README.md b/packages/typespec-azure-resource-manager/README.md index 184508b21a..14c24dff7d 100644 --- a/packages/typespec-azure-resource-manager/README.md +++ b/packages/typespec-azure-resource-manager/README.md @@ -65,6 +65,7 @@ Available ruleSets: ### Azure.ResourceManager - [`@armCommonTypesVersion`](#@armcommontypesversion) +- [`@armCustomResource`](#@armcustomresource) - [`@armLibraryNamespace`](#@armlibrarynamespace) - [`@armProviderNamespace`](#@armprovidernamespace) - [`@armProviderNameValue`](#@armprovidernamevalue) @@ -105,6 +106,23 @@ the version of the Azure Resource Manager common-types to use for refs in emitte | ------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | | version | `valueof string \| EnumMember` | The Azure.ResourceManager.CommonTypes.Versions for the desired common-types version or an equivalent string value like "v5". | +#### `@armCustomResource` + +This decorator is used on resources that do not satisfy the definition of a resource +but need to be identified as such. + +```typespec +@Azure.ResourceManager.armCustomResource +``` + +##### Target + +`Model` + +##### Parameters + +None + #### `@armLibraryNamespace` `@armLibraryNamespace` designates a namespace as containign Azure Resource Manager Provider information. diff --git a/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts b/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts index 5583d8206e..2c39af94c8 100644 --- a/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts +++ b/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts @@ -249,6 +249,14 @@ export type ArmCommonTypesVersionDecorator = ( */ export type ArmVirtualResourceDecorator = (context: DecoratorContext, target: Model) => void; +/** + * This decorator is used on resources that do not satisfy the definition of a resource + * but need to be identified as such. + * + * @param propertiesType : Type of the resource properties. + */ +export type ArmCustomResourceDecorator = (context: DecoratorContext, target: Model) => void; + /** * This decorator sets the base type of the given resource. * @@ -280,6 +288,7 @@ export type AzureResourceManagerDecorators = { armResourceList: ArmResourceListDecorator; armResourceOperations: ArmResourceOperationsDecorator; armCommonTypesVersion: ArmCommonTypesVersionDecorator; + armCustomResource: ArmCustomResourceDecorator; armVirtualResource: ArmVirtualResourceDecorator; resourceBaseType: ResourceBaseTypeDecorator; }; diff --git a/packages/typespec-azure-resource-manager/lib/decorators.tsp b/packages/typespec-azure-resource-manager/lib/decorators.tsp index 2b99ea3b1f..44fc4e0467 100644 --- a/packages/typespec-azure-resource-manager/lib/decorators.tsp +++ b/packages/typespec-azure-resource-manager/lib/decorators.tsp @@ -182,6 +182,14 @@ extern dec armCommonTypesVersion( */ extern dec armVirtualResource(target: Model); +/** + * This decorator is used on resources that do not satisfy the definition of a resource + * but need to be identified as such. + * + * @param propertiesType : Type of the resource properties. + */ +extern dec armCustomResource(target: Model); + /** * This decorator sets the base type of the given resource. * diff --git a/packages/typespec-azure-resource-manager/src/lib.ts b/packages/typespec-azure-resource-manager/src/lib.ts index 11dd6eca9c..c134e5efc0 100644 --- a/packages/typespec-azure-resource-manager/src/lib.ts +++ b/packages/typespec-azure-resource-manager/src/lib.ts @@ -36,6 +36,12 @@ export const $lib = createTypeSpecLibrary({ default: "Resource types must include a string property called 'name'.", }, }, + "arm-custom-resource-usage-discourage": { + severity: "warning", + messages: { + default: "Avoid using this decorator as it does not provide validation for ARM resources.", + }, + }, "arm-resource-missing-name-key-decorator": { severity: "error", messages: { diff --git a/packages/typespec-azure-resource-manager/src/operations.ts b/packages/typespec-azure-resource-manager/src/operations.ts index 5be5806562..6628a29bb4 100644 --- a/packages/typespec-azure-resource-manager/src/operations.ts +++ b/packages/typespec-azure-resource-manager/src/operations.ts @@ -32,6 +32,7 @@ import { isArmLibraryNamespace } from "./namespace.js"; import { getArmResourceInfo, getResourceBaseType, + isArmCustomResource, isArmVirtualResource, ResourceBaseType, } from "./resource.js"; @@ -234,8 +235,11 @@ export function armRenameListByOperationInternal( [parentTypeName, parentFriendlyTypeName] = getArmParentName(context.program, resourceType); } const parentType = getParentResource(program, resourceType); - - if (parentType && !isArmVirtualResource(program, parentType)) { + if ( + parentType && + !isArmVirtualResource(program, parentType) && + !isArmCustomResource(program, parentType) + ) { const parentResourceInfo = getArmResourceInfo(program, parentType); if ( !parentResourceInfo && @@ -278,7 +282,7 @@ export function armRenameListByOperationInternal( function getArmParentName(program: Program, resource: Model): string[] { const parent = getParentResource(program, resource); - if (parent && isArmVirtualResource(program, parent)) { + if (parent && (isArmVirtualResource(program, parent) || isArmCustomResource(program, parent))) { const parentName = getFriendlyName(program, parent) ?? parent.name; if (parentName === undefined || parentName.length < 2) { return ["", ""]; diff --git a/packages/typespec-azure-resource-manager/src/private.decorators.ts b/packages/typespec-azure-resource-manager/src/private.decorators.ts index 128438e753..aded1eda64 100644 --- a/packages/typespec-azure-resource-manager/src/private.decorators.ts +++ b/packages/typespec-azure-resource-manager/src/private.decorators.ts @@ -39,6 +39,7 @@ import { ResourceBaseType, getArmResourceKind, getResourceBaseType, + isArmCustomResource, isArmVirtualResource, resolveResourceBaseType, } from "./resource.js"; @@ -325,6 +326,7 @@ const $armResourceInternal: ArmResourceInternalDecorator = ( let kind = getArmResourceKind(resourceType); if (isArmVirtualResource(program, resourceType)) kind = "Virtual"; + if (isArmCustomResource(program, resourceType)) kind = "Custom"; if (!kind) { reportDiagnostic(program, { code: "arm-resource-invalid-base-type", diff --git a/packages/typespec-azure-resource-manager/src/resource.ts b/packages/typespec-azure-resource-manager/src/resource.ts index 232965e9e5..acfd1e50c8 100644 --- a/packages/typespec-azure-resource-manager/src/resource.ts +++ b/packages/typespec-azure-resource-manager/src/resource.ts @@ -17,6 +17,7 @@ import { import { isPathParam } from "@typespec/http"; import { $autoRoute, getParentResource, getSegment } from "@typespec/rest"; import { + ArmCustomResourceDecorator, ArmProviderNameValueDecorator, ArmResourceOperationsDecorator, ArmVirtualResourceDecorator, @@ -32,9 +33,10 @@ import { reportDiagnostic } from "./lib.js"; import { getArmProviderNamespace, isArmLibraryNamespace } from "./namespace.js"; import { ArmResourceOperations, resolveResourceOperations } from "./operations.js"; import { getArmResource, listArmResources } from "./private.decorators.js"; +import { isLegacyTypeSpec } from "./rules/utils.js"; import { ArmStateKeys } from "./state.js"; -export type ArmResourceKind = "Tracked" | "Proxy" | "Extension" | "Virtual"; +export type ArmResourceKind = "Tracked" | "Proxy" | "Extension" | "Virtual" | "Custom"; /** * Interface for ARM resource detail base. @@ -92,6 +94,20 @@ export const $armVirtualResource: ArmVirtualResourceDecorator = ( } }; +export const $armCustomResource: ArmCustomResourceDecorator = ( + context: DecoratorContext, + entity: Model, +) => { + //TODO: investigate which rules/constrains will make this a resource and add validation + const { program } = context; + if (isTemplateDeclaration(entity)) return; + if (!isLegacyTypeSpec(program, entity)) { + reportDiagnostic(program, { code: "arm-custom-resource-usage-discourage", target: entity }); + } + program.stateMap(ArmStateKeys.armCustomResource).set(entity, "Custom"); + return; +}; + function getProperty( target: Model, predicate: (property: ModelProperty) => boolean, @@ -114,6 +130,18 @@ export function isArmVirtualResource(program: Program, target: Model): boolean { return false; } +/** + * Determine if the given model is a custom resource. + * @param program The program to process. + * @param target The model to check. + * @returns true if the model or any model it extends is marked as a resource, otherwise false. + */ +export function isArmCustomResource(program: Program, target: Model): boolean { + if (program.stateMap(ArmStateKeys.armCustomResource).has(target)) return true; + if (target.baseModel) return isArmCustomResource(program, target.baseModel); + return false; +} + function resolveArmResourceDetails( program: Program, resource: ArmResourceDetailsBase, diff --git a/packages/typespec-azure-resource-manager/src/rules/utils.ts b/packages/typespec-azure-resource-manager/src/rules/utils.ts index 1a933ccf8f..f9bc704732 100644 --- a/packages/typespec-azure-resource-manager/src/rules/utils.ts +++ b/packages/typespec-azure-resource-manager/src/rules/utils.ts @@ -93,6 +93,14 @@ export function isInternalTypeSpec( ); } +export function isLegacyTypeSpec( + program: Program, + type: Model | Operation | ModelProperty | Interface | Namespace, +): boolean { + const namespace = getNamespaceName(program, type); + return namespace.includes(".Legacy"); +} + export function isSourceOperationResourceManagerInternal( operation: Operation | undefined, ): boolean { diff --git a/packages/typespec-azure-resource-manager/src/state.ts b/packages/typespec-azure-resource-manager/src/state.ts index e6ba7365cd..bc84415ebf 100644 --- a/packages/typespec-azure-resource-manager/src/state.ts +++ b/packages/typespec-azure-resource-manager/src/state.ts @@ -20,6 +20,7 @@ export const ArmStateKeys = { armSingletonResources: azureResourceManagerCreateStateSymbol("armSingletonResources"), resourceBaseType: azureResourceManagerCreateStateSymbol("resourceBaseTypeKey"), armBuiltInResource: azureResourceManagerCreateStateSymbol("armExternalResource"), + armCustomResource: azureResourceManagerCreateStateSymbol("armCustomResource"), // private.decorator.ts azureResourceBase: azureResourceManagerCreateStateSymbol("azureResourceBase"), diff --git a/packages/typespec-azure-resource-manager/src/tsp-index.ts b/packages/typespec-azure-resource-manager/src/tsp-index.ts index 1766ca62f3..5f6edef242 100644 --- a/packages/typespec-azure-resource-manager/src/tsp-index.ts +++ b/packages/typespec-azure-resource-manager/src/tsp-index.ts @@ -12,6 +12,7 @@ import { $armResourceUpdate, } from "./operations.js"; import { + $armCustomResource, $armProviderNameValue, $armResourceOperations, $armVirtualResource, @@ -48,6 +49,7 @@ export const $decorators = { armResourceList: $armResourceList, armResourceOperations: $armResourceOperations, armCommonTypesVersion: $armCommonTypesVersion, + armCustomResource: $armCustomResource, armVirtualResource: $armVirtualResource, resourceBaseType: $resourceBaseType, } satisfies AzureResourceManagerDecorators, diff --git a/packages/typespec-azure-resource-manager/test/resource.test.ts b/packages/typespec-azure-resource-manager/test/resource.test.ts index b7f6884758..a1febca75a 100644 --- a/packages/typespec-azure-resource-manager/test/resource.test.ts +++ b/packages/typespec-azure-resource-manager/test/resource.test.ts @@ -716,6 +716,77 @@ describe("typespec-azure-resource-manager: ARM resource model", () => { strictEqual(nameProperty?.type.kind, "Scalar"); strictEqual(nameProperty?.type.name, "WidgetNameType"); }); + + it("emits diagnostics for non ARM resources", async () => { + const { diagnostics } = await checkFor(` + @armProviderNamespace + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + namespace Microsoft.Contoso { + @parentResource(Microsoft.Person.Contoso.Person) + model Employee is TrackedResource { + ...ResourceNameParameter; + } + + /** Employee properties */ + model EmployeeProperties { + /** The status of the last operation. */ + @visibility("read") + provisioningState?: ProvisioningState; + } + + /** The provisioning state of a resource. */ + union ProvisioningState { + string, + + /** Resource has been created. */ + Succeeded: "Succeeded", + + /** Resource creation failed. */ + Failed: "Failed", + + /** Resource creation was canceled. */ + Canceled: "Canceled", + } + + interface Operations extends Azure.ResourceManager.Operations {} + + @armResourceOperations + interface Employees { + listByResourceGroup is ArmResourceListByParent; + } + } + + namespace Microsoft.Person.Contoso { + /** Person parent */ + model Person { + /** The parent name */ + @path + @visibility("read") + @segment("parents") + @key + name: string; + } + } +`); + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-azure-resource-manager/arm-resource-missing", + message: "No @armResource registration found for type Person", + }, + { + code: "@azure-tools/typespec-azure-resource-manager/parent-type", + message: "Parent type Person of Employee is not registered as an ARM resource type.", + }, + { + code: "@azure-tools/typespec-azure-resource-manager/arm-resource-missing", + message: "No @armResource registration found for type Person", + }, + { + code: "@azure-tools/typespec-azure-resource-manager/parent-type", + message: "Parent type Person of Employee is not registered as an ARM resource type.", + }, + ]); + }); }); it("emits default optional properties for resource", async () => { @@ -761,3 +832,57 @@ it("emits required properties for resource with @armResourcePropertiesOptionalit strictEqual(resources.length, 1); strictEqual(resources[0].typespecType.properties.get("properties")?.optional, false); }); + +it("resource with customResource identifier", async () => {}); + +it("recognizes resource with customResource identifier", async () => { + const { diagnostics } = await checkFor(` + @armProviderNamespace + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + namespace Microsoft.Contoso { + @parentResource(Microsoft.Person.Contoso.Person) + model Employee is TrackedResource { + ...ResourceNameParameter; + } + + /** Employee properties */ + model EmployeeProperties { + /** The status of the last operation. */ + @visibility("read") + provisioningState?: ProvisioningState; + } + + /** The provisioning state of a resource. */ + union ProvisioningState { + string, + + /** Resource has been created. */ + Succeeded: "Succeeded", + + /** Resource creation failed. */ + Failed: "Failed", + + /** Resource creation was canceled. */ + Canceled: "Canceled", + } + + interface Operations extends Azure.ResourceManager.Operations {} + + @armResourceOperations + interface Employees { + listByResourceGroup is ArmResourceListByParent; + } + } + + namespace Microsoft.Person.Contoso { + /** Person parent */ + #suppress "@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage" "For test" + @armCustomResource + model Person { + /** The parent name */ + name: string; + } + } +`); + expectDiagnosticEmpty(diagnostics); +}); diff --git a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md index eabf425fd7..b9cda9dd3f 100644 --- a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md +++ b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md @@ -25,6 +25,23 @@ the version of the Azure Resource Manager common-types to use for refs in emitte | ------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | | version | `valueof string \| EnumMember` | The Azure.ResourceManager.CommonTypes.Versions for the desired common-types version or an equivalent string value like "v5". | +### `@armCustomResource` {#@Azure.ResourceManager.armCustomResource} + +This decorator is used on resources that do not satisfy the definition of a resource +but need to be identified as such. + +```typespec +@Azure.ResourceManager.armCustomResource +``` + +#### Target + +`Model` + +#### Parameters + +None + ### `@armLibraryNamespace` {#@Azure.ResourceManager.armLibraryNamespace} `@armLibraryNamespace` designates a namespace as containign Azure Resource Manager Provider information. diff --git a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/index.mdx b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/index.mdx index fa54489830..b14b42997b 100644 --- a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/index.mdx +++ b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/index.mdx @@ -35,6 +35,7 @@ npm install --save-peer @azure-tools/typespec-azure-resource-manager ### Decorators - [`@armCommonTypesVersion`](./decorators.md#@Azure.ResourceManager.armCommonTypesVersion) +- [`@armCustomResource`](./decorators.md#@Azure.ResourceManager.armCustomResource) - [`@armLibraryNamespace`](./decorators.md#@Azure.ResourceManager.armLibraryNamespace) - [`@armProviderNamespace`](./decorators.md#@Azure.ResourceManager.armProviderNamespace) - [`@armProviderNameValue`](./decorators.md#@Azure.ResourceManager.armProviderNameValue) From 3bb22d545fd22184bc01b9a11ac7bb17a5565de6 Mon Sep 17 00:00:00 2001 From: Alitzel Mendez Bustillo Date: Wed, 27 Nov 2024 15:44:08 -0800 Subject: [PATCH 2/7] summary of changes --- ...-decorator-custom-azure-resource-2024-10-27-15-43-13.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .chronus/changes/new-decorator-custom-azure-resource-2024-10-27-15-43-13.md diff --git a/.chronus/changes/new-decorator-custom-azure-resource-2024-10-27-15-43-13.md b/.chronus/changes/new-decorator-custom-azure-resource-2024-10-27-15-43-13.md new file mode 100644 index 0000000000..74ca033898 --- /dev/null +++ b/.chronus/changes/new-decorator-custom-azure-resource-2024-10-27-15-43-13.md @@ -0,0 +1,7 @@ +--- +changeKind: feature +packages: + - "@azure-tools/typespec-azure-resource-manager" +--- + +Add the `@armCustomResources` decorator to identify ARM resources that do not use the base resource types. From e9b4be409a5e8954f98a5bb2e94b8761edfbe818 Mon Sep 17 00:00:00 2001 From: Alitzel Mendez Bustillo Date: Wed, 27 Nov 2024 16:14:17 -0800 Subject: [PATCH 3/7] rename decorator --- .../typespec-azure-resource-manager/README.md | 36 +++++++++---------- .../generated-defs/Azure.ResourceManager.ts | 4 +-- .../lib/decorators.tsp | 2 +- .../src/operations.ts | 6 ++-- .../src/private.decorators.ts | 4 +-- .../src/resource.ts | 12 +++---- .../src/state.ts | 2 +- .../src/tsp-index.ts | 4 +-- .../test/resource.test.ts | 2 +- .../reference/decorators.md | 34 +++++++++--------- .../reference/index.mdx | 2 +- 11 files changed, 54 insertions(+), 54 deletions(-) diff --git a/packages/typespec-azure-resource-manager/README.md b/packages/typespec-azure-resource-manager/README.md index 14c24dff7d..b8e1292777 100644 --- a/packages/typespec-azure-resource-manager/README.md +++ b/packages/typespec-azure-resource-manager/README.md @@ -65,7 +65,6 @@ Available ruleSets: ### Azure.ResourceManager - [`@armCommonTypesVersion`](#@armcommontypesversion) -- [`@armCustomResource`](#@armcustomresource) - [`@armLibraryNamespace`](#@armlibrarynamespace) - [`@armProviderNamespace`](#@armprovidernamespace) - [`@armProviderNameValue`](#@armprovidernamevalue) @@ -78,6 +77,7 @@ Available ruleSets: - [`@armResourceRead`](#@armresourceread) - [`@armResourceUpdate`](#@armresourceupdate) - [`@armVirtualResource`](#@armvirtualresource) +- [`@customAzureResource`](#@customazureresource) - [`@extensionResource`](#@extensionresource) - [`@locationResource`](#@locationresource) - [`@resourceBaseType`](#@resourcebasetype) @@ -106,23 +106,6 @@ the version of the Azure Resource Manager common-types to use for refs in emitte | ------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | | version | `valueof string \| EnumMember` | The Azure.ResourceManager.CommonTypes.Versions for the desired common-types version or an equivalent string value like "v5". | -#### `@armCustomResource` - -This decorator is used on resources that do not satisfy the definition of a resource -but need to be identified as such. - -```typespec -@Azure.ResourceManager.armCustomResource -``` - -##### Target - -`Model` - -##### Parameters - -None - #### `@armLibraryNamespace` `@armLibraryNamespace` designates a namespace as containign Azure Resource Manager Provider information. @@ -348,6 +331,23 @@ Azure.ResourceManager common types. None +#### `@customAzureResource` + +This decorator is used on resources that do not satisfy the definition of a resource +but need to be identified as such. + +```typespec +@Azure.ResourceManager.customAzureResource +``` + +##### Target + +`Model` + +##### Parameters + +None + #### `@extensionResource` `@extensionResource` marks an Azure Resource Manager resource model as an Extension resource. diff --git a/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts b/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts index 2c39af94c8..020b345961 100644 --- a/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts +++ b/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts @@ -255,7 +255,7 @@ export type ArmVirtualResourceDecorator = (context: DecoratorContext, target: Mo * * @param propertiesType : Type of the resource properties. */ -export type ArmCustomResourceDecorator = (context: DecoratorContext, target: Model) => void; +export type CustomAzureResourceDecorator = (context: DecoratorContext, target: Model) => void; /** * This decorator sets the base type of the given resource. @@ -288,7 +288,7 @@ export type AzureResourceManagerDecorators = { armResourceList: ArmResourceListDecorator; armResourceOperations: ArmResourceOperationsDecorator; armCommonTypesVersion: ArmCommonTypesVersionDecorator; - armCustomResource: ArmCustomResourceDecorator; armVirtualResource: ArmVirtualResourceDecorator; + customAzureResource: CustomAzureResourceDecorator; resourceBaseType: ResourceBaseTypeDecorator; }; diff --git a/packages/typespec-azure-resource-manager/lib/decorators.tsp b/packages/typespec-azure-resource-manager/lib/decorators.tsp index 44fc4e0467..be0d090d1a 100644 --- a/packages/typespec-azure-resource-manager/lib/decorators.tsp +++ b/packages/typespec-azure-resource-manager/lib/decorators.tsp @@ -188,7 +188,7 @@ extern dec armVirtualResource(target: Model); * * @param propertiesType : Type of the resource properties. */ -extern dec armCustomResource(target: Model); +extern dec customAzureResource(target: Model); /** * This decorator sets the base type of the given resource. diff --git a/packages/typespec-azure-resource-manager/src/operations.ts b/packages/typespec-azure-resource-manager/src/operations.ts index 6628a29bb4..60236a83e4 100644 --- a/packages/typespec-azure-resource-manager/src/operations.ts +++ b/packages/typespec-azure-resource-manager/src/operations.ts @@ -32,8 +32,8 @@ import { isArmLibraryNamespace } from "./namespace.js"; import { getArmResourceInfo, getResourceBaseType, - isArmCustomResource, isArmVirtualResource, + isCustomAzureResource, ResourceBaseType, } from "./resource.js"; import { ArmStateKeys } from "./state.js"; @@ -238,7 +238,7 @@ export function armRenameListByOperationInternal( if ( parentType && !isArmVirtualResource(program, parentType) && - !isArmCustomResource(program, parentType) + !isCustomAzureResource(program, parentType) ) { const parentResourceInfo = getArmResourceInfo(program, parentType); if ( @@ -282,7 +282,7 @@ export function armRenameListByOperationInternal( function getArmParentName(program: Program, resource: Model): string[] { const parent = getParentResource(program, resource); - if (parent && (isArmVirtualResource(program, parent) || isArmCustomResource(program, parent))) { + if (parent && (isArmVirtualResource(program, parent) || isCustomAzureResource(program, parent))) { const parentName = getFriendlyName(program, parent) ?? parent.name; if (parentName === undefined || parentName.length < 2) { return ["", ""]; diff --git a/packages/typespec-azure-resource-manager/src/private.decorators.ts b/packages/typespec-azure-resource-manager/src/private.decorators.ts index aded1eda64..46b9896b6f 100644 --- a/packages/typespec-azure-resource-manager/src/private.decorators.ts +++ b/packages/typespec-azure-resource-manager/src/private.decorators.ts @@ -39,8 +39,8 @@ import { ResourceBaseType, getArmResourceKind, getResourceBaseType, - isArmCustomResource, isArmVirtualResource, + isCustomAzureResource, resolveResourceBaseType, } from "./resource.js"; import { ArmStateKeys } from "./state.js"; @@ -326,7 +326,7 @@ const $armResourceInternal: ArmResourceInternalDecorator = ( let kind = getArmResourceKind(resourceType); if (isArmVirtualResource(program, resourceType)) kind = "Virtual"; - if (isArmCustomResource(program, resourceType)) kind = "Custom"; + if (isCustomAzureResource(program, resourceType)) kind = "Custom"; if (!kind) { reportDiagnostic(program, { code: "arm-resource-invalid-base-type", diff --git a/packages/typespec-azure-resource-manager/src/resource.ts b/packages/typespec-azure-resource-manager/src/resource.ts index acfd1e50c8..a6add95c3b 100644 --- a/packages/typespec-azure-resource-manager/src/resource.ts +++ b/packages/typespec-azure-resource-manager/src/resource.ts @@ -17,10 +17,10 @@ import { import { isPathParam } from "@typespec/http"; import { $autoRoute, getParentResource, getSegment } from "@typespec/rest"; import { - ArmCustomResourceDecorator, ArmProviderNameValueDecorator, ArmResourceOperationsDecorator, ArmVirtualResourceDecorator, + CustomAzureResourceDecorator, ExtensionResourceDecorator, LocationResourceDecorator, ResourceBaseTypeDecorator, @@ -94,7 +94,7 @@ export const $armVirtualResource: ArmVirtualResourceDecorator = ( } }; -export const $armCustomResource: ArmCustomResourceDecorator = ( +export const $customAzureResource: CustomAzureResourceDecorator = ( context: DecoratorContext, entity: Model, ) => { @@ -104,7 +104,7 @@ export const $armCustomResource: ArmCustomResourceDecorator = ( if (!isLegacyTypeSpec(program, entity)) { reportDiagnostic(program, { code: "arm-custom-resource-usage-discourage", target: entity }); } - program.stateMap(ArmStateKeys.armCustomResource).set(entity, "Custom"); + program.stateMap(ArmStateKeys.customAzureResource).set(entity, "Custom"); return; }; @@ -136,9 +136,9 @@ export function isArmVirtualResource(program: Program, target: Model): boolean { * @param target The model to check. * @returns true if the model or any model it extends is marked as a resource, otherwise false. */ -export function isArmCustomResource(program: Program, target: Model): boolean { - if (program.stateMap(ArmStateKeys.armCustomResource).has(target)) return true; - if (target.baseModel) return isArmCustomResource(program, target.baseModel); +export function isCustomAzureResource(program: Program, target: Model): boolean { + if (program.stateMap(ArmStateKeys.customAzureResource).has(target)) return true; + if (target.baseModel) return isCustomAzureResource(program, target.baseModel); return false; } diff --git a/packages/typespec-azure-resource-manager/src/state.ts b/packages/typespec-azure-resource-manager/src/state.ts index bc84415ebf..7323a184d3 100644 --- a/packages/typespec-azure-resource-manager/src/state.ts +++ b/packages/typespec-azure-resource-manager/src/state.ts @@ -20,7 +20,7 @@ export const ArmStateKeys = { armSingletonResources: azureResourceManagerCreateStateSymbol("armSingletonResources"), resourceBaseType: azureResourceManagerCreateStateSymbol("resourceBaseTypeKey"), armBuiltInResource: azureResourceManagerCreateStateSymbol("armExternalResource"), - armCustomResource: azureResourceManagerCreateStateSymbol("armCustomResource"), + customAzureResource: azureResourceManagerCreateStateSymbol("azureCustomResource"), // private.decorator.ts azureResourceBase: azureResourceManagerCreateStateSymbol("azureResourceBase"), diff --git a/packages/typespec-azure-resource-manager/src/tsp-index.ts b/packages/typespec-azure-resource-manager/src/tsp-index.ts index 5f6edef242..b722e204cb 100644 --- a/packages/typespec-azure-resource-manager/src/tsp-index.ts +++ b/packages/typespec-azure-resource-manager/src/tsp-index.ts @@ -12,10 +12,10 @@ import { $armResourceUpdate, } from "./operations.js"; import { - $armCustomResource, $armProviderNameValue, $armResourceOperations, $armVirtualResource, + $customAzureResource, $extensionResource, $locationResource, $resourceBaseType, @@ -49,7 +49,7 @@ export const $decorators = { armResourceList: $armResourceList, armResourceOperations: $armResourceOperations, armCommonTypesVersion: $armCommonTypesVersion, - armCustomResource: $armCustomResource, + customAzureResource: $customAzureResource, armVirtualResource: $armVirtualResource, resourceBaseType: $resourceBaseType, } satisfies AzureResourceManagerDecorators, diff --git a/packages/typespec-azure-resource-manager/test/resource.test.ts b/packages/typespec-azure-resource-manager/test/resource.test.ts index a1febca75a..3a4b2aa598 100644 --- a/packages/typespec-azure-resource-manager/test/resource.test.ts +++ b/packages/typespec-azure-resource-manager/test/resource.test.ts @@ -877,7 +877,7 @@ it("recognizes resource with customResource identifier", async () => { namespace Microsoft.Person.Contoso { /** Person parent */ #suppress "@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage" "For test" - @armCustomResource + @customAzureResource model Person { /** The parent name */ name: string; diff --git a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md index b9cda9dd3f..67437876e1 100644 --- a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md +++ b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md @@ -25,23 +25,6 @@ the version of the Azure Resource Manager common-types to use for refs in emitte | ------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | | version | `valueof string \| EnumMember` | The Azure.ResourceManager.CommonTypes.Versions for the desired common-types version or an equivalent string value like "v5". | -### `@armCustomResource` {#@Azure.ResourceManager.armCustomResource} - -This decorator is used on resources that do not satisfy the definition of a resource -but need to be identified as such. - -```typespec -@Azure.ResourceManager.armCustomResource -``` - -#### Target - -`Model` - -#### Parameters - -None - ### `@armLibraryNamespace` {#@Azure.ResourceManager.armLibraryNamespace} `@armLibraryNamespace` designates a namespace as containign Azure Resource Manager Provider information. @@ -267,6 +250,23 @@ Azure.ResourceManager common types. None +### `@customAzureResource` {#@Azure.ResourceManager.customAzureResource} + +This decorator is used on resources that do not satisfy the definition of a resource +but need to be identified as such. + +```typespec +@Azure.ResourceManager.customAzureResource +``` + +#### Target + +`Model` + +#### Parameters + +None + ### `@extensionResource` {#@Azure.ResourceManager.extensionResource} `@extensionResource` marks an Azure Resource Manager resource model as an Extension resource. diff --git a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/index.mdx b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/index.mdx index b14b42997b..8c2dc70e2f 100644 --- a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/index.mdx +++ b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/index.mdx @@ -35,7 +35,6 @@ npm install --save-peer @azure-tools/typespec-azure-resource-manager ### Decorators - [`@armCommonTypesVersion`](./decorators.md#@Azure.ResourceManager.armCommonTypesVersion) -- [`@armCustomResource`](./decorators.md#@Azure.ResourceManager.armCustomResource) - [`@armLibraryNamespace`](./decorators.md#@Azure.ResourceManager.armLibraryNamespace) - [`@armProviderNamespace`](./decorators.md#@Azure.ResourceManager.armProviderNamespace) - [`@armProviderNameValue`](./decorators.md#@Azure.ResourceManager.armProviderNameValue) @@ -48,6 +47,7 @@ npm install --save-peer @azure-tools/typespec-azure-resource-manager - [`@armResourceRead`](./decorators.md#@Azure.ResourceManager.armResourceRead) - [`@armResourceUpdate`](./decorators.md#@Azure.ResourceManager.armResourceUpdate) - [`@armVirtualResource`](./decorators.md#@Azure.ResourceManager.armVirtualResource) +- [`@customAzureResource`](./decorators.md#@Azure.ResourceManager.customAzureResource) - [`@extensionResource`](./decorators.md#@Azure.ResourceManager.extensionResource) - [`@locationResource`](./decorators.md#@Azure.ResourceManager.locationResource) - [`@resourceBaseType`](./decorators.md#@Azure.ResourceManager.resourceBaseType) From 79cdca08a3a3dee78e23e0c3434bc03ca0b03371 Mon Sep 17 00:00:00 2001 From: Alitzel Mendez Bustillo Date: Mon, 2 Dec 2024 11:12:07 -0800 Subject: [PATCH 4/7] small fixes --- .../generated-defs/Azure.ResourceManager.ts | 2 -- packages/typespec-azure-resource-manager/lib/decorators.tsp | 2 -- packages/typespec-azure-resource-manager/src/resource.ts | 1 - 3 files changed, 5 deletions(-) diff --git a/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts b/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts index 020b345961..3e9bb0ad80 100644 --- a/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts +++ b/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts @@ -252,8 +252,6 @@ export type ArmVirtualResourceDecorator = (context: DecoratorContext, target: Mo /** * This decorator is used on resources that do not satisfy the definition of a resource * but need to be identified as such. - * - * @param propertiesType : Type of the resource properties. */ export type CustomAzureResourceDecorator = (context: DecoratorContext, target: Model) => void; diff --git a/packages/typespec-azure-resource-manager/lib/decorators.tsp b/packages/typespec-azure-resource-manager/lib/decorators.tsp index be0d090d1a..2fe3690bbc 100644 --- a/packages/typespec-azure-resource-manager/lib/decorators.tsp +++ b/packages/typespec-azure-resource-manager/lib/decorators.tsp @@ -185,8 +185,6 @@ extern dec armVirtualResource(target: Model); /** * This decorator is used on resources that do not satisfy the definition of a resource * but need to be identified as such. - * - * @param propertiesType : Type of the resource properties. */ extern dec customAzureResource(target: Model); diff --git a/packages/typespec-azure-resource-manager/src/resource.ts b/packages/typespec-azure-resource-manager/src/resource.ts index a6add95c3b..cc15598885 100644 --- a/packages/typespec-azure-resource-manager/src/resource.ts +++ b/packages/typespec-azure-resource-manager/src/resource.ts @@ -98,7 +98,6 @@ export const $customAzureResource: CustomAzureResourceDecorator = ( context: DecoratorContext, entity: Model, ) => { - //TODO: investigate which rules/constrains will make this a resource and add validation const { program } = context; if (isTemplateDeclaration(entity)) return; if (!isLegacyTypeSpec(program, entity)) { From 40a27bf189422aece53be5d9c1141602daeaa6d4 Mon Sep 17 00:00:00 2001 From: Alitzel Mendez <6895254+AlitzelMendez@users.noreply.github.com> Date: Wed, 4 Dec 2024 16:30:36 -0800 Subject: [PATCH 5/7] Update packages/typespec-azure-resource-manager/src/lib.ts Co-authored-by: Mark Cowlishaw --- packages/typespec-azure-resource-manager/src/lib.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/typespec-azure-resource-manager/src/lib.ts b/packages/typespec-azure-resource-manager/src/lib.ts index c134e5efc0..3cc6429507 100644 --- a/packages/typespec-azure-resource-manager/src/lib.ts +++ b/packages/typespec-azure-resource-manager/src/lib.ts @@ -39,7 +39,7 @@ export const $lib = createTypeSpecLibrary({ "arm-custom-resource-usage-discourage": { severity: "warning", messages: { - default: "Avoid using this decorator as it does not provide validation for ARM resources.", + default: "Avoid using this decorator except when converting old APIs to TypeSpec, as it does not provide validation for ARM resources.", }, }, "arm-resource-missing-name-key-decorator": { From 310159e5f37d91c5cdea43667561d5d73b1871ed Mon Sep 17 00:00:00 2001 From: Alitzel Mendez Bustillo Date: Thu, 5 Dec 2024 10:54:28 -0800 Subject: [PATCH 6/7] feedback: moving decorator to legacy and moving error to linting rule --- .../generated-defs/Azure.ResourceManager.ts | 5 ++- .../lib/Legacy/arm.legacy.tsp | 1 + .../lib/Legacy/decorator.tsp | 9 ++++ .../lib/decorators.tsp | 6 --- .../src/lib.ts | 6 --- .../src/linter.ts | 2 + .../src/resource.ts | 6 +-- .../arm-custom-resource-usage-discourage.ts | 23 +++++++++++ .../src/rules/utils.ts | 8 ---- .../src/tsp-index.ts | 9 +++- .../test/resource.test.ts | 5 +-- ...m-custom-resource-usage-discourage.test.ts | 41 +++++++++++++++++++ .../src/rulesets/resource-manager.ts | 1 + 13 files changed, 90 insertions(+), 32 deletions(-) create mode 100644 packages/typespec-azure-resource-manager/lib/Legacy/decorator.tsp create mode 100644 packages/typespec-azure-resource-manager/src/rules/arm-custom-resource-usage-discourage.ts create mode 100644 packages/typespec-azure-resource-manager/test/rules/arm-custom-resource-usage-discourage.test.ts diff --git a/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts b/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts index 3e9bb0ad80..e956b75325 100644 --- a/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts +++ b/packages/typespec-azure-resource-manager/generated-defs/Azure.ResourceManager.ts @@ -287,6 +287,9 @@ export type AzureResourceManagerDecorators = { armResourceOperations: ArmResourceOperationsDecorator; armCommonTypesVersion: ArmCommonTypesVersionDecorator; armVirtualResource: ArmVirtualResourceDecorator; - customAzureResource: CustomAzureResourceDecorator; resourceBaseType: ResourceBaseTypeDecorator; }; + +export type AzureResourceManagerLegacyDecorators = { + customAzureResource: CustomAzureResourceDecorator; +}; diff --git a/packages/typespec-azure-resource-manager/lib/Legacy/arm.legacy.tsp b/packages/typespec-azure-resource-manager/lib/Legacy/arm.legacy.tsp index 65fe4b9ae1..0d7d1f84ec 100644 --- a/packages/typespec-azure-resource-manager/lib/Legacy/arm.legacy.tsp +++ b/packages/typespec-azure-resource-manager/lib/Legacy/arm.legacy.tsp @@ -1 +1,2 @@ import "./managed-identity.tsp"; +import "./decorator.tsp"; diff --git a/packages/typespec-azure-resource-manager/lib/Legacy/decorator.tsp b/packages/typespec-azure-resource-manager/lib/Legacy/decorator.tsp new file mode 100644 index 0000000000..d00ce1ed28 --- /dev/null +++ b/packages/typespec-azure-resource-manager/lib/Legacy/decorator.tsp @@ -0,0 +1,9 @@ +using TypeSpec.Reflection; + +namespace Azure.ResourceManager.Legacy; + +/** + * This decorator is used on resources that do not satisfy the definition of a resource + * but need to be identified as such. + */ +extern dec customAzureResource(target: Model); diff --git a/packages/typespec-azure-resource-manager/lib/decorators.tsp b/packages/typespec-azure-resource-manager/lib/decorators.tsp index 2fe3690bbc..2b99ea3b1f 100644 --- a/packages/typespec-azure-resource-manager/lib/decorators.tsp +++ b/packages/typespec-azure-resource-manager/lib/decorators.tsp @@ -182,12 +182,6 @@ extern dec armCommonTypesVersion( */ extern dec armVirtualResource(target: Model); -/** - * This decorator is used on resources that do not satisfy the definition of a resource - * but need to be identified as such. - */ -extern dec customAzureResource(target: Model); - /** * This decorator sets the base type of the given resource. * diff --git a/packages/typespec-azure-resource-manager/src/lib.ts b/packages/typespec-azure-resource-manager/src/lib.ts index 3cc6429507..11dd6eca9c 100644 --- a/packages/typespec-azure-resource-manager/src/lib.ts +++ b/packages/typespec-azure-resource-manager/src/lib.ts @@ -36,12 +36,6 @@ export const $lib = createTypeSpecLibrary({ default: "Resource types must include a string property called 'name'.", }, }, - "arm-custom-resource-usage-discourage": { - severity: "warning", - messages: { - default: "Avoid using this decorator except when converting old APIs to TypeSpec, as it does not provide validation for ARM resources.", - }, - }, "arm-resource-missing-name-key-decorator": { severity: "error", messages: { diff --git a/packages/typespec-azure-resource-manager/src/linter.ts b/packages/typespec-azure-resource-manager/src/linter.ts index 09be44f29e..563f47ab9a 100644 --- a/packages/typespec-azure-resource-manager/src/linter.ts +++ b/packages/typespec-azure-resource-manager/src/linter.ts @@ -1,5 +1,6 @@ import { defineLinter } from "@typespec/compiler"; import { armCommonTypesVersionRule } from "./rules/arm-common-types-version.js"; +import { armCustomResourceUsageDiscourage } from "./rules/arm-custom-resource-usage-discourage.js"; import { armDeleteResponseCodesRule } from "./rules/arm-delete-response-codes.js"; import { armNoRecordRule } from "./rules/arm-no-record.js"; import { armPostResponseCodesRule } from "./rules/arm-post-response-codes.js"; @@ -46,6 +47,7 @@ const rules = [ armResourceOperationsRule, armResourcePathInvalidCharsRule, armResourceProvisioningStateRule, + armCustomResourceUsageDiscourage, beyondNestingRule, coreOperationsRule, deleteOperationMissingRule, diff --git a/packages/typespec-azure-resource-manager/src/resource.ts b/packages/typespec-azure-resource-manager/src/resource.ts index cc15598885..ecfc16d292 100644 --- a/packages/typespec-azure-resource-manager/src/resource.ts +++ b/packages/typespec-azure-resource-manager/src/resource.ts @@ -33,7 +33,6 @@ import { reportDiagnostic } from "./lib.js"; import { getArmProviderNamespace, isArmLibraryNamespace } from "./namespace.js"; import { ArmResourceOperations, resolveResourceOperations } from "./operations.js"; import { getArmResource, listArmResources } from "./private.decorators.js"; -import { isLegacyTypeSpec } from "./rules/utils.js"; import { ArmStateKeys } from "./state.js"; export type ArmResourceKind = "Tracked" | "Proxy" | "Extension" | "Virtual" | "Custom"; @@ -100,11 +99,8 @@ export const $customAzureResource: CustomAzureResourceDecorator = ( ) => { const { program } = context; if (isTemplateDeclaration(entity)) return; - if (!isLegacyTypeSpec(program, entity)) { - reportDiagnostic(program, { code: "arm-custom-resource-usage-discourage", target: entity }); - } + program.stateMap(ArmStateKeys.customAzureResource).set(entity, "Custom"); - return; }; function getProperty( diff --git a/packages/typespec-azure-resource-manager/src/rules/arm-custom-resource-usage-discourage.ts b/packages/typespec-azure-resource-manager/src/rules/arm-custom-resource-usage-discourage.ts new file mode 100644 index 0000000000..f4e60dc323 --- /dev/null +++ b/packages/typespec-azure-resource-manager/src/rules/arm-custom-resource-usage-discourage.ts @@ -0,0 +1,23 @@ +import { createRule, Model } from "@typespec/compiler"; +import { isCustomAzureResource } from "../resource.js"; + +export const armCustomResourceUsageDiscourage = createRule({ + name: "arm-custom-resource-usage-discourage", + severity: "warning", + description: "Verify the usage of @customAzureResource decorator.", + messages: { + default: `Avoid using this decorator except when converting old APIs to TypeSpec, as it does not provide validation for ARM resources.`, + }, + create(context) { + return { + model: (model: Model) => { + if (isCustomAzureResource(context.program, model)) { + context.reportDiagnostic({ + code: "arm-custom-resource-usage-discourage", + target: model, + }); + } + }, + }; + }, +}); diff --git a/packages/typespec-azure-resource-manager/src/rules/utils.ts b/packages/typespec-azure-resource-manager/src/rules/utils.ts index f9bc704732..1a933ccf8f 100644 --- a/packages/typespec-azure-resource-manager/src/rules/utils.ts +++ b/packages/typespec-azure-resource-manager/src/rules/utils.ts @@ -93,14 +93,6 @@ export function isInternalTypeSpec( ); } -export function isLegacyTypeSpec( - program: Program, - type: Model | Operation | ModelProperty | Interface | Namespace, -): boolean { - const namespace = getNamespaceName(program, type); - return namespace.includes(".Legacy"); -} - export function isSourceOperationResourceManagerInternal( operation: Operation | undefined, ): boolean { diff --git a/packages/typespec-azure-resource-manager/src/tsp-index.ts b/packages/typespec-azure-resource-manager/src/tsp-index.ts index b722e204cb..2d0a27ea1b 100644 --- a/packages/typespec-azure-resource-manager/src/tsp-index.ts +++ b/packages/typespec-azure-resource-manager/src/tsp-index.ts @@ -1,5 +1,8 @@ import { definePackageFlags } from "@typespec/compiler"; -import { AzureResourceManagerDecorators } from "../generated-defs/Azure.ResourceManager.js"; +import { + AzureResourceManagerDecorators, + AzureResourceManagerLegacyDecorators, +} from "../generated-defs/Azure.ResourceManager.js"; import { $armCommonTypesVersion } from "./common-types.js"; import { $armLibraryNamespace, $armProviderNamespace, $useLibraryNamespace } from "./namespace.js"; import { @@ -49,10 +52,12 @@ export const $decorators = { armResourceList: $armResourceList, armResourceOperations: $armResourceOperations, armCommonTypesVersion: $armCommonTypesVersion, - customAzureResource: $customAzureResource, armVirtualResource: $armVirtualResource, resourceBaseType: $resourceBaseType, } satisfies AzureResourceManagerDecorators, + "Azure.ResourceManager.Legacy": { + customAzureResource: $customAzureResource, + } satisfies AzureResourceManagerLegacyDecorators, }; export const $flags = definePackageFlags({ diff --git a/packages/typespec-azure-resource-manager/test/resource.test.ts b/packages/typespec-azure-resource-manager/test/resource.test.ts index 3a4b2aa598..2577afb9d8 100644 --- a/packages/typespec-azure-resource-manager/test/resource.test.ts +++ b/packages/typespec-azure-resource-manager/test/resource.test.ts @@ -833,8 +833,6 @@ it("emits required properties for resource with @armResourcePropertiesOptionalit strictEqual(resources[0].typespecType.properties.get("properties")?.optional, false); }); -it("resource with customResource identifier", async () => {}); - it("recognizes resource with customResource identifier", async () => { const { diagnostics } = await checkFor(` @armProviderNamespace @@ -876,8 +874,7 @@ it("recognizes resource with customResource identifier", async () => { namespace Microsoft.Person.Contoso { /** Person parent */ - #suppress "@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage" "For test" - @customAzureResource + @Azure.ResourceManager.Legacy.customAzureResource model Person { /** The parent name */ name: string; diff --git a/packages/typespec-azure-resource-manager/test/rules/arm-custom-resource-usage-discourage.test.ts b/packages/typespec-azure-resource-manager/test/rules/arm-custom-resource-usage-discourage.test.ts new file mode 100644 index 0000000000..d47239d807 --- /dev/null +++ b/packages/typespec-azure-resource-manager/test/rules/arm-custom-resource-usage-discourage.test.ts @@ -0,0 +1,41 @@ +import { + BasicTestRunner, + LinterRuleTester, + createLinterRuleTester, +} from "@typespec/compiler/testing"; +import { beforeEach, it } from "vitest"; +import { armCustomResourceUsageDiscourage } from "../../src/rules/arm-custom-resource-usage-discourage.js"; +import { createAzureResourceManagerTestRunner } from "../test-host.js"; + +let runner: BasicTestRunner; +let tester: LinterRuleTester; + +beforeEach(async () => { + runner = await createAzureResourceManagerTestRunner(); + tester = createLinterRuleTester( + runner, + armCustomResourceUsageDiscourage, + "@azure-tools/typespec-azure-resource-manager", + ); +}); + +it("emits diagnostic when using @Azure.ResourceManager.Legacy.customAzureResource decorator", async () => { + await tester + .expect( + ` + @armProviderNamespace + @useDependency(Azure.ResourceManager.Versions.v1_0_Preview_1) + namespace Microsoft.Contoso; + + @Azure.ResourceManager.Legacy.customAzureResource + model Person { + name: string; + } + `, + ) + .toEmitDiagnostics({ + code: "@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage", + message: + "Avoid using this decorator except when converting old APIs to TypeSpec, as it does not provide validation for ARM resources.", + }); +}); diff --git a/packages/typespec-azure-rulesets/src/rulesets/resource-manager.ts b/packages/typespec-azure-rulesets/src/rulesets/resource-manager.ts index d3397a884e..a6da8a8bea 100644 --- a/packages/typespec-azure-rulesets/src/rulesets/resource-manager.ts +++ b/packages/typespec-azure-rulesets/src/rulesets/resource-manager.ts @@ -65,6 +65,7 @@ export default { "@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-version-format": true, "@azure-tools/typespec-azure-resource-manager/arm-resource-key-invalid-chars": true, "@azure-tools/typespec-azure-resource-manager/arm-resource-name-pattern": true, + "@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage": true, "@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response": true, "@azure-tools/typespec-azure-resource-manager/arm-resource-path-segment-invalid-chars": true, "@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state": true, From 962f0674cf7d23ffa533291eaaa496324d9b14a8 Mon Sep 17 00:00:00 2001 From: Alitzel Mendez Bustillo Date: Thu, 5 Dec 2024 11:01:37 -0800 Subject: [PATCH 7/7] Summary of changes + documentation --- ...stom-azure-resource-2024-10-27-15-43-13.md | 2 +- ...custom-azure-resource-2024-11-5-11-0-40.md | 7 ++++ .../typespec-azure-resource-manager/README.md | 40 ++++++++++--------- .../reference/decorators.md | 36 +++++++++-------- .../reference/index.mdx | 5 ++- .../reference/linter.md | 1 + 6 files changed, 54 insertions(+), 37 deletions(-) create mode 100644 .chronus/changes/new-decorator-custom-azure-resource-2024-11-5-11-0-40.md diff --git a/.chronus/changes/new-decorator-custom-azure-resource-2024-10-27-15-43-13.md b/.chronus/changes/new-decorator-custom-azure-resource-2024-10-27-15-43-13.md index 74ca033898..7c9994d549 100644 --- a/.chronus/changes/new-decorator-custom-azure-resource-2024-10-27-15-43-13.md +++ b/.chronus/changes/new-decorator-custom-azure-resource-2024-10-27-15-43-13.md @@ -4,4 +4,4 @@ packages: - "@azure-tools/typespec-azure-resource-manager" --- -Add the `@armCustomResources` decorator to identify ARM resources that do not use the base resource types. +Add the `@Azure.ResourceManager.Legacy.customAzureResource` decorator to identify ARM resources that do not use the base resource types. diff --git a/.chronus/changes/new-decorator-custom-azure-resource-2024-11-5-11-0-40.md b/.chronus/changes/new-decorator-custom-azure-resource-2024-11-5-11-0-40.md new file mode 100644 index 0000000000..cbb09e4ddb --- /dev/null +++ b/.chronus/changes/new-decorator-custom-azure-resource-2024-11-5-11-0-40.md @@ -0,0 +1,7 @@ +--- +changeKind: feature +packages: + - "@azure-tools/typespec-azure-rulesets" +--- + +Discourage usage of new decorator `@Azure.ResourceManager.Legacy.customAzureResource` diff --git a/packages/typespec-azure-resource-manager/README.md b/packages/typespec-azure-resource-manager/README.md index 3a49ad67c6..83f2165fc5 100644 --- a/packages/typespec-azure-resource-manager/README.md +++ b/packages/typespec-azure-resource-manager/README.md @@ -42,6 +42,7 @@ Available ruleSets: | `@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response` | [RPC 008]: PUT, GET, PATCH & LIST must return the same resource schema. | | `@azure-tools/typespec-azure-resource-manager/arm-resource-path-segment-invalid-chars` | Arm resource name must contain only alphanumeric characters. | | `@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state` | Check for properly configured provisioningState property. | +| `@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage` | Verify the usage of @customAzureResource decorator. | | `@azure-tools/typespec-azure-resource-manager/beyond-nesting-levels` | Tracked Resources must use 3 or fewer levels of nesting. | | `@azure-tools/typespec-azure-resource-manager/arm-resource-operation` | Validate ARM Resource operations. | | `@azure-tools/typespec-azure-resource-manager/no-resource-delete-operation` | Check for resources that must have a delete operation. | @@ -77,7 +78,6 @@ Available ruleSets: - [`@armResourceRead`](#@armresourceread) - [`@armResourceUpdate`](#@armresourceupdate) - [`@armVirtualResource`](#@armvirtualresource) -- [`@customAzureResource`](#@customazureresource) - [`@extensionResource`](#@extensionresource) - [`@locationResource`](#@locationresource) - [`@resourceBaseType`](#@resourcebasetype) @@ -331,23 +331,6 @@ Azure.ResourceManager common types. None -#### `@customAzureResource` - -This decorator is used on resources that do not satisfy the definition of a resource -but need to be identified as such. - -```typespec -@Azure.ResourceManager.customAzureResource -``` - -##### Target - -`Model` - -##### Parameters - -None - #### `@extensionResource` `@extensionResource` marks an Azure Resource Manager resource model as an Extension resource. @@ -514,3 +497,24 @@ This allows sharing Azure Resource Manager resource types across specifications | Name | Type | Description | | ---------- | ------------- | ------------------------------------------------------------------------ | | namespaces | `Namespace[]` | The namespaces of Azure Resource Manager libraries used in this provider | + +### Azure.ResourceManager.Legacy + +- [`@customAzureResource`](#@customazureresource) + +#### `@customAzureResource` + +This decorator is used on resources that do not satisfy the definition of a resource +but need to be identified as such. + +```typespec +@Azure.ResourceManager.Legacy.customAzureResource +``` + +##### Target + +`Model` + +##### Parameters + +None diff --git a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md index 67437876e1..9b2cc18146 100644 --- a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md +++ b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/decorators.md @@ -250,23 +250,6 @@ Azure.ResourceManager common types. None -### `@customAzureResource` {#@Azure.ResourceManager.customAzureResource} - -This decorator is used on resources that do not satisfy the definition of a resource -but need to be identified as such. - -```typespec -@Azure.ResourceManager.customAzureResource -``` - -#### Target - -`Model` - -#### Parameters - -None - ### `@extensionResource` {#@Azure.ResourceManager.extensionResource} `@extensionResource` marks an Azure Resource Manager resource model as an Extension resource. @@ -433,3 +416,22 @@ This allows sharing Azure Resource Manager resource types across specifications | Name | Type | Description | | ---------- | ------------- | ------------------------------------------------------------------------ | | namespaces | `Namespace[]` | The namespaces of Azure Resource Manager libraries used in this provider | + +## Azure.ResourceManager.Legacy + +### `@customAzureResource` {#@Azure.ResourceManager.Legacy.customAzureResource} + +This decorator is used on resources that do not satisfy the definition of a resource +but need to be identified as such. + +```typespec +@Azure.ResourceManager.Legacy.customAzureResource +``` + +#### Target + +`Model` + +#### Parameters + +None diff --git a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/index.mdx b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/index.mdx index 8c2dc70e2f..88fbc6bd48 100644 --- a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/index.mdx +++ b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/index.mdx @@ -47,7 +47,6 @@ npm install --save-peer @azure-tools/typespec-azure-resource-manager - [`@armResourceRead`](./decorators.md#@Azure.ResourceManager.armResourceRead) - [`@armResourceUpdate`](./decorators.md#@Azure.ResourceManager.armResourceUpdate) - [`@armVirtualResource`](./decorators.md#@Azure.ResourceManager.armVirtualResource) -- [`@customAzureResource`](./decorators.md#@Azure.ResourceManager.customAzureResource) - [`@extensionResource`](./decorators.md#@Azure.ResourceManager.extensionResource) - [`@locationResource`](./decorators.md#@Azure.ResourceManager.locationResource) - [`@resourceBaseType`](./decorators.md#@Azure.ResourceManager.resourceBaseType) @@ -267,6 +266,10 @@ npm install --save-peer @azure-tools/typespec-azure-resource-manager ## Azure.ResourceManager.Legacy +### Decorators + +- [`@customAzureResource`](./decorators.md#@Azure.ResourceManager.Legacy.customAzureResource) + ### Models - [`ManagedServiceIdentityV4`](./data-types.md#Azure.ResourceManager.Legacy.ManagedServiceIdentityV4) diff --git a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/linter.md b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/linter.md index b5ea735027..2c0f2012ef 100644 --- a/website/src/content/docs/docs/libraries/azure-resource-manager/reference/linter.md +++ b/website/src/content/docs/docs/libraries/azure-resource-manager/reference/linter.md @@ -36,6 +36,7 @@ Available ruleSets: | `@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response` | [RPC 008]: PUT, GET, PATCH & LIST must return the same resource schema. | | `@azure-tools/typespec-azure-resource-manager/arm-resource-path-segment-invalid-chars` | Arm resource name must contain only alphanumeric characters. | | `@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state` | Check for properly configured provisioningState property. | +| `@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage` | Verify the usage of @customAzureResource decorator. | | `@azure-tools/typespec-azure-resource-manager/beyond-nesting-levels` | Tracked Resources must use 3 or fewer levels of nesting. | | `@azure-tools/typespec-azure-resource-manager/arm-resource-operation` | Validate ARM Resource operations. | | `@azure-tools/typespec-azure-resource-manager/no-resource-delete-operation` | Check for resources that must have a delete operation. |