Skip to content

Commit 1fc4747

Browse files
authored
Automatically detect templates in a scan path #85 (#88)
1 parent 63938fd commit 1fc4747

10 files changed

Lines changed: 115 additions & 40 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
## Unreleased
44

5+
What's changed since v0.3.0:
6+
7+
- New Features:
8+
- Automatically detect templates in a scan path. [#85](https://github.com/Azure/PSDocs.Azure/issues/85)
9+
- To scan templates use `Invoke-PSDocument` with `-InputPath`.
10+
511
## v0.3.0
612

713
What's changed since v0.2.0:

pipeline.build.ps1

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,19 +155,19 @@ task PSScriptAnalyzer NuGet, {
155155

156156
# Synopsis: Install PSRule
157157
task PSRule NuGet, {
158-
if ($Null -eq (Get-InstalledModule -Name PSRule -MinimumVersion 1.0.3 -ErrorAction Ignore)) {
159-
Install-Module -Name PSRule -Repository PSGallery -MinimumVersion 1.0.3 -Scope CurrentUser -Force;
158+
if ($Null -eq (Get-InstalledModule -Name PSRule -MinimumVersion 1.4.0 -ErrorAction Ignore)) {
159+
Install-Module -Name PSRule -Repository PSGallery -MinimumVersion 1.4.0 -Scope CurrentUser -Force;
160160
}
161-
if ($Null -eq (Get-InstalledModule -Name PSRule.Rules.MSFT.OSS -MinimumVersion '0.1.0-B2012007' -AllowPrerelease -ErrorAction Ignore)) {
162-
Install-Module -Name PSRule.Rules.MSFT.OSS -Repository PSGallery -MinimumVersion '0.1.0-B2012007' -AllowPrerelease -Scope CurrentUser -Force;
161+
if ($Null -eq (Get-InstalledModule -Name PSRule.Rules.MSFT.OSS -MinimumVersion 0.1.0 -AllowPrerelease -ErrorAction Ignore)) {
162+
Install-Module -Name PSRule.Rules.MSFT.OSS -Repository PSGallery -MinimumVersion 0.1.0 -AllowPrerelease -Scope CurrentUser -Force;
163163
}
164164
Import-Module -Name PSRule.Rules.MSFT.OSS -Verbose:$False;
165165
}
166166

167167
# Synopsis: Install PSDocs
168168
task PSDocs NuGet, {
169-
if ($Null -eq (Get-InstalledModule -Name PSDocs -MinimumVersion 0.8.0 -ErrorAction Ignore)) {
170-
Install-Module -Name PSDocs -Repository PSGallery -MinimumVersion 0.8.0 -Scope CurrentUser -Force;
169+
if ($Null -eq (Get-InstalledModule -Name PSDocs -MinimumVersion '0.9.0-B2107020' -AllowPrerelease -ErrorAction Ignore)) {
170+
Install-Module -Name PSDocs -Repository PSGallery -MinimumVersion '0.9.0-B2107020' -AllowPrerelease -Scope CurrentUser -Force;
171171
}
172172
Import-Module -Name PSDocs -Verbose:$False;
173173
}
@@ -278,7 +278,7 @@ task UpdateTemplateDocs Build, {
278278
# Scan for Azure template file recursively in the templates/ directory
279279
Get-AzDocTemplateFile -Path templates/ | ForEach-Object {
280280
$template = Get-Item -Path $_.TemplateFile;
281-
Invoke-PSDocument -Module PSDocs.Azure -OutputPath $template.Directory.FullName -InputObject $template.FullName;
281+
Invoke-PSDocument -Module PSDocs.Azure -OutputPath $template.Directory.FullName -InputPath $template.FullName;
282282
}
283283
}
284284

src/PSDocs.Azure/docs/Azure.Conventions.Doc.ps1

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33

44
# Synopsis: Name documents by parent path.
55
Export-PSDocumentConvention 'Azure.NameByParentPath' {
6-
$template = Get-Item -Path $PSDocs.TargetObject;
6+
if ($PSDocs.TargetObject -is [String]) {
7+
$template = Get-Item -Path $PSDocs.TargetObject;
8+
}
9+
else {
10+
$template = Get-Item -Path $PSDocs.Source.FullName;
11+
}
712

813
# Get parent directory paths where <name>/v<version>/template.json
914
$version = $template.Directory.Name;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# Licensed under the MIT License.
3+
4+
---
5+
# Synopsis: Selector Azure templates based on $schema.
6+
apiVersion: github.com/microsoft/PSDocs/v1
7+
kind: Selector
8+
metadata:
9+
name: Azure.TemplateSchema
10+
spec:
11+
if:
12+
anyOf:
13+
- field: $schema
14+
match: 'http(s)?\:\/\/schema\.management\.azure\.com\/schemas\/.*deploymentTemplate\.json(#)?'
15+
- field: '.'
16+
isString: true

src/PSDocs.Azure/docs/Azure.Template.Doc.ps1

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@
99
function global:GetTemplateParameter {
1010
[CmdletBinding()]
1111
param (
12-
[Parameter(Mandatory = $True)]
13-
[String]$Path
12+
[Parameter(Mandatory = $True, ValueFromPipeline = $True)]
13+
[PSObject]$InputObject
1414
)
1515
process {
16-
$template = Get-Content -Path $Path -Raw | ConvertFrom-Json;
17-
foreach ($property in $template.parameters.PSObject.Properties) {
16+
foreach ($property in $InputObject.parameters.PSObject.Properties) {
1817
$result = [PSCustomObject]@{
1918
Name = $property.Name
2019
Description = ''
@@ -27,7 +26,7 @@ function global:GetTemplateParameter {
2726
}
2827
if ([bool]$property.Value.PSObject.Properties['defaultValue']) {
2928
$result.DefaultValue = $property.Value.defaultValue;
30-
$result.Required = "Optional"
29+
$result.Required = 'Optional'
3130
}
3231
if ([bool]$property.Value.PSObject.Properties['allowedValues']) {
3332
$result.AllowedValues = $property.Value.allowedValues;
@@ -49,7 +48,8 @@ function global:GetTemplateExample {
4948
$Path = Join-Path -Path $PWD -ChildPath $Path;
5049
}
5150
$template = Get-Content -Path $Path -Raw | ConvertFrom-Json;
52-
$normalPath = GetTemplateRelativePath -Path $Path;
51+
# $normalPath = GetTemplateRelativePath -Path $Path;
52+
$normalPath = $PSDocs.Source.Path;
5353
$baseContent = [PSCustomObject]@{
5454
'$schema'= "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json`#"
5555
contentVersion = '1.0.0.0'
@@ -133,16 +133,18 @@ function global:GetTemplateMetadata {
133133
[CmdletBinding()]
134134
[OutputType([Hashtable])]
135135
param (
136+
[Parameter(Mandatory = $True, ValueFromPipeline = $True)]
137+
[PSObject]$InputObject,
138+
136139
[Parameter(Mandatory = $True)]
137140
[String]$Path
138141
)
139142
process {
140143
$metadata = @{};
141144

142145
# Get metadata from template file
143-
$template = Get-Content -Path $Path -Raw | ConvertFrom-Json;
144-
if ([bool]$template.PSObject.Properties['metadata']) {
145-
foreach ($property in $template.metadata.PSObject.Properties.GetEnumerator()) {
146+
if ([bool]$InputObject.PSObject.Properties['metadata']) {
147+
foreach ($property in $InputObject.metadata.PSObject.Properties.GetEnumerator()) {
146148
$metadata[$property.Name] = $property.Value;
147149
}
148150
}
@@ -175,12 +177,11 @@ function global:GetTemplateMetadata {
175177
function global:GetTemplateOutput {
176178
[CmdletBinding()]
177179
param (
178-
[Parameter(Mandatory = $True)]
179-
[String]$Path
180+
[Parameter(Mandatory = $True, ValueFromPipeline = $True)]
181+
[PSObject]$InputObject
180182
)
181183
process {
182-
$template = Get-Content -Path $Path -Raw | ConvertFrom-Json;
183-
foreach ($property in $template.outputs.PSObject.Properties) {
184+
foreach ($property in $InputObject.outputs.PSObject.Properties) {
184185
$output = [PSCustomObject]@{
185186
Name = $property.Name
186187
Type = $property.Value.type
@@ -195,13 +196,26 @@ function global:GetTemplateOutput {
195196
}
196197

197198
# Synopsis: A definition to generate markdown for an ARM template
198-
Document 'README' {
199+
Document 'README' -With 'Azure.TemplateSchema' {
200+
201+
$templatePath = $PSDocs.Source.FullName;
202+
$template = $PSDocs.TargetObject;
203+
if ($PSDocs.TargetObject -is [String]) {
204+
$templatePath = (Get-Item -Path $PSDocs.TargetObject).FullName;
205+
$template = Get-Content -Path $templatePath -Raw | ConvertFrom-Json;
206+
$relativePath = (Split-Path (GetTemplateRelativePath -Path $templatePath) -Parent).Replace('\', '/').TrimStart('/');
207+
}
208+
else {
209+
$relativePath = Split-Path -Path $PSDocs.Source.Path -Parent;
210+
}
211+
212+
Write-Verbose -Message "Reading from template: $templatePath"
213+
Write-Verbose -Message "Reading from template: $relativePath"
199214

200215
# Read JSON files
201-
$templatePath = $InputObject;
202-
$parameters = GetTemplateParameter -Path $templatePath;
203-
$metadata = GetTemplateMetadata -Path $templatePath;
204-
$outputs = GetTemplateOutput -Path $templatePath;
216+
$parameters = $template | GetTemplateParameter;
217+
$metadata = $template | GetTemplateMetadata -Path $templatePath;
218+
$outputs = $template | GetTemplateOutput;
205219

206220
# Set document title
207221
if ($Null -ne $metadata -and $metadata.ContainsKey('name')) {
@@ -217,15 +231,14 @@ Document 'README' {
217231
}
218232

219233
# Add badges
220-
$relativePath = (Split-Path (GetTemplateRelativePath -Path $templatePath) -Parent).Replace('\', '/').TrimStart('/');
221234
$relativePathEncoded = [System.Web.HttpUtility]::UrlEncode($relativePath);
222235
Include '.ps-docs/azure-template-badges.md' -ErrorAction SilentlyContinue -BaseDirectory $PWD -Replace @{
223236
'{{ template_path }}' = $relativePath
224237
'{{ template_path_encoded }}' = $relativePathEncoded
225238
}
226239

227-
Write-Verbose $relativePath
228-
Write-Verbose $relativePathEncoded
240+
# Write-Verbose $relativePath
241+
# Write-Verbose $relativePathEncoded
229242

230243
# Add detailed description
231244
if ($Null -ne $metadata -and $metadata.ContainsKey('description')) {
@@ -234,24 +247,24 @@ Document 'README' {
234247

235248
# Add table and detail for each parameter
236249
Section $LocalizedData.Parameters {
237-
$parameters | Table -Property @{ Name = $LocalizedData.ParameterName; Expression = { $_.Name }},
238-
@{ Name = $LocalizedData.Required; Expression = {
250+
$parameters | Table -Property @{ Name = $LocalizedData.ParameterName; Expression = { $_.Name }},
251+
@{ Name = $LocalizedData.Required; Expression = {
239252
if($_.Required) {
240253
$LocalizedData.RequiredNo
241-
}
254+
}
242255
else {
243256
$LocalizedData.RequiredYes
244-
}
257+
}
245258
}
246-
},
259+
},
247260
@{ Name = $LocalizedData.Description; Expression = { $_.Description }}
248261

249262
foreach ($parameter in $parameters) {
250263
Section $parameter.Name {
251264
if($parameter.Required){
252265
"![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square)"
253266
}
254-
else{ "![Parameter Setting](https://img.shields.io/badge/parameter-required-orange?style=flat-square)" }
267+
else { "![Parameter Setting](https://img.shields.io/badge/parameter-required-orange?style=flat-square)" }
255268
$parameter.Description;
256269

257270
if (![String]::IsNullOrEmpty($parameter.DefaultValue)) {

templates/keyvault/v1/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ Determine if purge protection is enabled on this Key Vault.
8686

8787
The network firewall defined for this vault.
8888

89-
- Default value: `@{defaultAction=Allow; bypass=AzureServices; ipRules=System.Object[]; virtualNetworkRules=System.Object[]}`
89+
- Default value: `@{defaultAction=Allow; bypass=AzureServices; ipRules=System.Management.Automation.PSObject[]; virtualNetworkRules=System.Management.Automation.PSObject[]}`
9090

9191
### workspaceId
9292

tests/PSDocs.Azure.Tests/Azure.Common.Tests.ps1

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,23 @@ Describe 'PSDocs' -Tag 'PSDocs', 'Common' {
5252
$result | Should -Not -BeNullOrEmpty;
5353
}
5454

55+
It 'With -InputPath' {
56+
$invokeParams = @{
57+
Module = 'PSDocs.Azure'
58+
OutputPath = $outputPath
59+
InputPath = 'tests/PSDocs.Azure.Tests/basic.template.json'
60+
}
61+
$result = Invoke-PSDocument @invokeParams;
62+
$result | Should -Not -BeNullOrEmpty;
63+
}
64+
5565
It 'With relative path' {
5666
Push-Location -Path (Join-Path -Path $rootPath -ChildPath 'templates/storage/v1/');
5767
try {
5868
$invokeParams = @{
5969
Module = 'PSDocs.Azure'
6070
OutputPath = $outputPath
61-
InputObject = './template.json'
71+
InputPath = './template.json'
6272
Option = @{ 'Output.Culture' = 'en-US' }
6373
}
6474
$result = Invoke-PSDocument @invokeParams;

tests/PSDocs.Azure.Tests/Azure.Conventions.Tests.ps1

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ $Null = New-Item -Path $outputPath -ItemType Directory -Force;
2424

2525
Describe 'Conventions' -Tag 'Conventions' {
2626
Context 'Azure.NameByParentPath' {
27-
It 'Uses naming convention' {
27+
It 'With -InputObject' {
2828
$invokeParams = @{
2929
Module = 'PSDocs.Azure'
3030
}
@@ -54,5 +54,30 @@ Describe 'Conventions' -Tag 'Conventions' {
5454
$result[0].Name | Should -BeLike 'template-test.md';
5555
$result;
5656
}
57+
58+
It 'With -InputPath' {
59+
$invokeParams = @{
60+
Module = 'PSDocs.Azure'
61+
}
62+
63+
# Generates templates
64+
$templatePath = Join-Path -Path $rootPath -ChildPath 'templates/';
65+
$result = Invoke-PSDocument @invokeParams -OutputPath $outputPath -InputPath $templatePath -Convention 'Azure.NameByParentPath'
66+
$result | Should -Not -BeNullOrEmpty;
67+
$filteredResult = $result | Where-Object { $_.Name -like 'acr_*' };
68+
$filteredResult.Name | Should -BeLike 'acr_v1.md';
69+
$filteredResult = $result | Where-Object { $_.Name -like 'keyvault_*' };
70+
$filteredResult.Name | Should -BeLike 'keyvault_v1.md';
71+
$filteredResult = $result | Where-Object { $_.Name -like 'storage_*' };
72+
$filteredResult.Name | Should -BeLike 'storage_v1.md';
73+
$result;
74+
75+
# Generates templates without version path
76+
$templatePath = Join-Path -Path $here -ChildPath 'template-test/';
77+
$result = Invoke-PSDocument @invokeParams -OutputPath $outputPath -InputPath $templatePath -Convention 'Azure.NameByParentPath'
78+
$result | Should -Not -BeNullOrEmpty;
79+
$result[0].Name | Should -BeLike 'template-test.md';
80+
$result;
81+
}
5782
}
5883
}

tests/PSDocs.Azure.Tests/Azure.QuickStart.Tests.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Describe 'Templates' -Tag 'QuickStart' {
3636
# Generates templates
3737
$result = Get-AzDocTemplateFile -Path $templatePath | ForEach-Object {
3838
$template = Get-Item -Path $_.TemplateFile;
39-
$actualContent = Invoke-PSDocument @invokeParams -OutputPath $outputPath -InputObject $template.FullName -PassThru;
39+
$actualContent = Invoke-PSDocument @invokeParams -OutputPath $outputPath -InputPath $template.FullName -PassThru;
4040
$actualContent | Should -BeLike '*!`[Azure Public Test Date`](https://azurequickstartsservice.blob.core.windows.net/badges/template-test/PublicLastTestDate.svg)*';
4141
$actualContent | Should -BeLike "`# Storage Account*";
4242
$actualContent | Should -BeLike "*Create an empty Storage Account.*";

tests/PSDocs.Azure.Tests/Azure.Templates.Tests.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Describe 'Templates' -Tag 'Template' {
3535
$template = Get-Item -Path $_.TemplateFile;
3636
$parentPath = $template.Directory.FullName;
3737
$expectedContent = Get-Content -Path (Join-Path -Path $parentPath -ChildPath 'README.md') -Raw;
38-
$actualContent = Invoke-PSDocument @invokeParams -OutputPath $outputPath -InputObject $template.FullName -PassThru;
38+
$actualContent = Invoke-PSDocument @invokeParams -OutputPath $outputPath -InputPath $template.FullName -PassThru;
3939
$actualContent | Should -BeExactly $expectedContent;
4040
$actualContent;
4141
}

0 commit comments

Comments
 (0)