1

Je tente de créer un Azure Managed Cache à l'aide de PowerShell et de l'API Azure Management. Cette approche à deux volets est requise car le Offical Azure PowerShell Cmdlets ne prend en charge que très peu le Creation and Update of Azure Managed Cache. Il y a cependant un established pattern for calling the Azure Management API from PowerShell.Création et mise à jour des caches nommés dans Azure Managed Cache à l'aide de l'API de gestion

Mes tentatives pour trouver l'API correcte à appeler ont été quelque peu entravées par limited documentation sur l'API Azure Managed Cache. Cependant, après avoir parcouru les applets de commande en utilisant à la fois le code source et l'option -Debug dans PowerShell, j'ai pu trouver ce qui semble être les points de terminaison API corrects, j'ai donc développé du code pour accéder à ces points de terminaison.

Toutefois, je suis resté coincé après que la demande PUT a été acceptée dans l'API Azure car les appels suivants au point de terminaison API/Operations Management indiquent que le résultat de cette opération était Internal Server Error.

J'utilise Joseph Alabarhari's LINQPad pour explorer l'API car il me permet de itterate rapidement sur une solution utilisant le code minimum possible, afin d'exécuter les extraits de code suivant, vous aurez besoin à la fois LinqPad et l'extension suivante dans votre Mes extensions scénario:

public static X509Certificate2 GetCertificate(this StoreLocation storeLocation, string thumbprint) { 
    var certificateStore = new X509Store(StoreName.My, storeLocation); 
    certificateStore.Open(OpenFlags.ReadOnly); 
    var certificates = certificateStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false); 
    return certificates[0]; 
} 

le code source complet, y compris les includes sont disponibles ci-dessous:

  • My Extensions - vous pouvez remplacer un "Mes extensions" en cliquant droit Mes extensions i Dans le volet inférieur gauche, choisissez «Ouvrir le script dans l'Explorateur Windows», puis remplacez le fichier en surbrillance par celui-ci. Vous pouvez également fusionner mes extensions avec les vôtres.
  • Azure Managed Cache Script - vous devriez simplement être en mesure de télécharger et double-cliquer dessus, une fois ouvert et les extensions et certificats ci-dessus sont en place, vous serez en mesure d'exécuter le script.

Les paramètres suivants sont utilisés dans le script, les variables suivantes devront pour tous ceux qui suivent le long en utilisant leur propre Azure ID d'abonnement et d'un certificat de gestion:

var cacheName = "amc551aee"; 
var subscriptionId = "{{YOUR_SUBSCRIPTION_ID}}"; 
var certThumbprint = "{{YOUR_MANAGEMENT_CERTIFICATE_THUMBPRINT}}"; 
var endpoint = "management.core.windows.net"; 
var putPayloadXml = @"{{PATH_TO_PUT_PAYLOAD}}\cloudService.xml" 

D'abord, je l'ai fait quelques-uns installation sur le HttpClient:

var handler = new WebRequestHandler(); 
handler.ClientCertificateOptions = ClientCertificateOption.Manual; 
handler.ClientCertificates.Add(StoreLocation.CurrentUser.GetCertificate(certThumbprint)); 
var client = new HttpClient(handler); 
client.DefaultRequestHeaders.Add("x-ms-version", "2012-08-01"); 

Cela configure HttpClient à la fois utiliser un certificat client et l'en-tête x-ms-version, le premier appel à la a PI extrait le CloudService existant qui contient le cache géré Azure. Veuillez noter que ceci utilise un abonnement Azure autrement vide.

var getResult = client.GetAsync("https://" + endpoint + "/" + subscriptionId + "/CloudServices"); 
getResult.Result.Dump("GET " + getResult.Result.RequestMessage.RequestUri); 

Cette demande est réussie car elle retourne StatusCode: 200, ReasonPhrase: 'OK', je puis parse quelques informations clés sur la demande: le nom CloudService, le nom du cache et le cache ETag:

var cacheDataReader = new XmlTextReader(getResult.Result.Content.ReadAsStreamAsync().Result); 
var cacheData = XDocument.Load(cacheDataReader); 
var ns = cacheData.Root.GetDefaultNamespace(); 
var nsManager = new XmlNamespaceManager(cacheDataReader.NameTable); 
nsManager.AddNamespace("wa", "http://schemas.microsoft.com/windowsazure"); 

var cloudServices = cacheData.Root.Elements(ns + "CloudService"); 
var serviceName = String.Empty; 
var ETag = String.Empty; 
foreach (var cloudService in cloudServices) { 
    if (cloudService.XPathSelectElements("//wa:CloudService/wa:Resources/wa:Resource/wa:Name", nsManager).Select(x => x.Value).Contains(cacheName)) { 
     serviceName = cloudService.XPathSelectElement("//wa:CloudService/wa:Name", nsManager).Value; 
     ETag = cloudService.XPathSelectElement("//wa:CloudService/wa:Resources/wa:Resource/wa:ETag", nsManager).Value; 
    } 
} 

Je pré créé un fichier XML qui contient la charge utile de la demande PUT suivante:

<Resource xmlns="http://schemas.microsoft.com/windowsazure"> 
    <IntrinsicSettings> 
    <CacheServiceInput xmlns=""> 
     <SkuType>Standard</SkuType> 
     <Location>North Europe</Location> 
     <SkuCount>1</SkuCount> 
     <ServiceVersion>1.3.0</ServiceVersion> 
     <ObjectSizeInBytes>1024</ObjectSizeInBytes> 
     <NamedCaches> 
     <NamedCache> 
      <CacheName>default</CacheName> 
      <NotificationsEnabled>false</NotificationsEnabled> 
      <HighAvailabilityEnabled>false</HighAvailabilityEnabled> 
      <EvictionPolicy>LeastRecentlyUsed</EvictionPolicy> 
     </NamedCache> 
     <NamedCache> 
      <CacheName>richard</CacheName> 
      <NotificationsEnabled>true</NotificationsEnabled> 
      <HighAvailabilityEnabled>true</HighAvailabilityEnabled> 
      <EvictionPolicy>LeastRecentlyUsed</EvictionPolicy> 
     </NamedCache> 
     </NamedCaches> 
    </CacheServiceInput> 
    </IntrinsicSettings> 
