Skip to content

Commit 4f9b5d2

Browse files
authored
Outputs are added to generated document #28 (#36)
* Outputs are added to generated document #28 * Additional logical improvements
1 parent c065214 commit 4f9b5d2

10 files changed

Lines changed: 404 additions & 17 deletions

File tree

.vscode/tasks.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@
3939
"detail": "Clean output directories.",
4040
"command": "Invoke-Build Clean",
4141
"problemMatcher": []
42+
},
43+
{
44+
"label": "Update template docs",
45+
"detail": "Generate template markdown docs.",
46+
"type": "shell",
47+
"command": "Invoke-Build UpdateTemplateDocs",
48+
"problemMatcher": [],
49+
"presentation": {
50+
"clear": true,
51+
"panel": "dedicated"
52+
}
4253
}
4354
]
4455
}

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44

55
What's changed since v0.1.0:
66

7+
- New features:
8+
- Template outputs are added to generated document. [#28](https://github.com/Azure/PSDocs.Azure/issues/28)
79
- Bug fixes:
810
- Fixed snippet with short relative template causes exception. [#26](https://github.com/Azure/PSDocs.Azure/issues/26)
11+
- Fixed cannot bind argument when metadata name is not set. [#35](https://github.com/Azure/PSDocs.Azure/issues/35)
912

1013
## v0.1.0
1114

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,16 @@ For example:
8282
}
8383
},
8484
"resources": [
85-
]
85+
],
86+
"outputs": {
87+
"resourceId": {
88+
"type": "string",
89+
"value": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
90+
"metadata": {
91+
"description": "A unique resource identifier for the storage account."
92+
}
93+
}
94+
}
8695
}
8796
```
8897

@@ -108,6 +117,7 @@ Field | Scope | Type | Description
108117
`description` | Parameter | `string` | Used as the description for the parameter.
109118
`example` | Parameter | `string`, `boolean`, `object`, or `array` | An example use of the parameter. The example is included in the JSON snippet. If an example is not included the default value is used instead.
110119
`ignore` | Parameter | `boolean` | When `true` the parameter is not included in the JSON snippet.
120+
`description` | Output | `string` | Used as the description for the output.
111121

112122
An example of an Azure Storage Account template with metadata included is available [here](templates/storage/v1/template.json).
113123

pipeline.build.ps1

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,16 @@ task TestModule ModuleDependencies, Pester, PSScriptAnalyzer, {
272272
}
273273
}
274274

275+
task UpdateTemplateDocs Build, {
276+
Import-Module (Join-Path -Path $PWD -ChildPath 'out/modules/PSDocs.Azure')
277+
278+
# Scan for Azure template file recursively in the templates/ directory
279+
Get-AzDocTemplateFile -Path templates/ | ForEach-Object {
280+
$template = Get-Item -Path $_.TemplateFile;
281+
Invoke-PSDocument -Module PSDocs.Azure -OutputPath $template.Directory.FullName -InputObject $template.FullName;
282+
}
283+
}
284+
275285
# Synopsis: Run script analyzer
276286
task Analyze Build, PSScriptAnalyzer, {
277287
Invoke-ScriptAnalyzer -Path out/modules/PSDocs.Azure;

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

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,22 @@ function global:GetTemplateParameter {
1515
process {
1616
$template = Get-Content -Path $Path -Raw | ConvertFrom-Json;
1717
foreach ($property in $template.parameters.PSObject.Properties) {
18-
[PSCustomObject]@{
18+
$result = [PSCustomObject]@{
1919
Name = $property.Name
20-
Description = $property.Value.metadata.description
21-
DefaultValue = $property.Value.defaultValue
22-
AllowedValues = $property.Value.allowedValues
20+
Description = ''
21+
DefaultValue = $Null
22+
AllowedValues = $Null
2323
}
24+
if ([bool]$property.Value.PSObject.Properties['metadata'] -and [bool]$property.Value.metadata.PSObject.Properties['description']) {
25+
$result.Description = $property.Value.metadata.description;
26+
}
27+
if ([bool]$property.Value.PSObject.Properties['defaultValue']) {
28+
$result.DefaultValue = $property.Value.defaultValue;
29+
}
30+
if ([bool]$property.Value.PSObject.Properties['allowedValues']) {
31+
$result.AllowedValues = $property.Value.allowedValues;
32+
}
33+
$result;
2434
}
2535
}
2636
}
@@ -52,8 +62,9 @@ function global:GetTemplateExample {
5262
}
5363
foreach ($property in $template.parameters.PSObject.Properties) {
5464
$propertyValue = $Null;
65+
$hasMetadata = [bool]$property.Value.PSObject.Properties['metadata'];
5566

56-
if ($True -eq $property.Value.metadata.ignore) {
67+
if ($hasMetadata -and [bool]$property.Value.metadata.PSObject.Properties['ignore'] -and $True -eq $property.Value.metadata.ignore) {
5768
continue;
5869
}
5970

@@ -70,10 +81,10 @@ function global:GetTemplateExample {
7081
continue;
7182
}
7283

73-
if ($Null -ne $property.Value.metadata.example) {
84+
if ($hasMetadata -and [bool]$property.Value.metadata.PSObject.Properties['example'] -and $Null -ne $property.Value.metadata.example) {
7485
$propertyValue = $property.Value.metadata.example;
7586
}
76-
elseif ($Null -ne $property.Value.defaultValue) {
87+
elseif ([bool]$property.Value.PSObject.Properties['defaultValue'] -and $Null -ne $property.Value.defaultValue) {
7788
$propertyValue = $property.Value.defaultValue;
7889
}
7990
elseif ($property.Value.type -eq 'array') {
@@ -106,7 +117,33 @@ function global:GetTemplateMetadata {
106117
[String]$Path
107118
)
108119
process {
109-
return (Get-Content -Path $Path -Raw | ConvertFrom-Json).metadata;
120+
$template = Get-Content -Path $Path -Raw | ConvertFrom-Json;
121+
if ([bool]$template.PSObject.Properties['metadata']) {
122+
return $template.metadata;
123+
}
124+
}
125+
}
126+
127+
# A function to import outputs
128+
function global:GetTemplateOutput {
129+
[CmdletBinding()]
130+
param (
131+
[Parameter(Mandatory = $True)]
132+
[String]$Path
133+
)
134+
process {
135+
$template = Get-Content -Path $Path -Raw | ConvertFrom-Json;
136+
foreach ($property in $template.outputs.PSObject.Properties) {
137+
$output = [PSCustomObject]@{
138+
Name = $property.Name
139+
Type = $property.Value.type
140+
Description = ''
141+
}
142+
if ([bool]$property.Value.PSObject.Properties['metadata'] -and [bool]$property.Value.metadata.PSObject.Properties['description']) {
143+
$output.Description = $property.Value.metadata.description
144+
}
145+
$output;
146+
}
110147
}
111148
}
112149

@@ -117,16 +154,25 @@ Document 'README' {
117154
$templatePath = $InputObject;
118155
$parameters = GetTemplateParameter -Path $templatePath;
119156
$metadata = GetTemplateMetadata -Path $templatePath;
157+
$outputs = GetTemplateOutput -Path $templatePath;
120158

121159
# Set document title
122-
Title $metadata.name
160+
if ($Null -ne $metadata -and [bool]$metadata.PSObject.Properties['name']) {
161+
Title $metadata.name
162+
}
163+
else {
164+
Title $LocalizedData.DefaultTitle
165+
}
123166

124167
# Write opening line
125-
$metadata.Description
168+
if ($Null -ne $metadata -and [bool]$metadata.PSObject.Properties['description']) {
169+
$metadata.description
170+
}
126171

127-
# Add each parameter to a table
172+
# Add table and detail for each parameter
128173
Section $LocalizedData.Parameters {
129-
$parameters | Table -Property @{ Name = $LocalizedData.ParameterName; Expression = { $_.Name }}, $LocalizedData.Description
174+
$parameters | Table -Property @{ Name = $LocalizedData.ParameterName; Expression = { $_.Name }},
175+
@{ Name = $LocalizedData.Description; Expression = { $_.Description }}
130176

131177
foreach ($parameter in $parameters) {
132178
Section $parameter.Name {
@@ -145,6 +191,14 @@ Document 'README' {
145191
}
146192
}
147193

194+
# Add table for outputs
195+
Section $LocalizedData.Outputs {
196+
$outputs | Table -Property @{ Name = $LocalizedData.Name; Expression = { $_.Name }},
197+
@{ Name = $LocalizedData.Type; Expression = { $_.Type }},
198+
@{ Name = $LocalizedData.Description; Expression = { $_.Description }}
199+
}
200+
201+
# Insert snippet
148202
$example = GetTemplateExample -Path $templatePath;
149203
Section $LocalizedData.Snippets {
150204
$example | Code 'json'

src/PSDocs.Azure/en/PSDocs-strings.psd1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
@{
55
Parameters = 'Parameters'
66
Snippets = 'Snippets'
7+
Outputs = 'Outputs'
78
DefaultValue = "- Default value: {0}"
89
AllowedValues = "- Allowed values: {0}"
910
ParameterName = 'Parameter name'
1011
Description = 'Description'
12+
Type = 'Type'
13+
Name = 'Name'
14+
DefaultTitle = 'Azure template'
1115
}

templates/storage/v1/README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Parameter name | Description
88
-------------- | -----------
99
storageAccountName | Required. The name of the Storage Account.
1010
location | Optional. The Azure region to deploy to.
11-
sku | Optional. Crease the Storage Account as LRS or GRS.
11+
sku | Optional. Create the Storage Account as LRS or GRS.
1212
suffixLength | Optional. Determine how many additional characters are added to the storage account name as a suffix.
1313
containers | Optional. An array of storage containers to create on the storage account.
1414
lifecycleRules | Optional. An array of lifecycle management policies for the storage account.
@@ -33,7 +33,7 @@ Optional. The Azure region to deploy to.
3333

3434
### sku
3535

36-
Optional. Crease the Storage Account as LRS or GRS.
36+
Optional. Create the Storage Account as LRS or GRS.
3737

3838
- Default value: `Standard_LRS`
3939

@@ -95,6 +95,13 @@ Optional. Set to the objectId of Azure Key Vault to delegated permission for use
9595

9696
Optional. Tags to apply to the resource.
9797

98+
## Outputs
99+
100+
Name | Type | Description
101+
---- | ---- | -----------
102+
blobEndpoint | string | A URI to the blob storage endpoint.
103+
resourceId | string | A unique resource identifier for the storage account.
104+
98105
## Snippets
99106

100107
```json

