From f697a26b1f9a782906a0a1dc22243962d573e0a2 Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Tue, 30 Apr 2024 22:01:59 -0700 Subject: [PATCH 01/11] ongoing --- cSpell.json | 28 +++++----- documentation/directory-structure.md | 80 ++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 19 deletions(-) diff --git a/cSpell.json b/cSpell.json index 9d6043844e08..fe7306331f9d 100644 --- a/cSpell.json +++ b/cSpell.json @@ -3,6 +3,7 @@ "language": "en", "words": [ "authnotrequired", + "confidentialledger", "Creds", "fixdate", "frontends", @@ -291,38 +292,38 @@ "freemium" ] }, - { + { "filename": "**/specification/sql/resource-manager/Microsoft.Sql/preview/2023-02-01-preview/ManagedInstances.json", "words": [ "freemium" ] }, - { + { "filename": "**/specification/sql/resource-manager/Microsoft.Sql/preview/2023-05-01-preview/ManagedInstances.json", "words": [ "freemium" ] }, - { + { "filename": "**/specification/sql/resource-manager/Microsoft.Sql/preview/2023-08-01-preview/ManagedInstances.json", "words": [ "freemium" ] }, - { + { "filename": "**/specification/sql/resource-manager/Microsoft.Sql/preview/2023-08-01-preview/ServerTrustCertificates.json", "words": [ "freemium" ] }, - { + { "filename": "**/specification/sql/resource-manager/Microsoft.Sql/preview/2023-08-01-preview/ManagedInstanceDtcs.json", "words": [ "msdtcdns", "msdtc's" ] }, - { + { "filename": "**/specification/sql/resource-manager/Microsoft.Sql/preview/2023-08-01-preview/TimeZones.json", "words": [ "freemium" @@ -505,7 +506,7 @@ "Idms", "Cluter", "Mfamily", - "Datacentre" + "Datacentre" ] }, { @@ -865,7 +866,6 @@ "psqldb" ] }, - { "filename": "**/specification/maps/data-plane/Weather/stable/1.1/weather.json", "words": [ @@ -873,7 +873,6 @@ "unittype" ] }, - { "filename": "**/specification/maps/data-plane/Microsoft.Maps/Render/preview/1.0/render.json", "words": [ @@ -1183,10 +1182,9 @@ { "filename": "**/specification/containerservice/resource-manager/Microsoft.ContainerService/**/*.json", "words": [ - "containerd" + "containerd" ] }, - { "filename": "**/specification/batch/data-plane/Microsoft.Batch/**/*.json", "words": [ @@ -1225,8 +1223,8 @@ ] }, { - "filename": "**/specification/confidentialledger/data-plane/Microsoft.CodeTransparency/preview/**/*.json", - "words": [ + "filename": "**/specification/confidentialledger/data-plane/Microsoft.CodeTransparency/preview/**/*.json", + "words": [ "cbor", "txids", "operationid", @@ -1254,8 +1252,8 @@ { "filename": "**/specification/sqlvirtualmachine/resource-manager/Microsoft.SqlVirtualMachine/**/*.json", "words": [ - "WUMU", - "WSUS" + "WUMU", + "WSUS" ] }, { diff --git a/documentation/directory-structure.md b/documentation/directory-structure.md index c56b1a4e708a..51c2b8997c33 100644 --- a/documentation/directory-structure.md +++ b/documentation/directory-structure.md @@ -7,6 +7,8 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one --> - [`specification` directory structure](#specification-directory-structure) + - [Key concepts](#key-concepts) + - [Uniform versioning](#uniform-versioning) - [`specification` folder](#specification-folder) - [`resource-manager` and `data-plane` folders](#resource-manager-and-data-plane-folders) - [AutoRest configuration `README.md` files](#autorest-configuration-readmemd-files) @@ -17,7 +19,9 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one - [Advanced scenario: service group](#advanced-scenario-service-group) - [Service group `common-types`](#service-group-common-types) - [Versioning services in a service group](#versioning-services-in-a-service-group) + - [Migrating from singular service to service group](#migrating-from-singular-service-to-service-group) - [Deprecated structure and hand-written OpenAPI specs](#deprecated-structure-and-hand-written-openapi-specs) + # `specification` directory structure @@ -30,13 +34,66 @@ You may be also interested in following: > The structure described in this article is strictly enforced. There exist some exceptions for historical reasons. > These exceptions are not allowed going forward. +## Key concepts + +The directory structure is a reflection of few key concepts. + +A `service` is a set of operation endpoints (typically HTTP REST API endpoints) that **version uniformly**. + +A `service group` is a set of services that share common (ARM) **Resource Provider (RP) Namespace**, `RPNS`. + +In case of ARM, a `service` consists of multiple `resource types`. + +### Uniform versioning + +A `service` **must version uniformly**. This means that the service, +all its dependencies, and all artifacts generated from the service, +**must** have the same version. + +In practice, this means, for an example service with version `2024-03-25`: + +- All the OpenAPI specification `.json` files the service is composed of must have the same version of `2024-03-25`. +- All the shared specifications (i.e. `common-types`) the service depends on must have the same version of `2024-03-25`. +- In case of ARM service, all the resource types must have the same version of `2024-03-25`. +- The language SDKs generated from the service must have the same version of `2024-03-25`. +- The documentation published for the service must have the same version of `2024-03-25`. +- Update to any version of the above requires update of all the other versions. + For example, if `common-types` published an updated version of `2024-04-17`, + then if the service wants to take dependency on it, it can only do it in + a new version of `2024-04-17`. + Because the service version is now `2024-04-17`, all the OpenAPI specification `.json` files the service is composed + of must have the same version of `2024-04-17`. + In addition, a new SDK must be generated from the service, and new documentation published, both tagged with + version `2024-04-17`. +- As a consequence of the above, if given service version uses `-preview` version anywhere, then the service + version itself must be `-preview`, it can depend only **only** `-preview` versions, and the generated SDK + and published docs must denote they are in `preview` too. + +TODO: +- These rules seem too strict. What if cadence of releasing `common-types` does not align with cadence of releasing + given service? Same for resource types? + - For example, service got released on `2024-01-01`, then new `common-types` got released on `2024-02-01` and on + `2024-03-01` new service version is to be released? Can a `2024-03-01` service version depend on `2024-02-01` `common-types`? + - If a service version can depend on `common-types` of a different version, can the generated SDK also depend + on different `.json` versions? + See e.g. [this bad setup of compute rm 2024-03-01](https://github.com/Azure/azure-rest-api-specs/blob/main/specification/compute/resource-manager/readme.md#tag-package-2024-03-01). + Could we make package `2024-03-01` depend on, say, `common-types` of `2024-02-01` and all other `.json` files of, say, `2024-02-15` ? +- What is the difference between resource types and OpenAPI specification `.json` files? + Can one deduce the resource type version by looking at the source OpenAPI `.json` ? +- What does it mean for OpenAPI specification `.json` to "have a version"? Are we talking about it being in appropriate + version-stamped folder and having the `info.version` property set? [Example](https://github.com/Azure/azure-rest-api-specs/blob/53f44eb266066c95d3e3a3fab7c9b9d14a0e36dd/specification/confidentialledger/resource-manager/Microsoft.ConfidentialLedger/stable/2022-05-13/confidentialledger.json#L4). + ## `specification` folder The `specification` folder is the root folder for all service specifications. -Each child of the `specification` folder corresponds to a `service` specification for given Azure team. Here we denote such folder as ``. -In advanced cases for big teams the `` folder can host multiple services, known as `service group`. -Read [the relevant section](#advanced-scenario-service-group) for details. +Each child of the `specification` folder corresponds to a `service` or `service group` specification +for given Azure team, depending on if given Azure team owns one or multiple services. +We denote such folder as ``. + +This article explains the singular `service` scenario. The details specific to `service group` and how they differ +from the `service` scenario are explained in the +[advanced scenario: service group](#advanced-scenario-service-group) section. Given `` has following structure: @@ -50,7 +107,8 @@ You can learn more about TypeSpec at [aka.ms/azsdk/typespec] and [aka.ms/typespe ## `resource-manager` and `data-plane` folders -The `/resource-manager` contains the ARM OpenAPI specifications emitted from TypeSpec in `/`. +The `/resource-manager` contains the ARM OpenAPI specifications emitted from TypeSpec in `/` +folders. The `resource-manager` folder has exactly one child folder whose name matches the **Resource Provider (RP) Namespace** (``), such as `Microsoft.Automation` (full list of namespaces is [here][Resource Provider list]). @@ -184,6 +242,15 @@ In case of big Azure teams, their `specification/` hosts multiple ser The main difference between one service and a service group is how they are presented to Azure customers: One service has one SDK package and one documentation portal, while a service group has separate SDK package for each service and separate documentation. +In case of a `service group`, the structure is like for `service`, but the contents of each +`resource-manager/` and `data-plane/` is instead additionally nested in a `` parent, for each service in the service group. + +- `/` (multiple folders) +- `/resource-manager//` (multiple folders, one for each value of ``) +- `/data-plane//` (multiple folders, one for each value of ``) + +Furthermore the `README.md` files are no longer located in the `resource-manager` or `data-plane` folders, but instead in `` folders. + For example, [`specification/containerservice`] is a `service group` for both `aks` and `fleet` services. The doc for `aks` is [Azure Kubernetes Service]. It points to aks REST reference e.g. for [API version `2024-01-01`][aks REST reference 2024-01-01], @@ -211,6 +278,11 @@ This means that each service in the service group must obey the same versioning However, multiple separate services can have different versioning cycles, including different SDK packages. Refer to the aforementioned `aks` and `fleet` services for examples of different versioning cycles in a service group. +### Migrating from singular service to service group + +TODO: how do we do it? This is the case of: +- https://github.com/Azure/azure-rest-api-specs-pr/pull/17717#issuecomment-2081974288 + ## Deprecated structure and hand-written OpenAPI specs As mentioned at the beginning of this article, for historical reasons, some `specification/` folders may From 986da01c7113274f8e7e1c5ee77733980cfd0de2 Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Tue, 30 Apr 2024 22:28:53 -0700 Subject: [PATCH 02/11] add some TODOs --- documentation/directory-structure.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/documentation/directory-structure.md b/documentation/directory-structure.md index 51c2b8997c33..231a014c250f 100644 --- a/documentation/directory-structure.md +++ b/documentation/directory-structure.md @@ -251,6 +251,10 @@ In case of a `service group`, the structure is like for `service`, but the conte Furthermore the `README.md` files are no longer located in the `resource-manager` or `data-plane` folders, but instead in `` folders. +TODO: +- Do we also also different setups of README.md files? +- Do we allow different layout of service groups? + For example, [`specification/containerservice`] is a `service group` for both `aks` and `fleet` services. The doc for `aks` is [Azure Kubernetes Service]. It points to aks REST reference e.g. for [API version `2024-01-01`][aks REST reference 2024-01-01], From bee6e244ef5ccd66b7df1cacdf5c453e0a459907 Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Wed, 1 May 2024 22:25:31 -0700 Subject: [PATCH 03/11] Apply suggestions from code review Co-authored-by: Mike Kistler --- documentation/directory-structure.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/directory-structure.md b/documentation/directory-structure.md index 231a014c250f..9bbe6587ca4f 100644 --- a/documentation/directory-structure.md +++ b/documentation/directory-structure.md @@ -53,7 +53,7 @@ all its dependencies, and all artifacts generated from the service, In practice, this means, for an example service with version `2024-03-25`: - All the OpenAPI specification `.json` files the service is composed of must have the same version of `2024-03-25`. -- All the shared specifications (i.e. `common-types`) the service depends on must have the same version of `2024-03-25`. +- All the shared specifications (i.e. `common-types`) the service depends on must have the same version. - In case of ARM service, all the resource types must have the same version of `2024-03-25`. - The language SDKs generated from the service must have the same version of `2024-03-25`. - The documentation published for the service must have the same version of `2024-03-25`. @@ -66,7 +66,7 @@ In practice, this means, for an example service with version `2024-03-25`: In addition, a new SDK must be generated from the service, and new documentation published, both tagged with version `2024-04-17`. - As a consequence of the above, if given service version uses `-preview` version anywhere, then the service - version itself must be `-preview`, it can depend only **only** `-preview` versions, and the generated SDK + version itself must be `-preview`, it can depend **only** on `-preview` versions, and the generated SDK and published docs must denote they are in `preview` too. TODO: From 8b305047d9bedb11990116d5d038f7477dc86509 Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Wed, 1 May 2024 22:36:05 -0700 Subject: [PATCH 04/11] elaborate --- documentation/directory-structure.md | 37 ++++++++++++++++------------ 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/documentation/directory-structure.md b/documentation/directory-structure.md index 9bbe6587ca4f..4b8e9517921e 100644 --- a/documentation/directory-structure.md +++ b/documentation/directory-structure.md @@ -50,34 +50,30 @@ A `service` **must version uniformly**. This means that the service, all its dependencies, and all artifacts generated from the service, **must** have the same version. -In practice, this means, for an example service with version `2024-03-25`: +In practice this means, for an example service with version `2024-03-25`: - All the OpenAPI specification `.json` files the service is composed of must have the same version of `2024-03-25`. -- All the shared specifications (i.e. `common-types`) the service depends on must have the same version. +- All the shared specifications (i.e. `common-types`) the service depends on must have the same version, + [e.g. `v6`][common-types v6] (but it can be different from the version of the service). - In case of ARM service, all the resource types must have the same version of `2024-03-25`. - The language SDKs generated from the service must have the same version of `2024-03-25`. - The documentation published for the service must have the same version of `2024-03-25`. - Update to any version of the above requires update of all the other versions. - For example, if `common-types` published an updated version of `2024-04-17`, + For example, if `common-types` published an updated version of `v7`, then if the service wants to take dependency on it, it can only do it in - a new version of `2024-04-17`. + a new version. For example, `2024-04-17`. Because the service version is now `2024-04-17`, all the OpenAPI specification `.json` files the service is composed - of must have the same version of `2024-04-17`. + of must have the same version of `2024-04-17` and the `info.version` property must say `2024-04-17`. In addition, a new SDK must be generated from the service, and new documentation published, both tagged with version `2024-04-17`. - As a consequence of the above, if given service version uses `-preview` version anywhere, then the service version itself must be `-preview`, it can depend **only** on `-preview` versions, and the generated SDK and published docs must denote they are in `preview` too. -TODO: -- These rules seem too strict. What if cadence of releasing `common-types` does not align with cadence of releasing - given service? Same for resource types? - - For example, service got released on `2024-01-01`, then new `common-types` got released on `2024-02-01` and on - `2024-03-01` new service version is to be released? Can a `2024-03-01` service version depend on `2024-02-01` `common-types`? - - If a service version can depend on `common-types` of a different version, can the generated SDK also depend - on different `.json` versions? - See e.g. [this bad setup of compute rm 2024-03-01](https://github.com/Azure/azure-rest-api-specs/blob/main/specification/compute/resource-manager/readme.md#tag-package-2024-03-01). - Could we make package `2024-03-01` depend on, say, `common-types` of `2024-02-01` and all other `.json` files of, say, `2024-02-15` ? +TODO: +- Per the rules above, a service and everything related must have exactly the same version, with the singular exception + of `common-types`, which use different versioning scheme anyway (`v1`, `v2`, ...). Is this what we want? + What about `common-types` specific to a service group? - What is the difference between resource types and OpenAPI specification `.json` files? Can one deduce the resource type version by looking at the source OpenAPI `.json` ? - What does it mean for OpenAPI specification `.json` to "have a version"? Are we talking about it being in appropriate @@ -245,6 +241,8 @@ One service has one SDK package and one documentation portal, while a service gr In case of a `service group`, the structure is like for `service`, but the contents of each `resource-manager/` and `data-plane/` is instead additionally nested in a `` parent, for each service in the service group. +The Azure team that has a service group has following directory structure: + - `/` (multiple folders) - `/resource-manager//` (multiple folders, one for each value of ``) - `/data-plane//` (multiple folders, one for each value of ``) @@ -284,8 +282,14 @@ services for examples of different versioning cycles in a service group. ### Migrating from singular service to service group -TODO: how do we do it? This is the case of: -- https://github.com/Azure/azure-rest-api-specs-pr/pull/17717#issuecomment-2081974288 +TODO: +- how do we do it? This is the case of: + - https://github.com/Azure/azure-rest-api-specs-pr/pull/17717#issuecomment-2081974288 +- Specifically, if given directory has `stable` and `preview` children, is it allowed to also have other children? + This is the case that is necessary in case of migration: `/resource-manager//` has `stable` and `preview` children, but with the service + group addition, it also has `` child, beside `stable` and `preview`. +- Do we allow any other sharing of common types than `common-types` ? In the example PR we have `operations`. Also, these + operations are versioned like API versions, not like the global `common-types`. ## Deprecated structure and hand-written OpenAPI specs @@ -317,6 +321,7 @@ All of the aforementioned cases are considered legacy and are not allowed going [aks REST reference 2024-01-01]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/containerservice/resource-manager/Microsoft.ContainerService/aks/stable/2024-01-01 [Azure Kubernetes Fleet Manager]: https://learn.microsoft.com/en-us/azure/kubernetes-fleet/ [Azure Kubernetes Service]: https://learn.microsoft.com/en-us/azure/aks/ +[common-types v6]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/common-types/resource-management/ [fleet REST reference 2023-10-15]: https://learn.microsoft.com/en-us/rest/api/fleet/operation-groups?view=rest-fleet-2023-10-15 [Resource Provider list]: https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-services-resource-providers#match-resource-provider-to-service [Specification index]: https://azure.github.io/azure-sdk/releases/latest/all/specs.html From 9187ae5ef5375763fe5f8d53caf52fab617ae5fa Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Tue, 7 May 2024 12:48:19 -0700 Subject: [PATCH 05/11] clarify --- documentation/directory-structure.md | 57 ++++++++++++++++------------ 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/documentation/directory-structure.md b/documentation/directory-structure.md index 4b8e9517921e..9464c0cba13d 100644 --- a/documentation/directory-structure.md +++ b/documentation/directory-structure.md @@ -43,41 +43,50 @@ A `service` is a set of operation endpoints (typically HTTP REST API endpoints) A `service group` is a set of services that share common (ARM) **Resource Provider (RP) Namespace**, `RPNS`. In case of ARM, a `service` consists of multiple `resource types`. +A `resource type` can be derived from the URL of HTTP API operations that pertain to it. ### Uniform versioning -A `service` **must version uniformly**. This means that the service, -all its dependencies, and all artifacts generated from the service, -**must** have the same version. - -In practice this means, for an example service with version `2024-03-25`: - -- All the OpenAPI specification `.json` files the service is composed of must have the same version of `2024-03-25`. +A `service` **must version uniformly**. This means the following: + +1. Any deployed service operation endpoint must belong to an API version. An API version once deployed is immutable. + Its behavior or constituent operations cannot be changed. +1. Any given service API version can be composed only of HTTP API operations and ARM resource types (if applicable) + that have the same API version. +1. Any documentation pertaining to the service and any SDKs generated from the service must pertain to only + one service version. +1. The service version must be always represented in its entirety; any SDK or documentation referring to the service + must encompass all of it. +1. The `common-types` OpenAPI definition shared across multiple services can version independently of the service. + However, the rule that API version is immutable still must be observed. + +The **uniform versioning** has several implications and implementation decisions supporting it: + +- The service is effectively defined as a series of consecutive API versions. +- Each API version is represented by a pair of folders representing its lifecycle stage and release date, + like `stable/2024-03-05` or `preview/2024-05-15-preview`. +- The entirety of given API service specification must be placed inside its folder, e.g. `stable/2024-03-05`. + The service consists of operation endpoints defined in OpenAPI spec `.json` files placed in its API version folder. +- The service, its documentation, and any SDK referencing it, all must version in lockstep. If a new service API + version is released, also a new entry of documentation must be released to cover it. Similarly, a new version + of given SDK package must be released to refer to the new service version. +- Nowhere within a service, documentation for it, or SDK referencing it, + can multiple service API versions be mixed. As such: + - `preview` API versions cannot be mixed with `stable` API versions. + - No REST API endpoint for given API version can have any kind of dependency on any other API version. +- Any AutoRest config README.md file definition for the service must have corresponding tags to the API versions + present in the directory structure. Each of these tags must include all OpenAPI spec `.json` files for given API version, + and only for that API version. - All the shared specifications (i.e. `common-types`) the service depends on must have the same version, [e.g. `v6`][common-types v6] (but it can be different from the version of the service). -- In case of ARM service, all the resource types must have the same version of `2024-03-25`. -- The language SDKs generated from the service must have the same version of `2024-03-25`. -- The documentation published for the service must have the same version of `2024-03-25`. -- Update to any version of the above requires update of all the other versions. +- Updating `common-types` version requires updating the API version. For example, if `common-types` published an updated version of `v7`, then if the service wants to take dependency on it, it can only do it in a new version. For example, `2024-04-17`. Because the service version is now `2024-04-17`, all the OpenAPI specification `.json` files the service is composed of must have the same version of `2024-04-17` and the `info.version` property must say `2024-04-17`. In addition, a new SDK must be generated from the service, and new documentation published, both tagged with - version `2024-04-17`. -- As a consequence of the above, if given service version uses `-preview` version anywhere, then the service - version itself must be `-preview`, it can depend **only** on `-preview` versions, and the generated SDK - and published docs must denote they are in `preview` too. - -TODO: -- Per the rules above, a service and everything related must have exactly the same version, with the singular exception - of `common-types`, which use different versioning scheme anyway (`v1`, `v2`, ...). Is this what we want? - What about `common-types` specific to a service group? -- What is the difference between resource types and OpenAPI specification `.json` files? - Can one deduce the resource type version by looking at the source OpenAPI `.json` ? -- What does it mean for OpenAPI specification `.json` to "have a version"? Are we talking about it being in appropriate - version-stamped folder and having the `info.version` property set? [Example](https://github.com/Azure/azure-rest-api-specs/blob/53f44eb266066c95d3e3a3fab7c9b9d14a0e36dd/specification/confidentialledger/resource-manager/Microsoft.ConfidentialLedger/stable/2022-05-13/confidentialledger.json#L4). + service version `2024-04-17`. ## `specification` folder From efd074dd80e5f08493d043f34a344957654df704 Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Tue, 7 May 2024 12:59:44 -0700 Subject: [PATCH 06/11] clarify --- documentation/directory-structure.md | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/documentation/directory-structure.md b/documentation/directory-structure.md index 9464c0cba13d..eca8bbfeae7c 100644 --- a/documentation/directory-structure.md +++ b/documentation/directory-structure.md @@ -258,10 +258,6 @@ The Azure team that has a service group has following directory structure: Furthermore the `README.md` files are no longer located in the `resource-manager` or `data-plane` folders, but instead in `` folders. -TODO: -- Do we also also different setups of README.md files? -- Do we allow different layout of service groups? - For example, [`specification/containerservice`] is a `service group` for both `aks` and `fleet` services. The doc for `aks` is [Azure Kubernetes Service]. It points to aks REST reference e.g. for [API version `2024-01-01`][aks REST reference 2024-01-01], @@ -291,14 +287,14 @@ services for examples of different versioning cycles in a service group. ### Migrating from singular service to service group -TODO: -- how do we do it? This is the case of: - - https://github.com/Azure/azure-rest-api-specs-pr/pull/17717#issuecomment-2081974288 -- Specifically, if given directory has `stable` and `preview` children, is it allowed to also have other children? - This is the case that is necessary in case of migration: `/resource-manager//` has `stable` and `preview` children, but with the service - group addition, it also has `` child, beside `stable` and `preview`. -- Do we allow any other sharing of common types than `common-types` ? In the example PR we have `operations`. Also, these - operations are versioned like API versions, not like the global `common-types`. +In case your azure SDK team owned a singular service and is now expanding to a service group, do the following: + +- In one pull request, move the singular service to become a service in a service group. This means it will be moved + inside a directory denoting the service group name, and its README.md file will also be moved there. + As this PR is moving the service, it means the PR diff will include deletions of the singular service README.md and + API version folders, and it will include addition of the new READE.md and API version folder, both inside the service + group folder. +- In a follow-up PRs add other services to belong to the service group. One service per PR. ## Deprecated structure and hand-written OpenAPI specs From 9a986a146e16d37573ce02bb2af1c646f075f7a8 Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Tue, 7 May 2024 13:03:06 -0700 Subject: [PATCH 07/11] clarify --- documentation/directory-structure.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/documentation/directory-structure.md b/documentation/directory-structure.md index eca8bbfeae7c..28d7a78322d9 100644 --- a/documentation/directory-structure.md +++ b/documentation/directory-structure.md @@ -73,12 +73,12 @@ The **uniform versioning** has several implications and implementation decisions - Nowhere within a service, documentation for it, or SDK referencing it, can multiple service API versions be mixed. As such: - `preview` API versions cannot be mixed with `stable` API versions. - - No REST API endpoint for given API version can have any kind of dependency on any other API version. + - No REST API endpoint for given API version can have any kind of dependency on service endpoint from any other API version. - Any AutoRest config README.md file definition for the service must have corresponding tags to the API versions present in the directory structure. Each of these tags must include all OpenAPI spec `.json` files for given API version, and only for that API version. -- All the shared specifications (i.e. `common-types`) the service depends on must have the same version, - [e.g. `v6`][common-types v6] (but it can be different from the version of the service). +- All the shared OpenAPI definitions (i.e. `common-types`) the service depends on must have the same version, + [e.g. `v6`][common-types v6], but it can be different from the version of the service. - Updating `common-types` version requires updating the API version. For example, if `common-types` published an updated version of `v7`, then if the service wants to take dependency on it, it can only do it in @@ -87,6 +87,7 @@ The **uniform versioning** has several implications and implementation decisions of must have the same version of `2024-04-17` and the `info.version` property must say `2024-04-17`. In addition, a new SDK must be generated from the service, and new documentation published, both tagged with service version `2024-04-17`. +- All of these rules apply both for OpenAPI specs emitted from TypeSpec as well as for hand-written OpenAPI specs. ## `specification` folder From 7a634ca460cd8c0f562526991b35bf78fcdc702c Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Tue, 7 May 2024 13:05:47 -0700 Subject: [PATCH 08/11] clarify --- documentation/directory-structure.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/documentation/directory-structure.md b/documentation/directory-structure.md index 28d7a78322d9..ddac5612c4d2 100644 --- a/documentation/directory-structure.md +++ b/documentation/directory-structure.md @@ -291,11 +291,12 @@ services for examples of different versioning cycles in a service group. In case your azure SDK team owned a singular service and is now expanding to a service group, do the following: - In one pull request, move the singular service to become a service in a service group. This means it will be moved - inside a directory denoting the service group name, and its README.md file will also be moved there. + inside a directory denoting the service name (i.e. `//`), and its README.md file will also be moved there. As this PR is moving the service, it means the PR diff will include deletions of the singular service README.md and - API version folders, and it will include addition of the new READE.md and API version folder, both inside the service - group folder. -- In a follow-up PRs add other services to belong to the service group. One service per PR. + API version folders, and it will include addition of the new README.md and API version folder, + both inside the service folder. +- In a follow-up PRs add other services to belong to the service group. One service per PR. This means each such PR will + add new `//` folder with its own README.md and API version folders. ## Deprecated structure and hand-written OpenAPI specs From 14f01a25083efe5c16477e0ff11b0064c097ee1d Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Tue, 7 May 2024 13:09:31 -0700 Subject: [PATCH 09/11] conciseness --- documentation/directory-structure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/directory-structure.md b/documentation/directory-structure.md index ddac5612c4d2..192b201e91a0 100644 --- a/documentation/directory-structure.md +++ b/documentation/directory-structure.md @@ -87,7 +87,7 @@ The **uniform versioning** has several implications and implementation decisions of must have the same version of `2024-04-17` and the `info.version` property must say `2024-04-17`. In addition, a new SDK must be generated from the service, and new documentation published, both tagged with service version `2024-04-17`. -- All of these rules apply both for OpenAPI specs emitted from TypeSpec as well as for hand-written OpenAPI specs. +- All of these rules apply both for OpenAPI specs emitted from TypeSpec as well as for hand-written. ## `specification` folder From 1269828d6daafcd27cf0f9892a1c4511b8181f6f Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Fri, 24 May 2024 17:38:50 -0700 Subject: [PATCH 10/11] Update docs --- documentation/directory-structure.md | 332 ++++++------------ documentation/glossary.md | 66 ++++ .../typespec-structure-guidelines.md | 8 +- documentation/uniform-versioning.md | 95 +++++ 4 files changed, 263 insertions(+), 238 deletions(-) create mode 100644 documentation/glossary.md create mode 100644 documentation/uniform-versioning.md diff --git a/documentation/directory-structure.md b/documentation/directory-structure.md index 192b201e91a0..6f0e61258819 100644 --- a/documentation/directory-structure.md +++ b/documentation/directory-structure.md @@ -8,23 +8,19 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one - [`specification` directory structure](#specification-directory-structure) - [Key concepts](#key-concepts) - - [Uniform versioning](#uniform-versioning) - [`specification` folder](#specification-folder) - - [`resource-manager` and `data-plane` folders](#resource-manager-and-data-plane-folders) - - [AutoRest configuration `README.md` files](#autorest-configuration-readmemd-files) - - [`stable` and `preview` folders](#stable-and-preview-folders) - - [A complete example directory structure of `specification/`](#a-complete-example-directory-structure-of-specificationazureteam) - - [Naming guidelines for `specification` folder contents](#naming-guidelines-for-specification-folder-contents) + - [`` folders](#typespecsrc-folders) + - [`resource-manager/` folder](#resource-managerrpns-folder) + - [`data-plane/` folders](#data-planenamespace-folders) + - [Service folder structure](#service-folder-structure) - [`specification/common-types`](#specificationcommon-types) - - [Advanced scenario: service group](#advanced-scenario-service-group) - - [Service group `common-types`](#service-group-common-types) - - [Versioning services in a service group](#versioning-services-in-a-service-group) - - [Migrating from singular service to service group](#migrating-from-singular-service-to-service-group) - - [Deprecated structure and hand-written OpenAPI specs](#deprecated-structure-and-hand-written-openapi-specs) + - [Naming guidelines for `specification` folder contents](#naming-guidelines-for-specification-folder-contents) + - [About legacy, deprecated directory structure for services and service groups](#about-legacy-deprecated-directory-structure-for-services-and-service-groups) + - [Migrating from a singular service to service group in a legacy directory structure](#migrating-from-a-singular-service-to-service-group-in-a-legacy-directory-structure) + - [Deprecated directory structure and hand-written OpenAPI specs](#deprecated-directory-structure-and-hand-written-openapi-specs) # `specification` directory structure - This article describes the directory structure / folder layout of the `specification` folder. You may be also interested in following: - [Specification index] @@ -36,198 +32,100 @@ You may be also interested in following: ## Key concepts -The directory structure is a reflection of few key concepts. - -A `service` is a set of operation endpoints (typically HTTP REST API endpoints) that **version uniformly**. - -A `service group` is a set of services that share common (ARM) **Resource Provider (RP) Namespace**, `RPNS`. - -In case of ARM, a `service` consists of multiple `resource types`. -A `resource type` can be derived from the URL of HTTP API operations that pertain to it. - -### Uniform versioning - -A `service` **must version uniformly**. This means the following: - -1. Any deployed service operation endpoint must belong to an API version. An API version once deployed is immutable. - Its behavior or constituent operations cannot be changed. -1. Any given service API version can be composed only of HTTP API operations and ARM resource types (if applicable) - that have the same API version. -1. Any documentation pertaining to the service and any SDKs generated from the service must pertain to only - one service version. -1. The service version must be always represented in its entirety; any SDK or documentation referring to the service - must encompass all of it. -1. The `common-types` OpenAPI definition shared across multiple services can version independently of the service. - However, the rule that API version is immutable still must be observed. - -The **uniform versioning** has several implications and implementation decisions supporting it: - -- The service is effectively defined as a series of consecutive API versions. -- Each API version is represented by a pair of folders representing its lifecycle stage and release date, - like `stable/2024-03-05` or `preview/2024-05-15-preview`. -- The entirety of given API service specification must be placed inside its folder, e.g. `stable/2024-03-05`. - The service consists of operation endpoints defined in OpenAPI spec `.json` files placed in its API version folder. -- The service, its documentation, and any SDK referencing it, all must version in lockstep. If a new service API - version is released, also a new entry of documentation must be released to cover it. Similarly, a new version - of given SDK package must be released to refer to the new service version. -- Nowhere within a service, documentation for it, or SDK referencing it, - can multiple service API versions be mixed. As such: - - `preview` API versions cannot be mixed with `stable` API versions. - - No REST API endpoint for given API version can have any kind of dependency on service endpoint from any other API version. -- Any AutoRest config README.md file definition for the service must have corresponding tags to the API versions - present in the directory structure. Each of these tags must include all OpenAPI spec `.json` files for given API version, - and only for that API version. -- All the shared OpenAPI definitions (i.e. `common-types`) the service depends on must have the same version, - [e.g. `v6`][common-types v6], but it can be different from the version of the service. -- Updating `common-types` version requires updating the API version. - For example, if `common-types` published an updated version of `v7`, - then if the service wants to take dependency on it, it can only do it in - a new version. For example, `2024-04-17`. - Because the service version is now `2024-04-17`, all the OpenAPI specification `.json` files the service is composed - of must have the same version of `2024-04-17` and the `info.version` property must say `2024-04-17`. - In addition, a new SDK must be generated from the service, and new documentation published, both tagged with - service version `2024-04-17`. -- All of these rules apply both for OpenAPI specs emitted from TypeSpec as well as for hand-written. - -## `specification` folder - -The `specification` folder is the root folder for all service specifications. - -Each child of the `specification` folder corresponds to a `service` or `service group` specification -for given Azure team, depending on if given Azure team owns one or multiple services. -We denote such folder as ``. - -This article explains the singular `service` scenario. The details specific to `service group` and how they differ -from the `service` scenario are explained in the -[advanced scenario: service group](#advanced-scenario-service-group) section. +The directory structure is a reflection of a few key concepts. -Given `` has following structure: +Familiarize yourself with the concepts of `service`, `service group` and `uniform versioning` +as explained in the [glossary]. -- `/` (multiple folders) -- `/resource-manager` -- `/data-plane` - -The `/` folders contain the TypeSpec specification for the given `service` or `service group`. -You can find details on the name and contents of these folders in [TypeSpec directory structure]. -You can learn more about TypeSpec at [aka.ms/azsdk/typespec] and [aka.ms/typespec]. - -## `resource-manager` and `data-plane` folders +## `specification` folder -The `/resource-manager` contains the ARM OpenAPI specifications emitted from TypeSpec in `/` -folders. +The `specification` folder is the root folder for all `service` specifications. -The `resource-manager` folder has exactly one child folder whose name matches the **Resource Provider (RP) Namespace** (``), -such as `Microsoft.Automation` (full list of namespaces is [here][Resource Provider list]). -There is 1 to 1 correspondence between an RP and an RP namespace. -There must be **exactly one** RP namespace folder under given `resource-manager` folder. -We denote such folder as `resource-manager/`. +Each child of the `specification` folder corresponds to ``. +All the `service` (see [glossary]) specifications owned by that team are rooted in their `` folder. -The `/data-plane` contains the data-plane OpenAPI specifications emitted from TypeSpec in ``. -The `data-plane` folder has no child `` folder. However, it can have a set of `` folders. +Given `` folder has following structure: -## AutoRest configuration `README.md` files +- `/` (multiple `` folders are allowed) +- `/resource-manager/` (exactly one `` folder is allowed) +- `/data-plane/` (multiple `` folders are allowed) -Both the `/resource-manager` and `/data-plane` folders must contain an AutoRest configuration file, `README.md`. -Learn more about this file at [aka.ms/azsdk/autorest]. +### `` folders - +The `/` folders contain the TypeSpec specifications for the services owned by the team. -Each `README.md` describes a single `service` and is used as an SDK package and documentation for each version of the service. -Inside the `README.md` file there are lists of paths to OpenAPI spec `.json` files making up given service version. +The content of these folders is used as input to emit OpenAPI specifications +placed within `/resource-manager/` and `/data-plane/` folders. > [!NOTE] -> All OpenAPI specs for given service version (i.e. the list of paths in given `input-file:` block in the `README.md`) must have the same service version, -> which also means being in the same [API version lifecycle stage][aka.ms/azsdk/api-versions]. +> Some services may not have `` folders. In such case, these services OpenAPI specs are hand-written. +> This is legacy, deprecated practice and is not allowed going forward. -## `stable` and `preview` folders - -Both `/resource-manager/` and `/data-plane/` folders, in addition to containing `README.md`, also can contain -`stable` and `preview` folders. These folders contain OpenAPI specs in the `stable` and `preview` [lifecycle stages][aka.ms/azsdk/api-versions] -respectively, organized in `` subfolders for each service API version. For example, `/resource-manager//stable/` or -`/data-plane//preview/`. - -Each such API version folder directly contains a set of `.json` files containing OpenAPI specs emitted from TypeSpec, as well as an `examples` child folder -with `.json` files having the contents of [`x-ms-examples`] referenced from the OpenAPI specs. - -## A complete example directory structure of `specification/` - -Putting everything together discussed, the directory structure of a singular `specification//` is as follows: +You can find details on the name and contents of `` folders in [TypeSpec directory structure]. +You can learn more about TypeSpec at [aka.ms/azsdk/typespec] and [aka.ms/typespec]. -``` yaml -/1/... -/2/... # multiple '' folders +### `resource-manager/` folder -/resource-manager/README.md -/resource-manager//stable//*.json -/resource-manager//stable//examples/*.json - // ... # multiple '' folders -/resource-manager//preview//*.json -/resource-manager//preview//examples/*.json - // ... # multiple '' folders +The `/resource-manager/` is a folder corresponding to **Resource Provider (RP) namespace**. -/data-plane/README.md -/data-plane//stable//*.json -/data-plane//stable//examples/*.json - // ... # multiple '' folders -/data-plane//preview//*.json -/data-plane//preview//examples/*.json - // ... # multiple '' folders - // ... # multiple '' folders +An example RPNS is `Microsoft.Automation`. A list of RPs can be found in the [Resource Provider list]. -``` +This folder corresponds to a `service group` (see [glossary]) for all ARM services owned by the team. -As a specific example of the above, consider [`specification/confidentialledger`] `` which has the following structure: +An `` folder has one or more children `` folders corresponding to the services belonging +to the `service group` represented by the `` folder. -``` yaml +For example, [`specification/containerservice/resource-manager/Microsoft.ContainerService/aks`] +is a folder for the `aks` service within the `Microsoft.ContainerService` ARM Resource Provider namespace. -# ===== s +> [!NOTE] +> Many Azure teams that have one ARM service instead of rooting it in `specification//resource-manager//` root it +> in `specification//resource-manager`. This is legacy, deprecated structure and is not allowed going forward. -/Microsoft.CodeTransparency/ -/Microsoft.ManagedCcf/ +In addition, the `` folder may contain `common-types` child folder that usually is of form `common-types/v/common.json` and contains types +shared across API versions. E.g. [`Microsoft.Compute/common-types`]. -# ===== data-plane +### `data-plane/` folders -/data-plane/README.md +The set of `/data-plane/` folders is the equivalent of `/resource-manager/` but with following distinctions: -# ----- : Microsoft.CodeTransparency +- `/data-plane` pertains to data-plane service APIs, not ARM service APIs. +- `/data-plane/` is a set of one or more folder, not only one. -/data-plane/Microsoft.CodeTransparency/preview/2024-01-11-preview -/data-plane/Microsoft.CodeTransparency/preview/2024-01-11-preview/examples +## Service folder structure -# ----- : Microsoft.ConfidentialLedger +As described above, ARM service folder path is: -/data-plane/Microsoft.ConfidentialLedger/stable -/data-plane/Microsoft.ConfidentialLedger/stable/2022-05-13 -/data-plane/Microsoft.ConfidentialLedger/stable/2022-05-13/examples +`specification//resource-manager//` -/data-plane/Microsoft.ConfidentialLedger/preview -/data-plane/Microsoft.ConfidentialLedger/preview/2023-01-18-preview -/data-plane/Microsoft.ConfidentialLedger/preview/2023-01-18-preview/examples -# ... more previews here +while data-plane service folder path is: -# ----- : Microsoft.ManagedCcf +`specification//data-plane//`. -/data-plane/Microsoft.ManagedCcf/preview/2023-06-01-preview -/data-plane/Microsoft.ManagedCcf/preview/2023-06-01-preview/examples +A service folder has the following elements: -# ===== resource-manager +- The [AutoRest config `README.md` file]. See also section about it in [uniform versioning article]. +- Additional AutoRest config `README.md` files specific to given language SDK. +- The `stable` and `preview` folders if applicable. -/resource-manager/README.md +The `stable` and `preview` folders contain OpenAPI specs in the `stable` and `preview` [lifecycle stages][aka.ms/azsdk/api-versions] +respectively, organized in `` subfolders for each service API version. -# ----- resource-manager RP Namespace (): Microsoft.ConfidentialLedger +For example: +- `/resource-manager///stable/` +- `/resource-manager///preview/` +- `/data-plane///stable/` +- `/data-plane///preview/` -/resource-manager/Microsoft.ConfidentialLedger/stable/2022-05-13 -/resource-manager/Microsoft.ConfidentialLedger/stable/2022-05-13/examples +Each such API version folder directly contains a set of `.json` files containing OpenAPI specs emitted from TypeSpec, as well as an `examples` child folder +with `.json` files having the contents of [`x-ms-examples`] referenced from the OpenAPI specs. -/resource-manager/Microsoft.ConfidentialLedger/preview/2023-06-28-preview -/resource-manager/Microsoft.ConfidentialLedger/preview/2023-06-28-preview/examples -# ... more previews here -/resource-manager/Microsoft.ConfidentialLedger/preview/2020-12-01-preview -/resource-manager/Microsoft.ConfidentialLedger/preview/2020-12-01-preview/examples +Read [API versioning guidelines] to learn more. -``` +## `specification/common-types` -For another example, see [`specification/eventgrid`]. +The special directory of [`specification/common-types`] contains shared definitions that can be reused across all Azure team services in their +`specification` child folders. ## Naming guidelines for `specification` folder contents @@ -237,73 +135,33 @@ For another example, see [`specification/eventgrid`]. - For file names, any casing is allowed. - When in doubt, mimic naming of the examples provided in this article. -## `specification/common-types` - -The special directory of [`specification/common-types`] contains shared definitions that can be reused across all Azure team services in their -`specification` child folders. +## About legacy, deprecated directory structure for services and service groups -## Advanced scenario: service group +Many teams follow a legacy, deprecated directory structure which usually has following differences: -In case of big Azure teams, their `specification/` hosts multiple services, together known as `service group`. -The main difference between one service and a service group is how they are presented to Azure customers: -One service has one SDK package and one documentation portal, while a service group has separate SDK package for each service and separate documentation. +- If a team owns only one service, instead of rooting it in `specification//resource-manager//`, it is rooted in + `specification//resource-manager`. +- If a team first owned one service and then expanded to a service group, + it contains mixture of both the deprecated structure (for the first service) as well as the correct structure (for the 2nd and following services). -In case of a `service group`, the structure is like for `service`, but the contents of each -`resource-manager/` and `data-plane/` is instead additionally nested in a `` parent, for each service in the service group. +This legacy structure is not allowed going forward. -The Azure team that has a service group has following directory structure: +## Migrating from a singular service to service group in a legacy directory structure -- `/` (multiple folders) -- `/resource-manager//` (multiple folders, one for each value of ``) -- `/data-plane//` (multiple folders, one for each value of ``) +In case an Azure SDK team owns a singular service following the legacy, deprecated layout, and wants to expand to a full +service group, it can do the following: -Furthermore the `README.md` files are no longer located in the `resource-manager` or `data-plane` folders, but instead in `` folders. +- Keep the existing service as-is, without any changes. +- Introduce the new services using the new, correct structure. -For example, [`specification/containerservice`] is a `service group` for both `aks` and `fleet` services. +## Deprecated directory structure and hand-written OpenAPI specs -The doc for `aks` is [Azure Kubernetes Service]. It points to aks REST reference e.g. for [API version `2024-01-01`][aks REST reference 2024-01-01], -which corresponds to [`specification/containerservice/resource-manager/Microsoft.ContainerService/aks/stable/2024-01-01`]. - -The doc for `fleet` is [Azure Kubernetes Fleet Manager]. It point to fleet REST reference, e.g. for [API version `2023-10-15`][fleet REST reference 2023-10-15], -which corresponds to [`specification/containerservice/resource-manager/Microsoft.ContainerService/fleet/stable/2023-10-15`]. - -Using our example, note the most important directory structure difference of a `service group` scenario as compared to singular `service`: - -- The `resource-manager/Microsoft.ContainerService` folder has multiple child service folders which contain `stable` and `preview` folders for each service, - instead of directly containing `stable` and `preview` folders. -- Each of the `aks` and `fleet` subfolders have their own `README.md` file, instead of there being one `README.md` in the `resource-manager` folder. - As a result, the SDKs of these services are separate. - -### Service group `common-types` - -A service group can also introduce its own set of `common-types` which are too general to be shared across all Azure teams but common enough to be -shared across all services in given service group. For an example, see [`Microsoft.Compute/common-types`]. - -### Versioning services in a service group - -The versioning policy for API and SDK packages applies independently to each service in the service group. -This means that each service in the service group must obey the same versioning rules as it were a singular service. -However, multiple separate services can have different versioning cycles, including different SDK packages. Refer to the aforementioned `aks` and `fleet` -services for examples of different versioning cycles in a service group. - -### Migrating from singular service to service group - -In case your azure SDK team owned a singular service and is now expanding to a service group, do the following: - -- In one pull request, move the singular service to become a service in a service group. This means it will be moved - inside a directory denoting the service name (i.e. `//`), and its README.md file will also be moved there. - As this PR is moving the service, it means the PR diff will include deletions of the singular service README.md and - API version folders, and it will include addition of the new README.md and API version folder, - both inside the service folder. -- In a follow-up PRs add other services to belong to the service group. One service per PR. This means each such PR will - add new `//` folder with its own README.md and API version folders. - -## Deprecated structure and hand-written OpenAPI specs - -As mentioned at the beginning of this article, for historical reasons, some `specification/` folders may +As mentioned multiple times in this article, for historical reasons, some `specification/` folders may violate some of the constraints presented in this article. This includes violations like: - More deeply nested subfolders than allowed. +- `README.md` placed in a wrong folder (thus incorrectly denoting it as a `service` folder). +- Lack of `` directory for given service path. - Incorrect lack of `-preview` suffix in `preview` API versions. - Mixing of `stable` and `preview` API versions in the same folder subtree. - Mixing of multiple API versions in given `README.md` package, including mixing of multiple API version lifecycle stages. @@ -311,25 +169,31 @@ violate some of the constraints presented in this article. This includes violati In addition, some `` folders have OpenAPI specs that have been written manually instead of emitted from TypeSpec. In some cases the folders have mixture of manually-written and TypeSpec-emitted OpenAPI specs. -All of the aforementioned cases are considered legacy and are not allowed going forward. +All of the aforementioned cases are considered legacy & deprecated, and are not allowed going forward. [`Microsoft.Compute/common-types`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/compute/resource-manager/Microsoft.Compute/common-types/ [`specification/common-types`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/common-types +[`specification/containerservice/resource-manager/Microsoft.ContainerService/aks`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/containerservice/resource-manager/Microsoft.ContainerService/aks +[`x-ms-examples`]: https://azure.github.io/autorest/extensions/#x-ms-examples +[aka.ms/azsdk/api-versions]: https://aka.ms/azsdk/api-versions +[aka.ms/azsdk/typespec]: https://aka.ms/azsdk/typespec +[aka.ms/typespec]: https://aka.ms/typespec +[API versioning guidelines]: https://github.com/microsoft/api-guidelines/blob/vNext/azure/Guidelines.md#api-versioning +[AutoRest config `README.md` file]: https://aka.ms/azsdk/autorest + +[glossary]: ./glossary.md +[Resource Provider list]: https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-services-resource-providers#match-resource-provider-to-service +[Specification index]: https://azure.github.io/azure-sdk/releases/latest/all/specs.html +[TypeSpec directory structure]: https://github.com/Azure/azure-rest-api-specs/blob/main/documentation/typespec-structure-guidelines.md +[uniform versioning article]: ./uniform-versioning.md + + [`specification/confidentialledger`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/confidentialledger [`specification/containerservice/resource-manager/Microsoft.ContainerService/aks/stable/2024-01-01`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/containerservice/resource-manager/Microsoft.ContainerService/aks/stable/2024-01-01 [`specification/containerservice/resource-manager/Microsoft.ContainerService/fleet/stable/2023-10-15`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/containerservice/resource-manager/Microsoft.ContainerService/fleet/stable/2023-10-15 [`specification/containerservice`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/containerservice [`specification/eventgrid`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/eventgrid -[`x-ms-examples`]: https://azure.github.io/autorest/extensions/#x-ms-examples -[aka.ms/azsdk/api-versions]: https://aka.ms/azsdk/api-versions [aka.ms/azsdk/autorest]: https://aka.ms/azsdk/autorest -[aka.ms/azsdk/typespec]: https://aka.ms/azsdk/typespec -[aka.ms/typespec]: https://aka.ms/typespec [aks REST reference 2024-01-01]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/containerservice/resource-manager/Microsoft.ContainerService/aks/stable/2024-01-01 [Azure Kubernetes Fleet Manager]: https://learn.microsoft.com/en-us/azure/kubernetes-fleet/ -[Azure Kubernetes Service]: https://learn.microsoft.com/en-us/azure/aks/ -[common-types v6]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/common-types/resource-management/ [fleet REST reference 2023-10-15]: https://learn.microsoft.com/en-us/rest/api/fleet/operation-groups?view=rest-fleet-2023-10-15 -[Resource Provider list]: https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-services-resource-providers#match-resource-provider-to-service -[Specification index]: https://azure.github.io/azure-sdk/releases/latest/all/specs.html -[TypeSpec directory structure]: https://github.com/Azure/azure-rest-api-specs/blob/main/documentation/typespec-structure-guidelines.md diff --git a/documentation/glossary.md b/documentation/glossary.md new file mode 100644 index 000000000000..2ece593fa2ae --- /dev/null +++ b/documentation/glossary.md @@ -0,0 +1,66 @@ +# Glossary + +This article defines some of the terms used in the articles under `documentation` directory. + +## Resource type + +In case of ARM, a `service` is a collection of `resource types` or `resource type groups`. + +## Service + +A `service` is a set of operation endpoints (typically HTTP REST API endpoints) that [**version uniformly**][uniform versioning article]. + +A `service` corresponds to a cohesive, uniformly versioned experience for the customer with HTTP REST API surface, +documentation portal and language SDKs. For example, [Azure Kubernetes Service]. + +In this repository, an ARM service has a path of form: + +`specification//resource-manager//` + +where `` stands for ARM **Resource Provider (RP) namespace**. + +A data-plane service has a path of form: + +`specification//data-plane//` + +> [!NOTE] +> Some existing services follow different directory structure layouts. +> All such layouts are legacy, deprecated, and not allowed going forward. + +For example, [`specification/containerservice/resource-manager/Microsoft.ContainerService/aks`] +is a folder for the `aks` service within the `Microsoft.ContainerService` ARM Resource Provider namespace. + +You can learn more about how a `service` maps to its directory in the [directory structure article]. + +## Service group + +A `service group` is a set of services that share a common ARM **Resource Provider (RP) namespace**, `RPNS`. + +A `service group` has a path of form: + +`specification//resource-manager/` + +as such, it corresponds to ARM Resource Provider Namespace. + +Example service group: + +[`specification/containerservice/resource-manager/Microsoft.ContainerService`] + +which is composed of two services, [`aks`] and [`fleet`]. + +> [!NOTE] +> Previously `service group` was erroneously used in reference to services like `aks`. This is incorrect. + +You can learn more about how a `service group` maps to its directory in the [directory structure article]. + +## Uniform versioning + +See [uniform versioning article]. + +[`aks`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/containerservice/resource-manager/Microsoft.ContainerService/aks +[`fleet`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/containerservice/resource-manager/Microsoft.ContainerService/fleet +[`specification/containerservice/resource-manager/Microsoft.ContainerService/aks`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/containerservice/resource-manager/Microsoft.ContainerService/aks +[`specification/containerservice/resource-manager/Microsoft.ContainerService`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/containerservice/resource-manager/Microsoft.ContainerService +[Azure Kubernetes Service]: https://learn.microsoft.com/en-us/azure/aks/ +[directory structure article]: ./directory-structure.md +[uniform versioning article]: ./uniform-versioning.md diff --git a/documentation/typespec-structure-guidelines.md b/documentation/typespec-structure-guidelines.md index 92ee3450ea70..f7ff9359f922 100644 --- a/documentation/typespec-structure-guidelines.md +++ b/documentation/typespec-structure-guidelines.md @@ -4,9 +4,9 @@ - [Service folder structure](#service-folder-structure) - [Libraries for service groups](#libraries-for-service-groups) - [Specification versioning](#specification-versioning) - - [Organizing services in folders](#organizing-services-in-folders) - - [Utilizing feature branches](#utilizing-feature-branches) - - [Publishing specifications](#publishing-specifications) + - [Organizing services in folders](#organizing-services-in-folders) + - [Utilizing feature branches](#utilizing-feature-branches) + - [Publishing specifications](#publishing-specifications) # Guidelines for TypeSpec project repositories @@ -18,7 +18,7 @@ This document provides guidelines for managing TypeSpec projects for Azure. It o The structure of TypeSpec project repositories starts with the [specification](https://aka.ms/azsdk/spec-dirs) folder, serving as the root for all service specifications. Each child folder, denoted as ``, corresponds to a service specification for a specific Azure team. In more complex scenarios, such as larger teams, the `` folder can host multiple services, forming what is known as a service group. -The `` folder can include multiple ``s, each containing the TypeSpec specification for a given service or service group. +The `` folder can include multiple `` folders, each containing the TypeSpec specification for a given service or service group. A given TypeSpec project folder can represent various scenarios: diff --git a/documentation/uniform-versioning.md b/documentation/uniform-versioning.md new file mode 100644 index 000000000000..923e8c2c0ed4 --- /dev/null +++ b/documentation/uniform-versioning.md @@ -0,0 +1,95 @@ +# Uniform versioning + +> [!NOTE] +> This article uses terminology defined in the [glossary], like `service` or `service group`. + +A `service` **must version uniformly**. + +In brief, it means: + +> The service, its set of operation endpoints (typically HTTP REST API endpoints), its documentation, and any SDK referencing it, all must version in lockstep. +> If a new service API version is released, also a new documentation reference must be released to describe it. +> Similarly, a new version of given SDK package must be released to refer to the new service version. + +Each `service` within a `service group` can version independently of each other. + +## Uniform versioning rules + +All of the rules listed here apply both for OpenAPI specs emitted from TypeSpec as well as for hand-written OpenAPI specs. + +**Uniform versioning** prescribes the following + +1. Any deployed service operation endpoint must belong to an API version. An API version once deployed is immutable. + Its behavior or constituent operations cannot be changed. +2. Any given service API version can be composed only of HTTP API operations and ARM resource types (if applicable) + that have the same API version. +3. Any documentation pertaining to the service and any SDKs generated from the service must pertain to only + one service version. +4. The service version must be always represented in its entirety; any SDK or documentation referring to the service + must encompass all of it. +5. The `common-types` OpenAPI definition shared across multiple services can version independently of the service. + However, the rule that API version is immutable still must be observed. + As such, when versioning `common-types`, previous API versions will remain immutable because new API versions must be created. + +## Uniform versioning implications + +The **uniform versioning** has several implications and implementation decisions supporting it. + +### API versions + +- The service is effectively defined as a series of consecutive API versions. +- Each API version is represented by a pair of folders representing its lifecycle stage and a date, + like `stable/2024-03-05` or `preview/2024-05-15-preview`. +- Each API version date must be later than the previous date. +- `stable` and `preview` API versions cannot have the same date. This would prevent API users from knowing + which one is later one. +- Moving to `stable` from `preview` by removing `-preview` suffix is not allowed. + In such case, at least one day must be added to the `stable` API version. + +### Directory structure + +- The entirety of given API service specification must be placed inside its folder, e.g. `stable/2024-03-05`. + The service consists of operation endpoints defined in OpenAPI spec `.json` files placed in its API version folder. +- Learn more in [directory structure article]. + +### No API version mixing within a service + +- Nowhere within a service, documentation for it, or SDK referencing it, + can multiple service API versions be mixed. as such: + - `preview` API versions cannot be mixed with `stable` API versions. + - No HTTP API endpoint for given API version can have any kind of dependency on service endpoint from any other API version. + - The above apply to a stand-alone service as well as to a service that is a member of a `service group`. + +### API version mixing across services in a service group + +- Each `service` within a `service group` can version independently of each other. +- Each `service` within a `service group` must observe the **uniform versioning rules** within its own scope. + +### AutoRest configuration for SDK generation (`README.md` files) + +- Any [AutoRest config `README.md` file] definition for the service must have tags corresponding to the API versions + present in the directory structure. +- Each of the API version tags must include **all** OpenAPI spec `.json` files for given API version. +- Each of the API version tags must include **only** OpenAPI spec `.json` files for given API version. +- Each `README.md` describes a single `service` and is used as an SDK package and documentation for each version of the service. +- All OpenAPI specs for given `service` API version (i.e. the list of paths in given `input-file:` block for given API version tag in the `README.md`) + must have the same service version, which also means being in the same [API version lifecycle stage]. + +### Versioning of `common-types` + +- All the shared OpenAPI definitions (i.e. `common-types`) the service depends on must have the same version, + [e.g. `v6`][common-types v6], but it can be different from the version of the service. +- Updating `common-types` version requires updating the API version. + For example, if `common-types` published an updated version of `v7`, + then if the service wants to take dependency on it, it can only do it in + a new version. For example, `2024-04-17`. + Because the service version is now `2024-04-17`, all the OpenAPI specification `.json` files the service is composed + of must have the same version of `2024-04-17` and the `info.version` property must say `2024-04-17`. + In addition, a new SDK must be generated from the service, and new documentation published, both tagged with + service version `2024-04-17`. + +[API version lifecycle stage]: https://aka.ms/azsdk/api-versions +[AutoRest config `README.md` file]: https://aka.ms/azsdk/autorest +[common-types v6]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/common-types/resource-management/ +[directory structure article]: ./directory-structure.md +[glossary]: ./glossary.md From 4bc8b832769ee3669e0cf0d2c6c02dece7a498c5 Mon Sep 17 00:00:00 2001 From: Konrad Jamrozik Date: Wed, 5 Jun 2024 15:34:36 -0700 Subject: [PATCH 11/11] Soften guidance --- .markdownlint.jsonc | 7 ++- cSpell.json | 9 +-- documentation/directory-structure.md | 84 +++++++++++++++++----------- documentation/glossary.md | 23 +++++++- 4 files changed, 82 insertions(+), 41 deletions(-) diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc index 98657b7eff01..f4856b9b8949 100644 --- a/.markdownlint.jsonc +++ b/.markdownlint.jsonc @@ -31,5 +31,10 @@ // https://github.com/DavidAnson/markdownlint/blob/main/doc/md034.md // // We allow bare URLs e.g. to link to GitHub issues. - "MD034": false + "MD034": false, + + // MD041 - First line in a file should be a top-level heading + // + // We sometimes use "short link" table as first line. + "MD041": false } diff --git a/cSpell.json b/cSpell.json index 40f978b4ad07..e72217ed3b24 100644 --- a/cSpell.json +++ b/cSpell.json @@ -3,6 +3,7 @@ "language": "en", "words": [ "authnotrequired", + "azsdk", "confidentialledger", "Creds", "fixdate", @@ -1265,10 +1266,10 @@ { "filename": "**/specification/riskiq/data-plane/Microsoft.Easm/preview/2024-03-01-preview/easm.json", "words": [ - "Cisa", - "cisa", - "affected", - "AUTOCONFIRMED" + "Cisa", + "cisa", + "affected", + "AUTOCONFIRMED" ] }, { diff --git a/documentation/directory-structure.md b/documentation/directory-structure.md index 6f0e61258819..d3564b6314b9 100644 --- a/documentation/directory-structure.md +++ b/documentation/directory-structure.md @@ -11,7 +11,7 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one - [`specification` folder](#specification-folder) - [`` folders](#typespecsrc-folders) - [`resource-manager/` folder](#resource-managerrpns-folder) - - [`data-plane/` folders](#data-planenamespace-folders) + - [`data-plane/` folders](#data-planegroupingdir-folders) - [Service folder structure](#service-folder-structure) - [`specification/common-types`](#specificationcommon-types) - [Naming guidelines for `specification` folder contents](#naming-guidelines-for-specification-folder-contents) @@ -23,42 +23,43 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one This article describes the directory structure / folder layout of the `specification` folder. You may be also interested in following: + - [Specification index] - [Resource Provider list] > [!IMPORTANT] -> The structure described in this article is strictly enforced. There exist some exceptions for historical reasons. -> These exceptions are not allowed going forward. +> The structure described in this article is recommended. There exist some exceptions for historical reasons. +> These exceptions are strongly discouraged going forward. ## Key concepts The directory structure is a reflection of a few key concepts. -Familiarize yourself with the concepts of `service`, `service group` and `uniform versioning` +Familiarize yourself with the concepts of `service`, `service group`, `grouping directory` and `uniform versioning` as explained in the [glossary]. ## `specification` folder The `specification` folder is the root folder for all `service` specifications. -Each child of the `specification` folder corresponds to ``. +Each child of the `specification` folder corresponds to ``. All the `service` (see [glossary]) specifications owned by that team are rooted in their `` folder. Given `` folder has following structure: - `/` (multiple `` folders are allowed) - `/resource-manager/` (exactly one `` folder is allowed) -- `/data-plane/` (multiple `` folders are allowed) +- `/data-plane/` (multiple `` folders are allowed) ### `` folders The `/` folders contain the TypeSpec specifications for the services owned by the team. The content of these folders is used as input to emit OpenAPI specifications -placed within `/resource-manager/` and `/data-plane/` folders. +placed within `/resource-manager/` folder and `/data-plane/` folders. > [!NOTE] -> Some services may not have `` folders. In such case, these services OpenAPI specs are hand-written. +> Some services may not have `` folders. In such case, these services OpenAPI specs are hand-written. > This is legacy, deprecated practice and is not allowed going forward. You can find details on the name and contents of `` folders in [TypeSpec directory structure]. @@ -66,31 +67,45 @@ You can learn more about TypeSpec at [aka.ms/azsdk/typespec] and [aka.ms/typespe ### `resource-manager/` folder -The `/resource-manager/` is a folder corresponding to **Resource Provider (RP) namespace**. +The `/resource-manager/` is a folder corresponding to ARM **Resource Provider (RP) namespace**. An example RPNS is `Microsoft.Automation`. A list of RPs can be found in the [Resource Provider list]. This folder corresponds to a `service group` (see [glossary]) for all ARM services owned by the team. -An `` folder has one or more children `` folders corresponding to the services belonging +An `` folder has one or more child `` folders corresponding to the services belonging to the `service group` represented by the `` folder. -For example, [`specification/containerservice/resource-manager/Microsoft.ContainerService/aks`] +For example, [`specification/containerservice/resource-manager/Microsoft.ContainerService/aks`] is a folder for the `aks` service within the `Microsoft.ContainerService` ARM Resource Provider namespace. > [!NOTE] -> Many Azure teams that have one ARM service instead of rooting it in `specification//resource-manager//` root it -> in `specification//resource-manager`. This is legacy, deprecated structure and is not allowed going forward. +> Many Azure teams that have one ARM service instead of rooting it in +> `specification//resource-manager//` root it in +> `specification//resource-manager`. +> This is legacy, deprecated structure and is strongly discouraged going forward. -In addition, the `` folder may contain `common-types` child folder that usually is of form `common-types/v/common.json` and contains types -shared across API versions. E.g. [`Microsoft.Compute/common-types`]. +In addition, the `` folder may contain `common-types` child folder that usually is of +form `common-types/v/common.json` and contains types shared across API versions. +E.g. [`Microsoft.Compute/common-types`]. -### `data-plane/` folders +### `data-plane/` folders -The set of `/data-plane/` folders is the equivalent of `/resource-manager/` but with following distinctions: +The `/data-plane` folder is the equivalent +of `/resource-manager` but with following distinctions: - `/data-plane` pertains to data-plane service APIs, not ARM service APIs. -- `/data-plane/` is a set of one or more folder, not only one. +- `/data-plane` has no concept of Resource Provider Namespace (``). + Instead, it has or more `` child folders (see also [glossary]). + +Each `` folder has one or more child `` folders corresponding to the services grouped +in given ``. + +> [!NOTE] +> Many Azure teams that have one data-plane service instead of rooting it in +> `specification//data-plane//` root it in +> `specification//data-plane`. +> This is legacy, deprecated structure and is strongly discouraged going forward. ## Service folder structure @@ -100,7 +115,7 @@ As described above, ARM service folder path is: while data-plane service folder path is: -`specification//data-plane//`. +`specification//data-plane//`. A service folder has the following elements: @@ -112,20 +127,22 @@ The `stable` and `preview` folders contain OpenAPI specs in the `stable` and `p respectively, organized in `` subfolders for each service API version. For example: + - `/resource-manager///stable/` - `/resource-manager///preview/` -- `/data-plane///stable/` -- `/data-plane///preview/` +- `/data-plane///stable/` +- `/data-plane///preview/` -Each such API version folder directly contains a set of `.json` files containing OpenAPI specs emitted from TypeSpec, as well as an `examples` child folder -with `.json` files having the contents of [`x-ms-examples`] referenced from the OpenAPI specs. +Each such API version folder directly contains a set of `.json` files containing OpenAPI specs emitted from TypeSpec, +as well as an `examples` child folder with `.json` files having the contents of [`x-ms-examples`] referenced +from the OpenAPI specs. Read [API versioning guidelines] to learn more. ## `specification/common-types` -The special directory of [`specification/common-types`] contains shared definitions that can be reused across all Azure team services in their -`specification` child folders. +The special directory of [`specification/common-types`] contains shared definitions that can be reused across all +Azure team services in their `specification` child folders. ## Naming guidelines for `specification` folder contents @@ -139,12 +156,13 @@ The special directory of [`specification/common-types`] contains shared definiti Many teams follow a legacy, deprecated directory structure which usually has following differences: -- If a team owns only one service, instead of rooting it in `specification//resource-manager//`, it is rooted in - `specification//resource-manager`. +- If a team owns only one service, instead of rooting it in `specification//resource-manager//`, + it is rooted in`specification//resource-manager`. - If a team first owned one service and then expanded to a service group, - it contains mixture of both the deprecated structure (for the first service) as well as the correct structure (for the 2nd and following services). + it contains mixture of both the deprecated structure (for the first service) as well as the correct structure + (for the 2nd and following services). -This legacy structure is not allowed going forward. +This legacy structure is strongly discouraged going forward. ## Migrating from a singular service to service group in a legacy directory structure @@ -163,13 +181,14 @@ violate some of the constraints presented in this article. This includes violati - `README.md` placed in a wrong folder (thus incorrectly denoting it as a `service` folder). - Lack of `` directory for given service path. - Incorrect lack of `-preview` suffix in `preview` API versions. +- Multiple `` subfolders of `resource-manager` folder. - Mixing of `stable` and `preview` API versions in the same folder subtree. - Mixing of multiple API versions in given `README.md` package, including mixing of multiple API version lifecycle stages. -In addition, some `` folders have OpenAPI specs that have been written manually instead of emitted from TypeSpec. -In some cases the folders have mixture of manually-written and TypeSpec-emitted OpenAPI specs. +In addition, some `` folders have OpenAPI specs that have been written manually instead of emitted from +TypeSpec. In some cases the folders have mixture of manually-written and TypeSpec-emitted OpenAPI specs. -All of the aforementioned cases are considered legacy & deprecated, and are not allowed going forward. +All of the aforementioned cases are considered legacy & deprecated, and are strongly discouraged going forward. [`Microsoft.Compute/common-types`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/compute/resource-manager/Microsoft.Compute/common-types/ [`specification/common-types`]: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/common-types @@ -180,7 +199,6 @@ All of the aforementioned cases are considered legacy & deprecated, and are not [aka.ms/typespec]: https://aka.ms/typespec [API versioning guidelines]: https://github.com/microsoft/api-guidelines/blob/vNext/azure/Guidelines.md#api-versioning [AutoRest config `README.md` file]: https://aka.ms/azsdk/autorest - [glossary]: ./glossary.md [Resource Provider list]: https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-services-resource-providers#match-resource-provider-to-service [Specification index]: https://azure.github.io/azure-sdk/releases/latest/all/specs.html diff --git a/documentation/glossary.md b/documentation/glossary.md index 2ece593fa2ae..d55bbf11b9ff 100644 --- a/documentation/glossary.md +++ b/documentation/glossary.md @@ -2,13 +2,27 @@ This article defines some of the terms used in the articles under `documentation` directory. +## Grouping directory + +A `grouping directory`, denoted as `` in the [directory structure article], is a root folder for +a set of data-plane `service` folders. It is a subfolder of `data-plane` folder. + +Each `service` in given `grouping directory` must [**version uniformly**][uniform versioning article] but each `service` +within a `grouping directory` can version independently of each other. + +A `grouping directory` can be seen as a more free-form equivalent of the ARM `service group`, but for data-plane services. + +Specifically, all services grouped in given `groping directory` do not share any ARM **Resource Provider (RP) namespace** +and are not related to ARM in any way. + ## Resource type In case of ARM, a `service` is a collection of `resource types` or `resource type groups`. ## Service - -A `service` is a set of operation endpoints (typically HTTP REST API endpoints) that [**version uniformly**][uniform versioning article]. + +A `service` is a set of operation endpoints (typically HTTP REST API endpoints) +that [**version uniformly**][uniform versioning article]. A `service` corresponds to a cohesive, uniformly versioned experience for the customer with HTTP REST API surface, documentation portal and language SDKs. For example, [Azure Kubernetes Service]. @@ -27,7 +41,7 @@ A data-plane service has a path of form: > Some existing services follow different directory structure layouts. > All such layouts are legacy, deprecated, and not allowed going forward. -For example, [`specification/containerservice/resource-manager/Microsoft.ContainerService/aks`] +For example, [`specification/containerservice/resource-manager/Microsoft.ContainerService/aks`] is a folder for the `aks` service within the `Microsoft.ContainerService` ARM Resource Provider namespace. You can learn more about how a `service` maps to its directory in the [directory structure article]. @@ -36,6 +50,9 @@ You can learn more about how a `service` maps to its directory in the [directory A `service group` is a set of services that share a common ARM **Resource Provider (RP) namespace**, `RPNS`. +Each `service` in given `service group` must [**version uniformly**][uniform versioning article] but each `service` +within a `service group` can version independently of each other. + A `service group` has a path of form: `specification//resource-manager/`