</Resource> 

Je construcuct un HttpRequestMessage avec le payload ci-dessus et une URL comprenant du CloudService et noms Cache:

var resourceUrl = "https://" + endpoint + "/" + subscriptionId + "/cloudservices/" + serviceName + "/resources/cacheservice/Caching/" + cacheName; 
var data = File.ReadAllText(putPayloadXml); 
XDocument.Parse(data).Dump("Payload"); 
var message = new HttpRequestMessage(HttpMethod.Put, resourceUrl); 
message.Headers.TryAddWithoutValidation("If-Match", ETag); 
message.Content = new StringContent(data, Encoding.UTF8, "application/xml"); 
var putResult = client.SendAsync(message); 
putResult.Result.Dump("PUT " + putResult.Result.RequestMessage.RequestUri); 
putResult.Result.Content.ReadAsStringAsync().Result.Dump("Content " + putResult.Result.RequestMessage.RequestUri); 

Cette demande est par l'API de gestion des services Azure nominalement acceptée car elle renvoie une réponse StatusCode: 202, ReasonPhrase: 'Accepted'; Essentiellement, cela signifie que la charge utile a été acceptée et sera traitée en mode hors connexion, l'Opération carte d'identité peut être analysé hors de l'en-tête HTTP pour retreve plus d'informations:

var requestId = putResult.Result.Headers.GetValues("x-ms-request-id").FirstOrDefault(); 

Ce requestId peut être utilisé pour demander une mise à jour sur le statut de l'opération:

var operation = client.GetAsync("https://" + endpoint + "/" + subscriptionId + "/operations/" + requestId); 
operation.Result.Dump(requestId); 
XDocument.Load(operation.Result.Content.ReadAsStreamAsync().Result).Dump("Operation " + requestId); 

la demande aux opérations/résultats finaux dans la charge utile suivante:

<Operation xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
    <ID>5364614d-4d82-0f14-be41-175b3b85b480</ID> 
    <Status>Failed</Status> 
    <HttpStatusCode>500</HttpStatusCode> 
    <Error> 
    <Code>InternalError</Code> 
    <Message>The server encountered an internal error. Please retry the request.</Message> 
    </Error> 
</Operation> 

Et c'est là Je suis bloqué, il y a de fortes chances que je déforme subtilement la requête de telle sorte que la requête sous-jacente génère une Erreur interne du serveur 500, mais sans un message d'erreur plus détaillé ou une documentation API. avec ça.

Répondre

1

Nous avons travaillé avec Richard hors ligne et la charge utile XML suivante l'a débloqué. Remarque - Lorsque vous ajoutez/supprimez un cache nommé dans un cache existant, la taille de l'objet est fixe.

Remarque 2- L'API Azure Managed Cache est sensible aux espaces entre l'élément et l'élément.

Veuillez également noter que nous travaillons sur l'ajout d'une capacité de cache nommée à notre PowerShell lui-même, de sorte que les utilisateurs n'ont pas besoin d'utiliser les API pour le faire.

<Resource xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
    <IntrinsicSettings><CacheServiceInput xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
     <SkuType>Standard</SkuType> 
     <Location>North Europe</Location> 
     <SkuCount>1</SkuCount> 
     <ServiceVersion>1.3.0</ServiceVersion> 
     <ObjectSizeInBytes>1024</ObjectSizeInBytes> 
    <NamedCaches> 
     <NamedCache> 
     <CacheName>default</CacheName> 
     <NotificationsEnabled>false</NotificationsEnabled> 
     <HighAvailabilityEnabled>false</HighAvailabilityEnabled> 
     <EvictionPolicy>LeastRecentlyUsed</EvictionPolicy> 
     <ExpirationSettings> 
      <TimeToLiveInMinutes>10</TimeToLiveInMinutes> 
      <Type>Absolute</Type> 
     </ExpirationSettings> 
     </NamedCache> 
     <NamedCache> 
     <CacheName>richard</CacheName> 
     <NotificationsEnabled>false</NotificationsEnabled> 
     <HighAvailabilityEnabled>false</HighAvailabilityEnabled> 
     <EvictionPolicy>LeastRecentlyUsed</EvictionPolicy> 
     <ExpirationSettings> 
      <TimeToLiveInMinutes>10</TimeToLiveInMinutes> 
      <Type>Absolute</Type> 
     </ExpirationSettings> 
     </NamedCache> 
    </NamedCaches>  
    </CacheServiceInput> 
    </IntrinsicSettings> 
</Resource> 
+0

Bonne question! J'ai documenté les exigences telles que je les vois dans le numéro suivant sur la page GitHub d'azure-sdk-tools: https://github.com/Azure/azure-sdk-tools/issues/2876 –

+0

Richard, crée le cache via Powershell et l'ajout de caches nommés via le portail n'est pas acceptable dans votre scénario? – Saurabh

+0

oui - en raison de la complexité des systèmes du client, ils ont besoin d'une automatisation complète, ce qui est principalement pour satisfaire les exigences des autres équipes qui auront besoin de déployer une solution à de nombreux environnements après son utilisation. –

Questions connexes