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
@@ -0,0 +1,8 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: fix
packages:
- "@azure-tools/typespec-azure-resource-manager"
---

Fix issues in `resolveArmResources` when we have singleton resource with a customized name
2 changes: 1 addition & 1 deletion core
Submodule core updated 216 files
31 changes: 26 additions & 5 deletions packages/typespec-azure-resource-manager/src/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ interface ResolvedResourceOperations {
parent?: ResolvedResource;
/** The scope of this resource */
scope?: string;
/** For singleton resources, the names that can be used to reference the resource */
singletonResourceNames?: string[];
}
/** Resolved operations, including operations for non-arm resources */
export interface ResolvedResource {
Expand All @@ -190,6 +192,8 @@ export interface ResolvedResource {
parent?: ResolvedResource;
/** The scope of this resource */
scope?: string | ResolvedResource;
/** For singleton resources, the names that can be used to reference the resource */
singletonResourceNames?: string[];
}

/** Description of the resource type */
Expand Down Expand Up @@ -621,15 +625,20 @@ function getResourceScope(
return undefined;
}

function isVariableSegment(segment: string): boolean {
return (segment.startsWith("{") && segment.endsWith("}")) || segment === "default";
function isVariableSegment(segment: string, singletonResourceName?: string): boolean {
Copy link
Member

Choose a reason for hiding this comment

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

I think we want to do a lowercase transform over both the segment and the name

Copy link
Member

Choose a reason for hiding this comment

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

Also, I think we could do this over an array of singleton resource names, but this isn't required for this PR, we cna add it when we add singleton recognition for union and enum resource name types

Copy link
Member

Choose a reason for hiding this comment

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

I think we should also continue to use 'default' as a singleton resource name, in addition to the singleton resource name from getSingletonKey

return (segment.startsWith("{") && segment.endsWith("}")) || segment === singletonResourceName;
}

function getResourceInfo(
program: Program,
operation: ArmResourceOperation,
singletonResourceName: string | undefined,
): ResolvedResourceInfo | undefined {
const pathInfo = getResourcePathElements(operation.httpOperation.path, operation.kind);
const pathInfo = getResourcePathElements(
operation.httpOperation.path,
operation.kind,
singletonResourceName,
);
if (pathInfo === undefined) return undefined;
return {
...pathInfo,
Expand All @@ -640,6 +649,7 @@ function getResourceInfo(
export function getResourcePathElements(
path: string,
kind: ArmOperationKind,
singletonResourceName?: string,
): ResourcePathInfo | undefined {
const segments = path.split("/").filter((s) => s.length > 0);
const providerIndex = segments.findLastIndex((s) => s === "providers");
Expand All @@ -652,7 +662,15 @@ export function getResourcePathElements(
break;
}

if (i + 1 < segments.length && isVariableSegment(segments[i + 1])) {
// if the next segment is the last segment
if (
Copy link
Member

Choose a reason for hiding this comment

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

I think if we change this logic, we will fix the issues below - it makes sense that the singleton resource name should just always be checked when looking for a variable segment.

I think there is still a case to think about, when multiple resources in the resource type are singletons

i + 1 === segments.length - 1 &&
isVariableSegment(segments[i + 1], singletonResourceName)
) {
typeSegments.push(segments[i]);
instanceSegments.push(segments[i]);
instanceSegments.push(segments[i + 1]);
} else if (i + 1 < segments.length && isVariableSegment(segments[i + 1])) {
typeSegments.push(segments[i]);
instanceSegments.push(segments[i]);
instanceSegments.push(segments[i + 1]);
Expand Down Expand Up @@ -862,9 +880,10 @@ export function resolveArmResourceOperations(

if (armOperation === undefined) continue;
armOperation.kind = operation.kind;
const singletonResourceName = getSingletonResourceKey(program, resourceType);

armOperation.resourceModelName = operation.resource?.name ?? resourceType.name;
const resourceInfo = getResourceInfo(program, armOperation);
const resourceInfo = getResourceInfo(program, armOperation, singletonResourceName);
if (resourceInfo === undefined) continue;
armOperation.name = operation.name;
armOperation.resourceKind = operation.resourceKind;
Expand Down Expand Up @@ -893,6 +912,8 @@ export function resolveArmResourceOperations(
resourceType: resourceInfo.resourceType,
resourceInstancePath: resourceInfo.resourceInstancePath,
resourceName: resourceInfo.resourceName,
singletonResourceNames:
singletonResourceName !== undefined ? [singletonResourceName] : undefined,
operations: {
lifecycle: {
read: undefined,
Expand Down
Loading