templates/storage/v1/template.json

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"Standard_GRS"
3030
],
3131
"metadata": {
32-
"description": "Optional. Crease the Storage Account as LRS or GRS."
32+
"description": "Optional. Create the Storage Account as LRS or GRS."
3333
}
3434
},
3535
"suffixLength": {
@@ -346,5 +346,21 @@
346346
"principalType": "ServicePrincipal"
347347
}
348348
}
349-
]
349+
],
350+
"outputs": {
351+
"blobEndpoint": {
352+
"type": "string",
353+
"value": "[reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').primaryEndpoints.blob]",
354+
"metadata": {
355+
"description": "A URI to the blob storage endpoint."
356+
}
357+
},
358+
"resourceId": {
359+
"type": "string",
360+
"value": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
361+
"metadata": {
362+
"description": "A unique resource identifier for the storage account."
363+
}
364+
}
365+
}
350366
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ Describe 'PSDocs' -Tag 'PSDocs', 'Common' {
4242
$result | Should -Not -BeNullOrEmpty;
4343
}
4444

45+
It 'With basic template' {
46+
$invokeParams = @{
47+
Module = 'PSDocs.Azure'
48+
OutputPath = $outputPath
49+
InputObject = (Join-Path -Path $rootPath -ChildPath 'tests/PSDocs.Azure.Tests/basic.template.json')
50+
}
51+
$result = Invoke-PSDocument @invokeParams;
52+
$result | Should -Not -BeNullOrEmpty;
53+
}
54+
4555
It 'With relative path' {
4656
Push-Location -Path (Join-Path -Path $rootPath -ChildPath 'templates/storage/v1/');
4757
try {

0 commit comments

Comments
 (0)