Nauseating Pumpkin Mush

    @azure-tools/cadl-azure-resource-manager
    TypeScript icon, indicating that this package has built-in type declarations

    0.10.0 • Public • Published

    Cadl Azure Resource Manager Library

    This is a library that provides model types and interfaces which can be used to define an Azure Resource Manager service API.

    Table of Contents

    Getting Started

    To author an Azure Resource Manager service definition, you will first need to create a Cadl project for your service. The easiest way to do that is to follow the instructions on this page:

    https://github.com/Azure/cadl-azure/blob/main/packages/cadl-providerhub-templates/README.md#getting-started

    Concepts

    Before using this library, you should familiarize yourself with the Cadl language and tools. You can do this by reading the Cadl tutorial.

    Defining the Service

    To define an Azure Resource Manager service, the first thing you will need to do is define the service namespace and decorate it with the serviceTitle, serviceVersion and armProviderNamespace decorators:

    @armProviderNamespace
    @serviceTitle("<service name>")
    @serviceVersion("<service version>")
    namespace <mynamespace>;
    

    For example:

    @armProviderNamespace
    @serviceTitle("Contoso User Service")
    @serviceVersion("2020-10-01-preview")
    namespace Contoso.Users;
    

    The using keyword

    Just after the namespace declaration, you will also need to include a few using statements to pull in symbols from the namespaces of libraries you will for your specification.

    For example, these lines pull in symbols from the @cadl-lang/rest and @azure-tools/cadl-azure-resource-manager:

    using Cadl.Http;
    using Cadl.Rest;
    using Azure.ResourceManager;
    

    Defining Resource Types

    A resource provider is composed of resources. The Cadl Azure Resource Manager library makes it much easier to define the structure and endpoints of such resources.

    There are three essential components of a resource defined with Cadl:

    Read the Cadl tutorial to learn the basics about Cadl model types and interfaces.

    1. Define a model representing the properties of the ARM resource

    Each resource type must have a properties type which defines its custom properties. This type will be exposed as the properties property of the resource type.

    @doc("The properties of UserResource")
    model UserResourceProperties {
      @doc("The user's full name")
      fullName: string;
    
      @doc("The user's email address.")
      emailAddress: string;
    }
    

    2. Define a model representing the resource type

    Resource types are defined as plain models which pull in a standard resource type using the is keyword.

    You define a resource type, you need the following:

    • A name property which is marked with the following decorators
      • @key: Specifies the parameter name for this resource type in the service URI hierarchy
      • @segment: Specifies the name of the resource "collection", the URI segment that comes just before the parameter name which identifies the resource type
    • A second model type which defines the resource type's custom properties as we described in step 1

    Here we define a tracked resource called UserResource:

    @doc("A UserResource")
    model UserResource is TrackedResource<UserResourceProperties> {
      @key("userName")
      @segment("users")
      name: string;
    }
    

    3. Define an interface with operations for the resource type

    @armResourceOperations
    interface Users extends ResourceOperations<UserResource> {}
    

    This will now produce all the endpoints(get, post, put, patch and delete, listByResourceGroup, listBySubscription) for a resource called UserResources and the operations endpoint for the service:

    Method & Path Description
    GET /providers/Contoso.Users/operations List all operations for your service
    GET /subscriptions/{subscriptionId}/providers/Contoso.Users/users list all UserResource by subscription
    GET /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Contoso.Users/users list all UserResource by resource group
    GET /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Contoso.Users/users/{userName} get item
    PUT /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Contoso.Users/users/{userName} insert item
    PATCH /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Contoso.Users/users/{userName} patch item
    DELETE /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Contoso.Users/users/{userName} delete item

    Base Resource Types

    Here are the base resource types you can use when defining your own ARM resources:

    Name Description
    TrackedResource Defines a normal ARM resource where TProperties is the model of the properties
    ProxyResource Defines a proxy ARM resource where TProperties is the model of the properties
    ExtensionResource Defines an extension ARM resource where TProperties is the model of the properties

    Defining Child Resource Types

    You can create parent/child relationships between resource types by using the @parentResource decorator when defining a resource type.

    For example, here's how you could create a new AddressResource resource under the UserResource defined above:

    @doc("An address resource belonging to a user resource.")
    @parentResource(UserResource)
    model AddressResource is ProxyResource<AddressResourceProperties> {
      @key("addressName")
      @segment("addresses")
      name: string;
    }
    
    @doc("The properties of AddressResource")
    model AddressResourceProperties {
      @doc("The street address.")
      streetAddress: string;
    
      @doc("The city of the address.")
      city: string;
    
      @doc("The state of the address.")
      state: string;
    
      @doc("The zip code of the address.")
      zip: int32;
    }
    
    @armResourceOperations
    interface Addresses extends ProxyResourceOperations<AddressResource> {}
    

    Defining Custom Actions

    Some resources will provide more than the standard CRUD operations and will need to define a custom action endpoint. Additional resource operations can be added to the interface where you pulled in standard resource operations.

    For example, to add an additional POST action called /notify to the standard operations of UserResource:

    @doc("The details of a user notification.")
    model NotificationDetails {
      @doc("The notification message.")
      message: string;
    
      @doc("If true, the notification is urgent.")
      urgent: boolean;
    }
    
    @armResourceOperations
    interface Users mixes ResourceOperations<UserResource, UserResourceProperties> {
      @post
      @doc("Send a notification to the user")
      @segment("notify")
      op NotifyUser(
        ...ResourceInstanceParameters<UserResource>,
        @body notification: NotificationDetails
      ): ArmResponse<string> | ErrorResponse;
    }
    

    ARM Response Types

    Custom operations in ARM still need to respect the correct response schema. This library provides standard ARM response types to help with reusablility and compliance.

    Model Code Description
    ArmResponse<T> 200 Base Arm 200 response.
    ArmCreatedResponse<T> 201 Resource created response
    ArmDeletedResponse 200 Resource deleted response
    ArmDeleteAcceptedResponse 202 Resource deletion in progress response
    ArmDeletedNoContentResponse 204 Resource deleted response
    Page<T> 200 Return a list of resource with ARM pagination
    ErrorResponse<T> x Error response

    Common Operation Parameters

    There are a number of model types which specify common parameters which are used in resource type operations:

    Model In Description
    ApiVersionParameter query api-version parameter
    SubscriptionIdParameter path Subscription ID path parameter
    ResourceGroupNameParameter path Resource Group Name path parameter
    CommonResourceParameters path & query Group of Api version, Subscription ID and Resource group parameter
    ResourceUriParameter path Resource uri path parameter
    OperationIdParameter path Operation Id path parameter

    Generating an OpenAPI Specification

    To generate an OpenAPI v2 (Swagger) specification from the service definition, run the following command inside of the project folder:

    cadl compile . --emit @azure-tools/cadl-autorest
    

    This will create a file in the cadl-output subfolder called openapi.json.

    A Complete Example

    Here's a complete example main.cadl file based on all of the snippets in this README:

    import "@cadl-lang/rest";
    import "@cadl-lang/openapi";
    import "@azure-tools/cadl-autorest";
    import "@azure-tools/cadl-azure-core";
    import "@azure-tools/cadl-azure-resource-manager";
    
    @armProviderNamespace
    @serviceTitle("Contoso User Service")
    @serviceVersion("2020-10-01-preview")
    namespace Contoso.Users;
    
    using Cadl.Http;
    using Cadl.Rest;
    using Azure.ResourceManager;
    
    @doc("The properties of UserResource")
    model UserResourceProperties {
      @doc("The user's full name")
      fullName: string;
    
      @doc("The user's email address.")
      emailAddress: string;
    }
    
    @doc("A UserResource")
    model UserResource is TrackedResource<UserResourceProperties> {
      @key("userName")
      @segment("users")
      name: string;
    }
    
    @doc("The details of a user notification.")
    model NotificationDetails {
      @doc("The notification message.")
      message: string;
    
      @doc("If true, the notification is urgent.")
      urgent: boolean;
    }
    
    @armResourceOperations
    interface Users mixes ResourceOperations<UserResource, UserResourceProperties> {
      @post
      @doc("Send a notification to the user")
      @segment("notify")
      op NotifyUser(
        ...ResourceInstanceParameters<UserResource>,
        @body notification: NotificationDetails
      ): ArmResponse<string> | ErrorResponse;
    }
    
    @doc("An address resource belonging to a user resource.")
    @parentResource(UserResource)
    model AddressResource is ProxyResource<AddressResourceProperties> {
      @key("addressName")
      @segment("addresses")
      name: string;
    }
    
    @doc("The properties of AddressResource")
    model AddressResourceProperties {
      @doc("The street address.")
      streetAddress: string;
    
      @doc("The city of the address.")
      city: string;
    
      @doc("The state of the address.")
      state: string;
    
      @doc("The zip code of the address.")
      zip: int32;
    }
    
    @armResourceOperations
    interface Addresses mixes ProxyResourceOperations<AddressResource> {
    }
    

    Keywords

    Install

    npm i @azure-tools/cadl-azure-resource-manager

    DownloadsWeekly Downloads

    366

    Version

    0.10.0

    License

    MIT

    Unpacked Size

    208 kB

    Total Files

    88

    Last publish

    Collaborators

    • azure-sdk