This sample shows the recommended TypeSpec (and generated Swagger) for an OperationStatus response: playground
This swagger causes the following errors:
error | RequiredPropertiesMissingInResourceModel | Model definition 'OperationStatus' must have the properties 'name', 'id' and 'type' in its hierarchy and these properties must be marked as readonly.
- file:///home/mharder/specs-mh/specification/widget/resource-manager/Microsoft.Widget/Widget/stable/2021-11-01/widget.json:154:5
error | BodyTopLevelProperties | Top level properties should be one of name, type, id, location, properties, tags, plan, sku, etag, managedBy, identity, zones. Model definition 'OperationStatus' has extra properties ['status'].
- file:///home/mharder/specs-mh/specification/widget/resource-manager/Microsoft.Widget/Widget/stable/2021-11-01/widget.json:154:5
error | BodyTopLevelProperties | Top level properties should be one of name, type, id, location, properties, tags, plan, sku, etag, managedBy, identity, zones. Model definition 'OperationStatus' has extra properties ['startTime'].
- file:///home/mharder/specs-mh/specification/widget/resource-manager/Microsoft.Widget/Widget/stable/2021-11-01/widget.json:154:5
error | BodyTopLevelProperties | Top level properties should be one of name, type, id, location, properties, tags, plan, sku, etag, managedBy, identity, zones. Model definition 'OperationStatus' has extra properties ['endTime'].
- file:///home/mharder/specs-mh/specification/widget/resource-manager/Microsoft.Widget/Widget/stable/2021-11-01/widget.json:154:5
error | BodyTopLevelProperties | Top level properties should be one of name, type, id, location, properties, tags, plan, sku, etag, managedBy, identity, zones. Model definition 'OperationStatus' has extra properties ['percentComplete'].
- file:///home/mharder/specs-mh/specification/widget/resource-manager/Microsoft.Widget/Widget/stable/2021-11-01/widget.json:154:5
error | BodyTopLevelProperties | Top level properties should be one of name, type, id, location, properties, tags, plan, sku, etag, managedBy, identity, zones. Model definition 'OperationStatus' has extra properties ['error'].
- file:///home/mharder/specs-mh/specification/widget/resource-manager/Microsoft.Widget/Widget/stable/2021-11-01/widget.json:154:5
We believe this swagger should cause no errors. The rules RequiredPropertiesMissingInResourceModel and BodyTopLevelProperties should be updated to allow (or require?) the schema in this sample.
Example existing spec, that fails with these errors (they were ignored when the PR was merged to main):
https://github.com/Azure/azure-rest-api-specs/blob/fda1bb1d4593ae819edd699446d0941d1e8f1174/specification/chaos/resource-manager/Microsoft.Chaos/Chaos/stable/2024-01-01/operationStatuses.json#L37-L83
Examples (from playground)
TypeSpec
import "@typespec/http";
import "@typespec/rest";
import "@typespec/versioning";
import "@azure-tools/typespec-azure-core";
import "@azure-tools/typespec-azure-resource-manager";
using Http;
using Rest;
using Versioning;
using Azure.Core;
using Azure.ResourceManager;
/** Contoso Resource Provider management API. */
@armProviderNamespace
@service(#{ title: "ContosoProviderHubClient" })
@versioned(Versions)
namespace Microsoft.ContosoProviderHub;
/** Contoso API versions */
enum Versions {
/** 2021-10-01-preview version */
@armCommonTypesVersion(Azure.ResourceManager.CommonTypes.Versions.v5)
`2021-10-01-preview`,
}
/** A ContosoProviderHub resource */
@parentResource(SubscriptionLocationResource)
model OperationStatus {
/** The operation status */
@Azure.Core.lroStatus
status: Azure.ResourceManager.ResourceProvisioningState;
/** The unique identifier for the operationStatus resource */
@visibility(Lifecycle.Read)
id: string;
/** The name of the operationStatus resource */
@visibility(Lifecycle.Read)
@key
@path
@segment("operationStatuses")
name: string;
/** Operation start time */
@visibility(Lifecycle.Read)
startTime?: utcDateTime;
/** Operation complete time */
@visibility(Lifecycle.Read)
endTime?: utcDateTime;
/** The progress made toward completing the operation */
@visibility(Lifecycle.Read)
percentComplete?: float64;
/** rp-specific properties */
properties?: OperationStatusProperties;
/** Errors that occurred if the operation ended with Canceled or Failed status */
@visibility(Lifecycle.Read)
error?: Azure.ResourceManager.Foundations.ErrorDetail;
}
/** Employee properties */
model OperationStatusProperties {
/** Age of employee */
age?: int32;
/** City of employee */
city?: string;
/** Profile of employee */
@encode("base64url")
profile?: bytes;
}
interface Operations extends Azure.ResourceManager.Operations {}
@armResourceOperations
interface Employees {
get is ArmResourceRead<OperationStatus>;
}
Swagger
{
"swagger": "2.0",
"info": {
"title": "ContosoProviderHubClient",
"version": "2021-10-01-preview",
"description": "Contoso Resource Provider management API.",
"x-typespec-generated": [
{
"emitter": "@azure-tools/typespec-autorest"
}
]
},
"schemes": [
"https"
],
"host": "management.azure.com",
"produces": [
"application/json"
],
"consumes": [
"application/json"
],
"security": [
{
"azure_auth": [
"user_impersonation"
]
}
],
"securityDefinitions": {
"azure_auth": {
"type": "oauth2",
"description": "Azure Active Directory OAuth2 Flow.",
"flow": "implicit",
"authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize",
"scopes": {
"user_impersonation": "impersonate your user account"
}
}
},
"tags": [
{
"name": "Operations"
},
{
"name": "Employees"
}
],
"paths": {
"/providers/Microsoft.ContosoProviderHub/operations": {
"get": {
"operationId": "Operations_List",
"tags": [
"Operations"
],
"description": "List the operations for the provider",
"parameters": [
{
"$ref": "../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter"
}
],
"responses": {
"200": {
"description": "Azure operation completed successfully.",
"schema": {
"$ref": "../../../common-types/resource-management/v5/types.json#/definitions/OperationListResult"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse"
}
}
},
"x-ms-pageable": {
"nextLinkName": "nextLink"
}
}
},
"/subscriptions/{subscriptionId}/providers/Microsoft.ContosoProviderHub/locations/{location}/operationStatuses/{name}": {
"get": {
"operationId": "Employees_Get",
"tags": [
"Employees"
],
"description": "Get a OperationStatus",
"parameters": [
{
"$ref": "../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter"
},
{
"$ref": "../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter"
},
{
"$ref": "../../../common-types/resource-management/v5/types.json#/parameters/LocationParameter"
},
{
"name": "name",
"in": "path",
"description": "The name of the operationStatus resource",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "Azure operation completed successfully.",
"schema": {
"$ref": "#/definitions/OperationStatus"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse"
}
}
}
}
}
},
"definitions": {
"Azure.ResourceManager.ResourceProvisioningState": {
"type": "string",
"description": "The provisioning state of a resource type.",
"enum": [
"Succeeded",
"Failed",
"Canceled"
],
"x-ms-enum": {
"name": "ResourceProvisioningState",
"modelAsString": true,
"values": [
{
"name": "Succeeded",
"value": "Succeeded",
"description": "Resource has been created."
},
{
"name": "Failed",
"value": "Failed",
"description": "Resource creation failed."
},
{
"name": "Canceled",
"value": "Canceled",
"description": "Resource creation was canceled."
}
]
}
},
"OperationStatus": {
"type": "object",
"description": "A ContosoProviderHub resource",
"properties": {
"status": {
"$ref": "#/definitions/Azure.ResourceManager.ResourceProvisioningState",
"description": "The operation status"
},
"id": {
"type": "string",
"description": "The unique identifier for the operationStatus resource",
"readOnly": true
},
"name": {
"type": "string",
"description": "The name of the operationStatus resource",
"readOnly": true
},
"startTime": {
"type": "string",
"format": "date-time",
"description": "Operation start time",
"readOnly": true
},
"endTime": {
"type": "string",
"format": "date-time",
"description": "Operation complete time",
"readOnly": true
},
"percentComplete": {
"type": "number",
"format": "double",
"description": "The progress made toward completing the operation",
"readOnly": true
},
"properties": {
"$ref": "#/definitions/OperationStatusProperties",
"description": "rp-specific properties"
},
"error": {
"$ref": "../../../common-types/resource-management/v5/types.json#/definitions/ErrorDetail",
"description": "Errors that occurred if the operation ended with Canceled or Failed status",
"readOnly": true
}
},
"required": [
"status",
"id",
"name"
]
},
"OperationStatusProperties": {
"type": "object",
"description": "Employee properties",
"properties": {
"age": {
"type": "integer",
"format": "int32",
"description": "Age of employee"
},
"city": {
"type": "string",
"description": "City of employee"
},
"profile": {
"type": "string",
"format": "base64url",
"description": "Profile of employee"
}
}
}
},
"parameters": {}
}
This sample shows the recommended TypeSpec (and generated Swagger) for an
OperationStatusresponse: playgroundThis swagger causes the following errors:
We believe this swagger should cause no errors. The rules
RequiredPropertiesMissingInResourceModelandBodyTopLevelPropertiesshould be updated to allow (or require?) the schema in this sample.Example existing spec, that fails with these errors (they were ignored when the PR was merged to main):
https://github.com/Azure/azure-rest-api-specs/blob/fda1bb1d4593ae819edd699446d0941d1e8f1174/specification/chaos/resource-manager/Microsoft.Chaos/Chaos/stable/2024-01-01/operationStatuses.json#L37-L83
Examples (from playground)
TypeSpec
Swagger
{ "swagger": "2.0", "info": { "title": "ContosoProviderHubClient", "version": "2021-10-01-preview", "description": "Contoso Resource Provider management API.", "x-typespec-generated": [ { "emitter": "@azure-tools/typespec-autorest" } ] }, "schemes": [ "https" ], "host": "management.azure.com", "produces": [ "application/json" ], "consumes": [ "application/json" ], "security": [ { "azure_auth": [ "user_impersonation" ] } ], "securityDefinitions": { "azure_auth": { "type": "oauth2", "description": "Azure Active Directory OAuth2 Flow.", "flow": "implicit", "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", "scopes": { "user_impersonation": "impersonate your user account" } } }, "tags": [ { "name": "Operations" }, { "name": "Employees" } ], "paths": { "/providers/Microsoft.ContosoProviderHub/operations": { "get": { "operationId": "Operations_List", "tags": [ "Operations" ], "description": "List the operations for the provider", "parameters": [ { "$ref": "../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" } ], "responses": { "200": { "description": "Azure operation completed successfully.", "schema": { "$ref": "../../../common-types/resource-management/v5/types.json#/definitions/OperationListResult" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" } } }, "x-ms-pageable": { "nextLinkName": "nextLink" } } }, "/subscriptions/{subscriptionId}/providers/Microsoft.ContosoProviderHub/locations/{location}/operationStatuses/{name}": { "get": { "operationId": "Employees_Get", "tags": [ "Employees" ], "description": "Get a OperationStatus", "parameters": [ { "$ref": "../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" }, { "$ref": "../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" }, { "$ref": "../../../common-types/resource-management/v5/types.json#/parameters/LocationParameter" }, { "name": "name", "in": "path", "description": "The name of the operationStatus resource", "required": true, "type": "string" } ], "responses": { "200": { "description": "Azure operation completed successfully.", "schema": { "$ref": "#/definitions/OperationStatus" } }, "default": { "description": "An unexpected error response.", "schema": { "$ref": "../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" } } } } } }, "definitions": { "Azure.ResourceManager.ResourceProvisioningState": { "type": "string", "description": "The provisioning state of a resource type.", "enum": [ "Succeeded", "Failed", "Canceled" ], "x-ms-enum": { "name": "ResourceProvisioningState", "modelAsString": true, "values": [ { "name": "Succeeded", "value": "Succeeded", "description": "Resource has been created." }, { "name": "Failed", "value": "Failed", "description": "Resource creation failed." }, { "name": "Canceled", "value": "Canceled", "description": "Resource creation was canceled." } ] } }, "OperationStatus": { "type": "object", "description": "A ContosoProviderHub resource", "properties": { "status": { "$ref": "#/definitions/Azure.ResourceManager.ResourceProvisioningState", "description": "The operation status" }, "id": { "type": "string", "description": "The unique identifier for the operationStatus resource", "readOnly": true }, "name": { "type": "string", "description": "The name of the operationStatus resource", "readOnly": true }, "startTime": { "type": "string", "format": "date-time", "description": "Operation start time", "readOnly": true }, "endTime": { "type": "string", "format": "date-time", "description": "Operation complete time", "readOnly": true }, "percentComplete": { "type": "number", "format": "double", "description": "The progress made toward completing the operation", "readOnly": true }, "properties": { "$ref": "#/definitions/OperationStatusProperties", "description": "rp-specific properties" }, "error": { "$ref": "../../../common-types/resource-management/v5/types.json#/definitions/ErrorDetail", "description": "Errors that occurred if the operation ended with Canceled or Failed status", "readOnly": true } }, "required": [ "status", "id", "name" ] }, "OperationStatusProperties": { "type": "object", "description": "Employee properties", "properties": { "age": { "type": "integer", "format": "int32", "description": "Age of employee" }, "city": { "type": "string", "description": "City of employee" }, "profile": { "type": "string", "format": "base64url", "description": "Profile of employee" } } } }, "parameters": {} }