UNPKG

@azure-tools/typespec-azure-resource-manager

Version:

TypeSpec Azure Resource Manager library

109 lines 5.61 kB
import { createRule, getProperty, paramMessage } from "@typespec/compiler"; import { getUnionAsEnum } from "@azure-tools/typespec-azure-core"; import { getArmResource } from "../resource.js"; import { isReadonlyProperty } from "../utils.js"; import { getSourceProperty } from "./utils.js"; export const armResourceProvisioningStateRule = createRule({ name: "arm-resource-provisioning-state", severity: "warning", description: "Check for properly configured provisioningState property.", messages: { default: "The RP-specific property model in the 'properties' property of this resource must contain a 'provisioningState property. The property type should be an enum or a union of string values, and it must specify known state values 'Succeeded', 'Failed', and 'Canceled'.", missingValues: paramMessage `provisioningState, must reference an enum with 'Succeeded', 'Failed', 'Canceled' values. The enum is missing the values: [${"missingValues"}].`, missingReadOnlyVisibility: "The provisioningState property must have a single read visibility.", mustBeOptional: "The provisioningState property must be optional.", }, create(context) { return { model: (model) => { const resourceModel = getArmResource(context.program, model); if (resourceModel === undefined) { return; } const resourceProperties = getProperty(model, "properties")?.type; if (resourceProperties === undefined || resourceProperties.kind !== "Model") { return; } let provisioning = getProperty(resourceProperties, "provisioningState"); if (provisioning === undefined) { context.reportDiagnostic({ target: resourceProperties, }); } else { provisioning = getSourceProperty(provisioning); const provisioningType = provisioning.type; switch (provisioningType.kind) { case "Enum": { const enumType = provisioningType; const missing = []; if (!enumType.members.get("Succeeded")) { missing.push("Succeeded"); } if (!enumType.members.get("Canceled")) { missing.push("Canceled"); } if (!enumType.members.get("Failed")) { missing.push("Failed"); } if (missing.length > 0) { context.reportDiagnostic({ messageId: "missingValues", format: { missingValues: missing.join(", ") }, target: enumType, }); } break; } case "Union": { const [unionAsEnum] = getUnionAsEnum(provisioningType); if (unionAsEnum === undefined) { context.reportDiagnostic({ target: resourceProperties, }); break; } const missing = []; if (!unionAsEnum.flattenedMembers.get("Succeeded")) { missing.push("Succeeded"); } if (!unionAsEnum.flattenedMembers.get("Canceled")) { missing.push("Canceled"); } if (!unionAsEnum.flattenedMembers.get("Failed")) { missing.push("Failed"); } if (missing.length > 0) { context.reportDiagnostic({ messageId: "missingValues", format: { missingValues: missing.join(", ") }, target: provisioningType, }); } break; } default: context.reportDiagnostic({ target: provisioning, }); } // validate provisioning state is optional if (provisioning.optional !== true) { context.reportDiagnostic({ messageId: "mustBeOptional", target: provisioning, }); } // validate it must has a read only visibility if (!isReadonlyProperty(context.program, provisioning)) { context.reportDiagnostic({ messageId: "missingReadOnlyVisibility", target: provisioning, }); } } }, }; }, }); //# sourceMappingURL=arm-resource-provisioning-state-rule.js.map