Seriál Windows PowerShell: PowerShell a Azure REST API (část 53.)

Jsem si jist, že na TechNet blogu sledujete Azure články mého kolegy z Mainstream Technologies – Matouše Rokose. Na Azure můžete jít přes portál nebo (mnou preferovaná varianta) z konzole PowerShellu. V minulosti jsem o modulu pro Microsoft Azure také psal. Občas se ale stane, že Azure cmdlety nepokrývají funkcionalitu, kterou zrovna chcete řešit. V tom případě máte možnost zaprogramovat si v C# (či jiném jazyku) nebo použít pro přístup do Azure REST API. Nebojte, nejedná se o žádnou složitost. Vzhledem k tomu, že v PowerShellu existuje cmdlet Invoke-RestMethod, je použití jednoduché – minimálně pro toho, kdo dokáže v PowerShellu pracovat např. s Active Directory.

Pokud vás zajímá víc informací v Azure REST API, podívejte na MSDN https://msdn.microsoft.com/en-us/library/azure/ee460799.aspx.

Příklady

Ukážeme si dva jednoduché příklady použití REST API. V prvním si zobrazíme Azure Cloud Services. Na stránce, kterou jsem uvedl výše, najdeme, že URI pro náš dotaz má formát: https://management.core.windows.net/\<subscription-id>/services/hostedservicesa musíme použít metodu GET.

image

Každý REST dotaz musí obsahovat (minimálně) informaci o použité verzi. Doporučuji najít si aktuální poslední verzi a tu použít.

image

Nyní máme pohromadě potřebné informace (cmdlet, URI a hlavičku) a můžeme zkusit sestavit náš dotaz.

PS C:\> $uri = 'https://management.core.windows.net/9a89…0b44/services/hostedservices'
PS C:\> Invoke-RestMethod -Uri $uri

Invoke-RestMethod: <Error xmlns="https://schemas.microsoft.com/windowsazure" xmlns:i="https://www.w3.org/2001/XMLSchema-instance"><Code>ForbiddenError</Code><Message>The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription.</Message></Error>
At line:1 char:1
+ Invoke-RestMethod $uri
+ ~~~~~~~~
     + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Vidíte, že request nebyl správně ověřen oproti serveru. Musíme tedy přidat CertificateThumbprint. Ověřujeme certifikátem, který máme stažený v počítači (při prvotním nastavení PowerShell cmdletů).

PS C:\> Invoke-RestMethod -Uri $uri -CertificateThumbprint C939114DA392E64947E4C22FB92FB92FB9

Invoke-RestMethod : <Error xmlns="https://schemas.microsoft.com/windowsazure" xmlns:i="https://www.w3.org/2001/XMLSchema-instance"><Code>MissingOrIncorrectVersionHeader</Code><Message>Request needs to have a x-ms-version header.</Message></Error>
At line:1 char:1
+ Invoke-RestMethod -Uri $uri -CertificateThumbprint C939114DA392E64947E4C22FB92FB92FB9
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Nyní vidíte, že chyba je odlišná. Jasně nám sděluje, že potřebujeme přidat onu verzi, kterou jsme viděli na jednom z předchozích obrázků. Přidáme tedy hash tabulku a uvedeme potřebné parametry. Hash tabulka by vás již neměla překvapit, používali jsme ji v několika minulých dílech.

PS C:\> Invoke-RestMethod -Uri $uri -CertificateThumbprint C939114DA392E64947E4C22FB92FB92FB9 -Headers @{'x-ms-version'='2014-06-01'}

HostedServices
--------------
HostedServices

Vidíme, že jsme opravdu dostali odpověď, která obsahuje nějaká (zatím neznámá) data. Vzhledem k tomu, že odpověď je standardní XML soubor, můžeme použít PowerShell syntaxi pro přístup k XML proměnné.

PS C:\> (Invoke-RestMethod -Uri $uri -CertificateThumbprint C939114DA392E64947E4C22FB92FB92FB9 -Headers @{'x-ms-version'='2014-06-01'}).HostedServices.HostedService.ServiceName

MakovecAZ083
MakovecAzATEST
mkutestvm1
PCfromtempl

Pokud vás zajímá, jaký tvar má odpověď, můžete se podívat na web, kde je vše podrobně popsáno. Malá část je zobrazena na následujícím obrázku.

image

image

