Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/src/TemplateRefGenerator/bin/Debug/net9.0/TemplateRefGenerator",
"program": "${workspaceFolder}/src/TemplateRefGenerator/bin/Debug/net10.0/TemplateRefGenerator",
"args": [
"--source-folder",
"../../../bicep-types-az/generated",
Expand All @@ -26,7 +26,7 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/src/TemplateRefGenerator/bin/Debug/net9.0/TemplateRefGenerator",
"program": "${workspaceFolder}/src/TemplateRefGenerator/bin/Debug/net10.0/TemplateRefGenerator",
"args": [
"--source-folder",
"../../../bicep-types-az/generated",
Expand Down
4 changes: 2 additions & 2 deletions docs/dev_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ Run `dotnet build` to build this project.
After building the .NET solution, you can use the CLI by running:

```sh
./src/TemplateRefGenerator/bin/Debug/net9.0/TemplateRefGenerator
./src/TemplateRefGenerator/bin/Debug/net10.0/TemplateRefGenerator
```

If you run this command without supplying any arguments, you will see a help message giving information on the supported arguments.

Here's an example of how you can run the CLI tool:
```sh
src/TemplateRefGenerator/bin/Debug/net9.0/TemplateRefGenerator --source-folder ../bicep-types-az/generated --output-folder ./generated
src/TemplateRefGenerator/bin/Debug/net10.0/TemplateRefGenerator --source-folder ../bicep-types-az/generated --output-folder ./generated
```

To get detailed logging, use the `--verbose` flag.
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
},
"sdk": {
"allowPrerelease": false,
"version": "9.0.309",
"version": "10.0.101",
"rollForward": "latestPatch"
}
}
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<LangVersion>default</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>$(NoWarn);NU5104</NoWarn>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ resource symbolicname 'Microsoft.Addons/supportProviders/supportPlanTypes@2018-0
| Name | Description | Value |
| ---- | ----------- | ------------ |
| name | The resource name | 'Advanced'<br />'Essential'<br />'Standard' (required) |
| parent | In Bicep, you can specify the parent resource for a child resource. You only need to add this property when the child resource is declared outside of the parent resource.<br /><br />For more information, see [Child resource outside parent resource](/azure/azure-resource-manager/bicep/child-resource-name-type#outside-parent-resource). | Symbolic name for resource of type: [supportProviders](~/microsoft.addons/supportproviders.md) |
| parent | In Bicep, you can specify the parent resource for a child resource. You only need to add this property when the child resource is declared outside of the parent resource.<br /><br />For more information, see [Child resource outside parent resource](/azure/azure-resource-manager/bicep/child-resource-name-type#outside-parent-resource). | Symbolic name for resource of type: supportProviders |


::: zone-end
Expand Down Expand Up @@ -105,7 +105,7 @@ resource "azapi_resource" "symbolicname" {
| Name | Description | Value |
| ---- | ----------- | ------------ |
| name | The resource name | 'Advanced'<br />'Essential'<br />'Standard' (required) |
| parent_id | The ID of the resource that is the parent for this resource. | ID for resource of type: [supportProviders](~/microsoft.addons/supportproviders.md) |
| parent_id | The ID of the resource that is the parent for this resource. | ID for resource of type: supportProviders |
| type | The resource type | "Microsoft.Addons/supportProviders/supportPlanTypes@2018-03-01" |


Expand Down
67 changes: 46 additions & 21 deletions src/TemplateRefGenerator/Generators/MarkdownGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ public IReadOnlyDictionary<string, ImmutableArray<string>> GetApiVersionsByType(
.SelectMany(x => x.Value.Select(y => (type: y, version: x.Key)))
.GroupBy(x => x.type, x => x.version, StringComparer.OrdinalIgnoreCase)
.ToDictionary(x => x.Key, x => x.ToImmutableArray(), StringComparer.OrdinalIgnoreCase);

public bool HasType(string resourceType, string apiVersion)
=> ResourceTypeByApiVersion.TryGetValue(apiVersion, out var types)
&& types.Contains(resourceType, StringComparer.OrdinalIgnoreCase);
}

public record GenerateResult(
Expand All @@ -49,7 +53,9 @@ public record ResourceMetadata(
string ResourceType,
string UnqualifiedResourceType,
string ApiVersion,
ResourceType Type);
ResourceType Type,
bool IsChildResource,
bool IsParentTypeAvailable);

public record NamedType(string Name, TypeBase Type);

Expand Down Expand Up @@ -171,7 +177,7 @@ private static string GetResourceRemarks(ResourceMetadata resource, RemarksFile
sb.Append($"""
### Azure Quickstart Samples

The following [Azure Quickstart templates](https://aka.ms/azqst) contain Bicep samples for deploying this resource type.
The following {MarkdownUtils.GetLink("Azure Quickstart templates", "https://aka.ms/azqst")} contain Bicep samples for deploying this resource type.

> [!div class="mx-tableFixed"]
> | Bicep File | Description |
Expand Down Expand Up @@ -209,7 +215,7 @@ private static string GetJsonQuickstartsSection(SamplesFile samples, ResourceMet
sb.Append($"""
### Azure Quickstart Templates

The following [Azure Quickstart templates](https://aka.ms/azqst) deploy this resource type.
The following {MarkdownUtils.GetLink("Azure Quickstart templates", "https://aka.ms/azqst")} deploy this resource type.

> [!div class="mx-tableFixed"]
> | Template | Description |
Expand Down Expand Up @@ -250,7 +256,7 @@ The following [Azure Quickstart templates](https://aka.ms/azqst) deploy this res
sb.Append($"""
### Azure Verified Modules

The following [Azure Verified Modules](https://aka.ms/avm) can be used to deploy this resource type.
The following {MarkdownUtils.GetLink("Azure Verified Modules", "https://aka.ms/avm")} can be used to deploy this resource type.

> [!div class="mx-tableFixed"]
> | Module | Description |
Expand Down Expand Up @@ -288,28 +294,28 @@ private static string GetBicepZone(ConfigLoader configLoader, RemarksLoader rema
if (resource.Type.ScopeType.HasFlag(ScopeType.Tenant))
{
sb.Append($"""
* **Tenant** - See [tenant deployment commands](/azure/azure-resource-manager/bicep/deploy-to-tenant)
* **Tenant** - See {MarkdownUtils.GetLink("tenant deployment commands", "/azure/azure-resource-manager/bicep/deploy-to-tenant")}
""");
}

if (resource.Type.ScopeType.HasFlag(ScopeType.ManagementGroup))
{
sb.Append($"""
* **Management groups** - See [management group deployment commands](/azure/azure-resource-manager/bicep/deploy-to-management-group)
* **Management groups** - See {MarkdownUtils.GetLink("management group deployment commands", "/azure/azure-resource-manager/bicep/deploy-to-management-group")}
""");
}

if (resource.Type.ScopeType.HasFlag(ScopeType.Subscription))
{
sb.Append($"""
* **Subscription** - See [subscription deployment commands](/azure/azure-resource-manager/bicep/deploy-to-subscription)
* **Subscription** - See {MarkdownUtils.GetLink("subscription deployment commands", "/azure/azure-resource-manager/bicep/deploy-to-subscription")}
""");
}

if (resource.Type.ScopeType.HasFlag(ScopeType.ResourceGroup))
{
sb.Append($"""
* **Resource groups** - See [resource group deployment commands](/azure/azure-resource-manager/bicep/deploy-to-resource-group)
* **Resource groups** - See {MarkdownUtils.GetLink("resource group deployment commands", "/azure/azure-resource-manager/bicep/deploy-to-resource-group")}
""");
}

Expand All @@ -318,7 +324,7 @@ private static string GetBicepZone(ConfigLoader configLoader, RemarksLoader rema
sb.Append($"""


For a list of changed properties in each API version, see [change log](~/{resource.Provider.ToLowerInvariant()}/change-log/{resource.UnqualifiedResourceType.ToLowerInvariant()}.md).
For a list of changed properties in each API version, see {MarkdownUtils.GetLink("change log", $"~/{resource.Provider.ToLowerInvariant()}/change-log/{resource.UnqualifiedResourceType.ToLowerInvariant()}.md")}.

## Resource format

Expand Down Expand Up @@ -417,28 +423,28 @@ private static string GetArmTemplateZone(ConfigLoader configLoader, ResourceMeta
if (resource.Type.ScopeType.HasFlag(ScopeType.Tenant))
{
sb.Append($"""
* **Tenant** - See [tenant deployment commands](/azure/azure-resource-manager/templates/deploy-to-tenant)
* **Tenant** - See {MarkdownUtils.GetLink("tenant deployment commands", "/azure/azure-resource-manager/templates/deploy-to-tenant")}
""");
}

if (resource.Type.ScopeType.HasFlag(ScopeType.ManagementGroup))
{
sb.Append($"""
* **Management groups** - See [management group deployment commands](/azure/azure-resource-manager/templates/deploy-to-management-group)
* **Management groups** - See {MarkdownUtils.GetLink("management group deployment commands", "/azure/azure-resource-manager/templates/deploy-to-management-group")}
""");
}

if (resource.Type.ScopeType.HasFlag(ScopeType.Subscription))
{
sb.Append($"""
* **Subscription** - See [subscription deployment commands](/azure/azure-resource-manager/templates/deploy-to-subscription)
* **Subscription** - See {MarkdownUtils.GetLink("subscription deployment commands", "/azure/azure-resource-manager/templates/deploy-to-subscription")}
""");
}

if (resource.Type.ScopeType.HasFlag(ScopeType.ResourceGroup))
{
sb.Append($"""
* **Resource groups** - See [resource group deployment commands](/azure/azure-resource-manager/templates/deploy-to-resource-group)
* **Resource groups** - See {MarkdownUtils.GetLink("resource group deployment commands", "/azure/azure-resource-manager/templates/deploy-to-resource-group")}
""");
}

Expand All @@ -447,7 +453,7 @@ private static string GetArmTemplateZone(ConfigLoader configLoader, ResourceMeta
sb.Append($"""


For a list of changed properties in each API version, see [change log](~/{resource.Provider.ToLowerInvariant()}/change-log/{resource.UnqualifiedResourceType.ToLowerInvariant()}.md).
For a list of changed properties in each API version, see {MarkdownUtils.GetLink("change log", $"~/{resource.Provider.ToLowerInvariant()}/change-log/{resource.UnqualifiedResourceType.ToLowerInvariant()}.md")}.

## Resource format

Expand Down Expand Up @@ -548,7 +554,7 @@ private static string GetTerraformZone(ConfigLoader configLoader, RemarksLoader
sb.Append($"""


For a list of changed properties in each API version, see [change log](~/{resource.Provider.ToLowerInvariant()}/change-log/{resource.UnqualifiedResourceType.ToLowerInvariant()}.md).
For a list of changed properties in each API version, see {MarkdownUtils.GetLink("change log", $"~/{resource.Provider.ToLowerInvariant()}/change-log/{resource.UnqualifiedResourceType.ToLowerInvariant()}.md")}.

## Resource format

Expand Down Expand Up @@ -855,16 +861,16 @@ private static IEnumerable<PropertyData> GetProperties(

yield return new(
"parent",
$"In Bicep, you can specify the parent resource for a child resource. You only need to add this property when the child resource is declared outside of the parent resource.{Br}{Br}For more information, see [Child resource outside parent resource](/azure/azure-resource-manager/bicep/child-resource-name-type#outside-parent-resource).",
$"Symbolic name for resource of type: [{parentTypeUnqualified}](~/{parentType.ToLowerInvariant()}.md)");
$"In Bicep, you can specify the parent resource for a child resource. You only need to add this property when the child resource is declared outside of the parent resource.{Br}{Br}For more information, see {MarkdownUtils.GetLink("Child resource outside parent resource", "/azure/azure-resource-manager/bicep/child-resource-name-type#outside-parent-resource")}.",
$"Symbolic name for resource of type: {GetParentResourceNameWithOptionalLink(resource)}");
}
else if (resource.Type.ScopeType == ScopeType.Unknown ||
resource.Type.ScopeType.HasFlag(ScopeType.Extension))
{
yield return new(
"scope",
"Use when creating a resource at a scope that is different than the deployment scope.",
"Set this property to the symbolic name of a resource to apply the [extension resource](/azure/azure-resource-manager/bicep/scope-extension-resources).");
$"Set this property to the symbolic name of a resource to apply the {MarkdownUtils.GetLink("extension resource", "/azure/azure-resource-manager/bicep/scope-extension-resources")}.");
}
break;
case DeploymentType.Terraform:
Expand All @@ -876,7 +882,7 @@ private static IEnumerable<PropertyData> GetProperties(
yield return new(
"parent_id",
$"The ID of the resource that is the parent for this resource.",
$"ID for resource of type: [{parentTypeUnqualified}](~/{parentType.ToLowerInvariant()}.md)");
$"ID for resource of type: {GetParentResourceNameWithOptionalLink(resource)}");
}
else if (resource.Type.ScopeType == ScopeType.Unknown ||
resource.Type.ScopeType.HasFlag(ScopeType.Extension))
Expand Down Expand Up @@ -910,7 +916,7 @@ private static IEnumerable<PropertyData> GetProperties(
if (isResourceType && propName == "tags")
{
var tagsType = deploymentType != DeploymentType.Terraform ?
"Dictionary of tag names and values. See [Tags in templates](/azure/azure-resource-manager/management/tag-resources#arm-templates)" :
$"Dictionary of tag names and values. See {MarkdownUtils.GetLink("Tags in templates", "/azure/azure-resource-manager/management/tag-resources#arm-templates")}" :
"Dictionary of tag names and values.";

yield return new(
Expand Down Expand Up @@ -1016,13 +1022,17 @@ public static string GenerateMarkdown(GroupedTypes groupedTypes, ResourceType re
var apiVersion = resourceType.Name.Split('@')[1];
var providerNamespace = Utils.GetProviderNamespace(resourceTypeName);
var unqualifiedResourceType = Utils.GetUnqualifiedType(resourceTypeName);
var isChildResource = Utils.IsChildResource(unqualifiedResourceType);
var isParentTypeAvailable = isChildResource && groupedTypes.HasType(Utils.GetParentResource(resourceTypeName), apiVersion);

var resource = new ResourceMetadata(
Provider: providerNamespace,
ResourceType: resourceTypeName,
UnqualifiedResourceType: unqualifiedResourceType,
ApiVersion: apiVersion,
Type: resourceType);
Type: resourceType,
IsChildResource: isChildResource,
IsParentTypeAvailable: isParentTypeAvailable);

var namedTypes = GetNamedTypes(resource);
var remarks = remarksLoader.GetRemarks(providerNamespace);
Expand All @@ -1039,4 +1049,19 @@ public static string GenerateMarkdown(GroupedTypes groupedTypes, ResourceType re
{GetTerraformZone(configLoader, remarksLoader, resource, namedTypes, remarks, 2)}
""";
}

private static string GetParentResourceNameWithOptionalLink(ResourceMetadata resource)
{
if (!resource.IsChildResource)
{
throw new InvalidOperationException($"Resource {resource.ResourceType} is not a child resource");
}

var parentType = Utils.GetParentResource(resource.ResourceType);
var parentTypeUnqualified = Utils.GetParentResource(resource.UnqualifiedResourceType);

return resource.IsParentTypeAvailable ?
MarkdownUtils.GetLink(parentTypeUnqualified, $"~/{parentType.ToLowerInvariant()}.md") :
parentTypeUnqualified;
}
}