├── .vscode └── spellright.dict ├── Cities.ps1 ├── New-ClassDefinitionFromObject.ps1 ├── PSJson.Tests.ps1 ├── PSJson.ps1 ├── PSJsonClass.ps1 └── README.md /.vscode/spellright.dict: -------------------------------------------------------------------------------- 1 | isbn 2 | az 3 | -------------------------------------------------------------------------------- /Cities.ps1: -------------------------------------------------------------------------------- 1 | $cities=@" 2 | [ 3 | { name: "London", "population": 8615246 }, 4 | { name: "Berlin", "population": 3517424 }, 5 | { name: "Madrid", "population": 3165235 }, 6 | { name: "Rome", "population": 2870528 } 7 | ] 8 | "@ | ConvertFrom-Json 9 | 10 | $cities.name | ConvertTo-Json -Compress -------------------------------------------------------------------------------- /New-ClassDefinitionFromObject.ps1: -------------------------------------------------------------------------------- 1 | function New-ClassDefinitionFromObject { 2 | [CmdletBinding()] 3 | param( 4 | [Parameter( 5 | Mandatory 6 | )] 7 | [object] 8 | $InputObject , 9 | 10 | [Parameter()] 11 | [SupportsWildcards()] 12 | [String[]] 13 | $EnumType 14 | ) 15 | End { 16 | function helper { 17 | [CmdletBinding()] 18 | param( 19 | [Parameter( 20 | Mandatory, 21 | ValueFromPipeline 22 | )] 23 | [object] 24 | $InputObject , 25 | 26 | [Parameter()] 27 | [ValidateRange(1,99)] # ConvertFrom-Json supports depth up to 99 28 | [uint16] 29 | $Depth = 1 , 30 | 31 | [Parameter()] 32 | [ValidateNotNullOrEmpty()] 33 | [String] 34 | $ParentKey = 'root' , 35 | 36 | [Parameter( 37 | Mandatory 38 | )] 39 | [hashtable] 40 | $DataData , 41 | 42 | [Parameter()] 43 | [SupportsWildcards()] 44 | [String[]] 45 | $EnumType 46 | ) 47 | 48 | Process { 49 | $InputObject.PSObject.Properties.ForEach({ 50 | $prop = $_ 51 | 52 | $propData = @{ 53 | Name = $prop.Name 54 | Type = @() 55 | IsObject = $prop.Value -is [PSObject] 56 | IsArray = $prop.Value -is [Array] 57 | IsEnum = $EnumType -and $prop.Name -ilike $EnumType 58 | Depth = $Depth 59 | ParentKey = $ParentKey 60 | } 61 | 62 | if ($propData.IsArray) { 63 | $prop.Value | helper -Depth ($Depth+1) -DataData $DataData -EnumType $EnumType -ParentKey $propData.Name 64 | if ($DataData.classes.ParentKey -contains $propData.Name) { 65 | $propData.IsObject = $true 66 | } 67 | } 68 | 69 | $propData.Type += $prop.TypeNameOfValue 70 | 71 | if ( 72 | $prop.IsEnum -and ( 73 | $prop.Value -isnot [String] -or 74 | $prop.Value -notmatch '^[a-zA-Z][a-zA-Z0-9_]*$' 75 | ) 76 | ) { 77 | throw [System.InvalidOperationException]"The property '$($propData.Name)' cannot be an enum because one its values is not valid for an enum." 78 | } 79 | 80 | if ($propData.IsObject) { 81 | $prop.Value | helper -Depth ($Depth+1) -DataData $DataData -EnumType $EnumType -ParentKey $propData.Name 82 | } 83 | 84 | if ($propData.IsEnum) { 85 | if ($DataData.enums.ContainsKey($propData.Name)) { 86 | if ($DataData.enums[$propData.Name] -notcontains $prop.Value) { 87 | $DataData.enums[$propData.Name] += $prop.Value 88 | } 89 | } else { 90 | $DataData.enums[$propData.Name] = @($prop.Value) 91 | } 92 | } 93 | 94 | if ($DataData.classes.Where({$_.Name -eq $propData.Name -and $_.ParentKey -eq $propData.ParentKey})) { 95 | return # Naively skip it (for now?) 96 | } 97 | 98 | $DataData.classes += [PSCustomObject]$propData 99 | }) 100 | } 101 | } 102 | 103 | $NL = [System.Environment]::NewLine 104 | 105 | $data = @{ 106 | classes = @() 107 | enums = @{} 108 | } 109 | 110 | helper -InputObject $InputObject -DataData $data -EnumType $EnumType 111 | 112 | $data.classes += [PSCustomObject]@{ 113 | Name = 'root' 114 | Depth = 0 115 | IsObject = $true 116 | } 117 | 118 | $defs = @{ 119 | classes = @() 120 | enums = @() 121 | } 122 | 123 | $data.classes | Sort-Object -Property Depth -Descending | ForEach-Object -Process { 124 | $class = $_ 125 | if ($class.IsEnum) { 126 | $defs.enums += "enum $($class.Name)$NL{$NL`t$($data.enums[$class.Name] -join ';')$NL}$NL" 127 | } 128 | 129 | if ($class.IsObject) { 130 | $params = $data.classes.Where({$_.ParentKey -eq $class.Name}).ForEach({ 131 | $type = if ($_.IsEnum -or $_.IsObject) { 132 | $_.Name 133 | } else { 134 | $_.Type[0] 135 | } 136 | if ($_.IsArray) { 137 | $type = "$type[]" 138 | } 139 | $type = "[$type]" 140 | $name = $_.Name 141 | "`t$type`$$name" 142 | }) -join $NL 143 | $defs.classes += "class $($class.Name)$NL{$NL$params$NL}$NL" 144 | } 145 | } 146 | 147 | "$($defs.enums -join $NL)$NL$($defs.classes -join $NL)" 148 | } 149 | } -------------------------------------------------------------------------------- /PSJson.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "this" { 2 | $data = . "$PSScriptRoot\PSJson.ps1" 3 | 4 | It "Should have data" { 5 | $data | Should Not Be Null 6 | } 7 | 8 | It "Should have 4 authors" { 9 | $actual = $data.store.book.author 10 | 11 | $actual.count | Should be 4 12 | } 13 | 14 | It "Should have these authors" { 15 | $actual = $data.store.book.author 16 | 17 | $actual[0] | Should Be "Nigel Rees" 18 | $actual[1] | Should Be "Evelyn Waugh" 19 | $actual[2] | Should Be "Herman Melville" 20 | $actual[3] | Should Be "J. R. R. Tolkien" 21 | } 22 | 23 | It "Should have 5 prices" { 24 | $actual = $data.store.psobject.Properties.name| ForEach-Object {$data.store.$_.price} 25 | $actual.count | Should be 5 26 | } 27 | 28 | It "Should have these prices" { 29 | $actual = $data.store.psobject.Properties.name| ForEach-Object {$data.store.$_.price} 30 | 31 | $actual[0] | Should Be 8.95 32 | $actual[1] | Should Be 12.99 33 | $actual[2] | Should Be 8.99 34 | $actual[3] | Should Be 22.99 35 | $actual[4] | Should Be 19.95 36 | } 37 | 38 | It "Should have these properties for the 3rd book" { 39 | $actual = $data.store.book[2] 40 | 41 | $actual.category | Should Be "fiction" 42 | $actual.author | Should Be "Herman Melville" 43 | $actual.title | Should Be "Moby Dick" 44 | $actual.isbn | Should Be "0-553-21311-3" 45 | $actual.price | Should Be 8.99 46 | } 47 | 48 | It "Should have these properties for the last book via subscript" { 49 | $actual = $data.store.book[($data.store.book.count - 1)] 50 | 51 | $actual.category | Should Be "fiction" 52 | $actual.author | Should Be "J. R. R. Tolkien" 53 | $actual.title | Should Be "The Lord of the Rings" 54 | $actual.isbn | Should Be "0-395-19395-8" 55 | $actual.price | Should Be 22.99 56 | } 57 | 58 | It "Should have these properties for the last book via array slicing" { 59 | $actual = $data.store.book[-1] 60 | 61 | $actual.category | Should Be "fiction" 62 | $actual.author | Should Be "J. R. R. Tolkien" 63 | $actual.title | Should Be "The Lord of the Rings" 64 | $actual.isbn | Should Be "0-395-19395-8" 65 | $actual.price | Should Be 22.99 66 | } 67 | 68 | It "Should get first 2 books" { 69 | $actual = $data.store.book[0..1] 70 | 71 | $actual.count | Should Be 2 72 | 73 | $actual[0].category | Should Be "reference" 74 | $actual[0].author | Should Be "Nigel Rees" 75 | $actual[0].title | Should Be "Sayings of the Century" 76 | $actual[0].price | Should Be 8.95 77 | 78 | $actual[1].category | Should Be "fiction" 79 | $actual[1].author | Should Be "Evelyn Waugh" 80 | $actual[1].title | Should Be "Sword of Honour" 81 | $actual[1].price | Should Be 12.99 82 | } 83 | 84 | It "Should Filter all books with isbn number" { 85 | $actual = $data.store.book | ? isbn 86 | $actual.count | Should Be 2 87 | 88 | #fiction Herman Melville Moby Dick 0-553-21311-3 8.99 89 | $actual[0].category | Should Be "fiction" 90 | $actual[0].author | Should Be "Herman Melville" 91 | $actual[0].title | Should Be "Moby Dick" 92 | $actual[0].isbn | Should Be "0-553-21311-3" 93 | $actual[0].price | Should Be 8.99 94 | 95 | #fiction J. R. R. Tolkien The Lord of the Rings 0-395-19395-8 22.99 96 | $actual[1].category | Should Be "fiction" 97 | $actual[1].author | Should Be "J. R. R. Tolkien" 98 | $actual[1].title | Should Be "The Lord of the Rings" 99 | $actual[1].isbn | Should Be "0-395-19395-8" 100 | $actual[1].price | Should Be 22.99 101 | } 102 | 103 | It "Should Filter all books cheaper than 10" { 104 | $actual = $data.store.book | ? price -lt 10 105 | $actual.count | Should Be 2 106 | } 107 | 108 | It "Should Filter all books that cost 8.95" { 109 | $actual = @($data.store.book | ? price -eq 8.95) 110 | $actual.count | Should Be 1 111 | } 112 | 113 | It "Should Filter all fiction books cheaper than 30" { 114 | $actual = $data.store.book | ? {$_.price -lt 30 -and $_.category -eq 'fiction'} 115 | $actual.count | Should Be 3 116 | } 117 | 118 | It "Should Sum all book prices" { 119 | $actual = $data.store.book | Measure-Object Price -Sum 120 | $actual.sum | Should be 53.92 121 | } 122 | } -------------------------------------------------------------------------------- /PSJson.ps1: -------------------------------------------------------------------------------- 1 | @" 2 | { 3 | "store": { 4 | "book": [ 5 | { 6 | "category": "reference", 7 | "author": "Nigel Rees", 8 | "title": "Sayings of the Century", 9 | "price": 8.95 10 | }, { 11 | "category": "fiction", 12 | "author": "Evelyn Waugh", 13 | "title": "Sword of Honour", 14 | "price": 12.99 15 | }, { 16 | "category": "fiction", 17 | "author": "Herman Melville", 18 | "title": "Moby Dick", 19 | "isbn": "0-553-21311-3", 20 | "price": 8.99 21 | }, { 22 | "category": "fiction", 23 | "author": "J. R. R. Tolkien", 24 | "title": "The Lord of the Rings", 25 | "isbn": "0-395-19395-8", 26 | "price": 22.99 27 | } 28 | ], 29 | "bicycle": { 30 | "color": "red", 31 | "price": 19.95 32 | } 33 | } 34 | } 35 | "@ | ConvertFrom-Json -------------------------------------------------------------------------------- /PSJsonClass.ps1: -------------------------------------------------------------------------------- 1 | class book { 2 | $category 3 | $author 4 | $title 5 | $isbn 6 | $price 7 | } 8 | 9 | class bicycle { 10 | $color 11 | $price 12 | } 13 | 14 | class store { 15 | [book[]]$book 16 | [bicycle]$bicycle 17 | } 18 | 19 | class root { 20 | [store]$store 21 | } 22 | 23 | [root](.\PSJson.ps1) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Inspired and ported from here https://github.com/dchester/jsonpath 2 | 3 | Comes with: 4 | 5 | * [Pester](https://github.com/pester/Pester) tests 6 | * PowerShell classes for casting the JSON 7 | 8 | 9 | # Query Example 10 | 11 | ```ps 12 | $cities=@" 13 | [ 14 | { name: "London", "population": 8615246 }, 15 | { name: "Berlin", "population": 3517424 }, 16 | { name: "Madrid", "population": 3165235 }, 17 | { name: "Rome", "population": 2870528 } 18 | ] 19 | "@ | ConvertFrom-Json 20 | 21 | $cities.name | ConvertTo-Json -Compress 22 | ``` 23 | 24 | 25 | 26 | ```json 27 | ["London","Berlin","Madrid","Rome"] 28 | ``` 29 | 30 | 31 | # Example Expressions 32 | Query JSON with PowerShell 33 | 34 | ### The sample JSON 35 | 36 | ```json 37 | { 38 | "store": { 39 | "book": [ 40 | { 41 | "category": "reference", 42 | "author": "Nigel Rees", 43 | "title": "Sayings of the Century", 44 | "price": 8.95 45 | }, { 46 | "category": "fiction", 47 | "author": "Evelyn Waugh", 48 | "title": "Sword of Honour", 49 | "price": 12.99 50 | }, { 51 | "category": "fiction", 52 | "author": "Herman Melville", 53 | "title": "Moby Dick", 54 | "isbn": "0-553-21311-3", 55 | "price": 8.99 56 | }, { 57 | "category": "fiction", 58 | "author": "J. R. R. Tolkien", 59 | "title": "The Lord of the Rings", 60 | "isbn": "0-395-19395-8", 61 | "price": 22.99 62 | } 63 | ], 64 | "bicycle": { 65 | "color": "red", 66 | "price": 19.95 67 | } 68 | } 69 | } 70 | ``` 71 | 72 | 73 | 74 | ### Cast to a Class in PowerShell 75 | 76 | You can create Classes in PowerShell and you can cast JSON to them like this. 77 | 78 | 79 | ```ps 80 | class book { 81 | $category 82 | $author 83 | $title 84 | $isbn 85 | $price 86 | } 87 | 88 | class bicycle { 89 | $color 90 | $price 91 | } 92 | 93 | class store { 94 | [book[]]$book 95 | [bicycle]$bicycle 96 | } 97 | 98 | class root { 99 | [store]$store 100 | } 101 | 102 | [root](.\PSJson.ps1) 103 | ``` 104 | 105 | 106 | 107 | This approach enables you to validate that the incoming data has correct objects and fields associated with it. 108 | 109 | 110 | 111 | 112 | 113 | ### Generate the Classes From the Data 114 | 115 | ```ps 116 | $PSObjs = & .\PSJson.ps1 117 | New-ClassDefinitionFromObject -InputObject $PSObjs 118 | ``` 119 | 120 | Do this on a dataset beforehand to pre-generate the classes so you don't have to create them all by hand. 121 | Tweak as needed if the sample dataset you fed it didn't cover all possibilities. 122 | 123 | `New-ClassDefinitionFromObject` can also be told to convert some properties into an `enum` instead with the `-EnumType` parameter (wildcards supported): 124 | 125 | ```ps 126 | New-ClassDefinitionFromObject -InputObject $PSObjs -EnumType categ* 127 | ``` 128 | 129 | And the actual generated code from the above command: 130 | 131 | ```ps 132 | enum category 133 | { 134 | reference;fiction 135 | } 136 | 137 | class book 138 | { 139 | [category]$category 140 | [System.String]$author 141 | [System.String]$title 142 | [System.Decimal]$price 143 | [System.String]$isbn 144 | } 145 | 146 | class bicycle 147 | { 148 | [System.String]$color 149 | [System.Decimal]$price 150 | } 151 | 152 | class store 153 | { 154 | [book[]]$book 155 | [bicycle]$bicycle 156 | } 157 | 158 | class root 159 | { 160 | [store]$store 161 | } 162 | ``` 163 | 164 | 165 | 166 | 167 | ### Queries 168 | 169 | | PowerShell | Description | 170 | | --- | --- | 171 | | `$data.store.book.author` | The authors of all books in the store | 172 | 173 | ``` 174 | Nigel Rees 175 | Evelyn Waugh 176 | Herman Melville 177 | J. R. R. Tolkien 178 | ``` 179 | 180 | | PowerShell | Description | 181 | | --- | --- | 182 | | `$data.store \| Format-List` | All the things in the store | 183 | 184 | ``` 185 | book : {@{category=reference; author=Nigel Rees; title=Sayings of the Century; price=8.95}, @{category=fiction; author=Evelyn Waugh; title=Sword of Honour; 186 | price=12.99}, @{category=fiction; author=Herman Melville; title=Moby Dick; isbn=0-553-21311-3; price=8.99}, @{category=fiction; author=J. R. R. Tolkien; 187 | title=The Lord of the Rings; isbn=0-395-19395-8; price=22.99}} 188 | bicycle : @{color=red; price=19.95} 189 | ``` 190 | 191 | | PowerShell | Description | 192 | | --- | --- | 193 | | `$data.store.psobject.Properties.name \| ForEach-Object {$data.store.$_.price} ` | The price of everything in the store | 194 | 195 | ``` 196 | 8.95 197 | 12.99 198 | 8.99 199 | 22.99 200 | 19.95 201 | ``` 202 | 203 | | PowerShell | Description | 204 | | --- | --- | 205 | | `$data.store.book[2]` | The third book | 206 | 207 | ``` 208 | category : fiction 209 | author : Herman Melville 210 | title : Moby Dick 211 | isbn : 0-553-21311-3 212 | price : 8.99 213 | ``` 214 | 215 | | PowerShell | Description | 216 | | --- | --- | 217 | | `$data.store.book[($data.store.book.count-1)] ` | The last book via subscript | 218 | 219 | ``` 220 | category : fiction 221 | author : J. R. R. Tolkien 222 | title : The Lord of the Rings 223 | isbn : 0-395-19395-8 224 | price : 22.99 225 | ``` 226 | 227 | | PowerShell | Description | 228 | | --- | --- | 229 | | `$data.store.book[-1]` | The last book via array slicing | 230 | 231 | ``` 232 | category : fiction 233 | author : J. R. R. Tolkien 234 | title : The Lord of the Rings 235 | isbn : 0-395-19395-8 236 | price : 22.99 237 | ``` 238 | 239 | | PowerShell | Description | 240 | | --- | --- | 241 | | `$data.store.book[0..1]` | The first two books | 242 | 243 | ``` 244 | category author title price 245 | -------- ------ ----- ----- 246 | reference Nigel Rees Sayings of the Century 8.95 247 | fiction Evelyn Waugh Sword of Honour 12.99 248 | ``` 249 | 250 | | PowerShell | Description | 251 | | --- | --- | 252 | | `$data.store.book \| ? isbn` | Filter all books with isbn number | 253 | 254 | ``` 255 | category author title isbn price 256 | -------- ------ ----- ---- ----- 257 | fiction Herman Melville Moby Dick 0-553-21311-3 8.99 258 | fiction J. R. R. Tolkien The Lord of the Rings 0-395-19395-8 22.99 259 | ``` 260 | 261 | | PowerShell | Description | 262 | | --- | --- | 263 | | `$data.store.book \| ? price -lt 10` | Filter all books cheaper than 10 | 264 | 265 | ``` 266 | category author title price 267 | -------- ------ ----- ----- 268 | reference Nigel Rees Sayings of the Century 8.95 269 | fiction Herman Melville Moby Dick 8.99 270 | ``` 271 | 272 | | PowerShell | Description | 273 | | --- | --- | 274 | | `$data.store.book \| ? price -eq 8.95` | Filter all books that cost 8.95 | 275 | 276 | ``` 277 | category author title price 278 | -------- ------ ----- ----- 279 | reference Nigel Rees Sayings of the Century 8.95 280 | ``` 281 | 282 | | PowerShell | Description | 283 | | --- | --- | 284 | | `$data.store.book \| Measure-Object price -Sum` | Sum all book prices | 285 | 286 | ``` 287 | Count : 4 288 | Average : 289 | Sum : 53.92 290 | Maximum : 291 | Minimum : 292 | Property : price 293 | ``` 294 | 295 | | PowerShell | Description | 296 | | --- | --- | 297 | | `$data.store.book \| ? {$_.price -lt 30 -and $_.category -eq 'fiction'}` | Filter all fiction books cheaper than 30 | 298 | 299 | ``` 300 | category author title price 301 | -------- ------ ----- ----- 302 | fiction Evelyn Waugh Sword of Honour 12.99 303 | fiction Herman Melville Moby Dick 8.99 304 | fiction J. R. R. Tolkien The Lord of the Rings 22.99 305 | ``` 306 | 307 | 308 | 309 | # PowerShell and the Azure CLI 310 | 311 | **Example az cli:** 312 | 313 | [![Launch Cloud Shell](https://shell.azure.com/images/launchcloudshell.png "Launch Cloud Shell")](https://shell.azure.com/powershell) 314 | 315 | 316 | ```ps 317 | az vm list 318 | ``` 319 | 320 | **Example Result:** 321 | 322 | Here is a pruned down output from ~90 lines of JSON information. 323 | 324 | ``` 325 | { 326 | "additionalProperties": {}, 327 | "availabilitySet": null, 328 | "diagnosticsProfile": { 329 | "additionalProperties": {}, 330 | "bootDiagnostics": { 331 | "additionalProperties": {} 332 | } 333 | }, 334 | "hardwareProfile": { 335 | } 336 | . 337 | . 338 | . 339 | "identity": null, 340 | "licenseType": null, 341 | "location": "eastus", 342 | "name": "TestServer1", 343 | "osProfile": { 344 | "additionalProperties": {} 345 | } 346 | 347 | } 348 | ``` 349 | 350 | **Example az cli:** 351 | 352 | Pipe the result from `az cli` to PowerShell's `ConvertFrom-Json`, it gets converted to an array of objects, and then you pipe it to the Select-Object cmdlet to display the name property. 353 | 354 | [![Launch Cloud Shell](https://shell.azure.com/images/launchcloudshell.png "Launch Cloud Shell")](https://shell.azure.com/powershell) 355 | 356 | 357 | ```ps 358 | (az vm list | ConvertFrom-Json) | Select-Object name 359 | ``` 360 | 361 | **Example Result:** 362 | 363 | PowerShell easily iterates over just the names of the VMs. 364 | 365 | ``` 366 | name 367 | ---- 368 | TestServer1 369 | TestServer2 370 | TestServer3 371 | TestServer4 372 | TestServer5 373 | TestServer6 374 | TestServer7 375 | TestServer8 376 | ``` 377 | 378 | **Example az cli:** 379 | 380 | Now, grab more than one property. 381 | 382 | [![Launch Cloud Shell](https://shell.azure.com/images/launchcloudshell.png "Launch Cloud Shell")](https://shell.azure.com/powershell) 383 | 384 | ```ps 385 | (az vm list | ConvertFrom-Json) | Select-Object resourcegroup, name 386 | ``` 387 | 388 | **Example Result:** 389 | 390 | That lines converts the az cli JSON to an array of PowerShell objects and you pick off the two properties by name. 391 | 392 | ``` 393 | resourceGroup name 394 | ------------- ---- 395 | TESTSERVER1-RG TestServer1 396 | TESTSERVER2-RG TestServer2 397 | TESTSERVER3-RG TestServer3 398 | TESTSERVER4-RG TestServer4 399 | TESTSERVER5-RG TestServer5 400 | TESTSERVER6-RG TestServer6 401 | TESTSERVER7-RG TestServer7 402 | TESTSERVER8-RG TestServer8 403 | ``` 404 | 405 | **Example az cli:** 406 | 407 | Or, do custom transformations. 408 | 409 | [![Launch Cloud Shell](https://shell.azure.com/images/launchcloudshell.png "Launch Cloud Shell")](https://shell.azure.com/powershell) 410 | 411 | 412 | ```ps 413 | (az vm list | ConvertFrom-Json) | ForEach-Object { 414 | 415 | $details = $_.storageProfile.imageReference | Select-Object offer, publisher, sku, version 416 | [PSCustomObject][Ordered]@{ 417 | ResourceGroup = $_.ResourceGroup 418 | Name = $_.Name 419 | Offer = $details.Offer 420 | Publisher = $details.Publisher 421 | Sku = $details.Sku 422 | Version = $details.Version 423 | } 424 | } 425 | ``` 426 | 427 | **Example Result:** 428 | 429 | PowerShell makes it easy to traverse nested JSON and flattened the results. 430 | 431 | ``` 432 | ResourceGroup Name Offer Publisher Sku Version 433 | ------------- ---- ----- --------- --- ------- 434 | TESTSERVER1-RG TestServer1 UbuntuServer Canonical 16.04-LTS latest 435 | TESTSERVER2-RG TestServer2 RHEL RedHat 7.2 latest 436 | TESTSERVER3-RG TestServer3 kali-linux kali-linux kali latest 437 | TESTSERVER4-RG TestServer4 UbuntuServer Canonical 16.04-LTS latest 438 | TESTSERVER5-RG TestServer5 UbuntuServer Canonical 16.04-LTS latest 439 | TESTSERVER6-RG TestServer6 UbuntuServer Canonical 16.04-LTS latest 440 | TESTSERVER7-RG TestServer7 UbuntuServer Canonical 16.04-LTS latest 441 | TESTSERVER8-RG TestServer8 UbuntuServer Canonical 16.04-LTS latest 442 | ``` 443 | 444 | 445 | --------------------------------------------------------------------------------