Nyní máme seznam všech Services a můžeme se podívat na jednotlivé virtuální počítače, které jsou součástí těchto Services. Na MSDN opět najdeme formát pro dotaz: https://management.core.windows.net/\<subscription-id>/services/hostedservices/<cloudservice-name>

Pokud si přečtete informace na webu pozorně, což se při čtení na MSDN vždy hodí J, zjistíte, že URI může obsahovat parametr embed-detail, který (pokud je nastaven) vrátí více informací a Services. Pro náš dotaz jej tedy zapneme.

PS C:\> $uri= 'https://management.core.windows.net/<subscription-id>/services/hostedservices/mkutestvm1?embed-detail=true'
PS C:\temp> (Invoke-RestMethod -Uri $uri -CertificateThumbprint C939114DA392E64947E4C22FB92FB92FB9 -Headers @{'x-ms-version'='2014-06-01'}).HostedService.Deployments.Deployment.Name
mkutestvm1

Vidíte, že výsledkem je jméno virtuálního počítače, který je v této Cloud Service. Pokud chceme replikovat funkcionalitu cmdletu Get-AzureVM můžeme si napsat jednoduchou funkci.

function Get-AzureVMfromREST
{
    $subscriptionID = '9a89542c-4657-807f-4fd0b2bd0b44'
    $certificateTP = ' C939114DA392E64947E4C22FB92FB92FB9'
    $requestHeader = @{ 'x-ms-version' = '2014-06-01' }

    $uriHS = "https://management.core.windows.net/$subscriptionID/services/hostedservices"

    $uriVM = https://management.core.windows.net/$subscriptionID/services/hostedservices/{0}?embed-detail=true
    (Invoke-RestMethod -Method Get -Uri $uriHS -CertificateThumbprint $certificateTP -Headers $requestHeader).HostedServices.HostedService |
         ForEach {
            $hsName = $_.ServiceName
            Invoke-RestMethod -Method Get -Uri ($uriVM -f $hsName) -CertificateThumbprint $certificateTP -Headers $requestHeader |
               ForEach {
               $prop = [ordered]@{
                   'ServiceName' = $_.HostedService.ServiceName
                   'Name' = $_.HostedService.Deployments.Deployment.Name
                   'Status' = $_.HostedService.Deployments.Deployment.RoleInstanceList.RoleInstance.InstanceStatus
               }
               New-Object -TypeName PSObject -Property $prop
          }
     }
}

A podíváme se na výsledek.

PS C:\> Get-AzureVMfromREST

ServiceName Name Status
----------- ---- ------
MakovecAZ083 MakovecAZ083 StoppedDeallocated
MakovecAzATEST MakovecAzATEST StoppedDeallocated
mkutestvm1 mkutestvm1 StoppedDeallocated

Tip

Celý článek vznikl i proto, abych vám ukázal další pěkné použití proměnné PSDefaultParameterValues (také jsem o ní psal již dříve). Vzhledem k tomu, že momentálně nepřistupuji na jiné REST služby, než do své subskripce, může použít následující řádky pro nastavení mého prostředí.

# Azure REST API
$sID = '9a89542c-4657-807f-4fd0b2bd0b44'
$cTP = 'C939114DA392E64947E4C22FB92FB92FB9'
$HeaderRESTAzure = @{ 'x-ms-version' = '2014-06-01' }
$PSDefaultParameterValues.Add('Invoke-RestMethod:CertificateThumbprint', $cTP)
$PSDefaultParameterValues.Add('Invoke-RestMethod:Headers', $HeaderRESTAzure)
$PSDefaultParameterValues.Add('Invoke-RestMethod:Method', 'Get')

PSDefaultParameterValue definuje standardní hodnotu pro jednotlivé parametry definovaných cmdletů. Proto mohu předchozí příklad spustit nyní takto:

PS C:\> $uri = https://management.core.windows.net/$sid/services/hostedservices
PS C:\> irm $uri

HostedServices
--------------
HostedServices

Parametry Headers, CertificateThumbprint a Methodjsou automaticky doplněné.

Z dnešního článku byste si měli odnést poučení, které platí pro celý PowerShell. Pokud umíte pracovat v PowerShellu s jednou technologií a ovládáte jednotlivé části, můžete vaše znalosti přenést na úplně novou technologii (zdroj) bez větších problémů.

Přeji vám všem hezké skriptování v roce 2015.

David Moravec, MVP
Mainstream Technologies