PowerShell と Azure Management API を使用してAzure Managed Cacheを作成しようとしています。公式のAzure PowerShell コマンドレットでは Azure Managed Cache の作成と更新のサポートが非常に限られているため、この 2 つのアプローチが必要です。ただし、PowerShell から Azure Management API を呼び出すための確立されたパターンがあります。
呼び出す正しい API を見つけようとする私の試みは、Azure Managed Cache API に関するドキュメントが限られているために多少妨げられています。ただし、ソース コードと PowerShell のオプションの両方を使用してコマンドレットを処理した後-Debug
、正しい API エンドポイントと思われるものを見つけることができたので、これらのエンドポイントにアクセスするためのコードをいくつか開発しました。
ただし、PUT 要求が Azure API に受け入れられた後、Management API /operations エンドポイントへの後続の呼び出しで、この操作の結果がInternal Server Error
.
Joseph Alabarhari のLinqPad を使用して API を調べてきました。これにより、可能な限り最小限のコードを使用してソリューションを迅速に繰り返すことができるため、次のコード スニペットを実行するには、LinqPadと My Extensions スクリプトの次の拡張機能の両方が必要になります。
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];
}
インクルードを含む完全なソースコードは以下から入手できます。
- My Extensions - 左下のペインで [My Extensions] を右クリックし、[Open Script Location in Windows Explorer] を選択して、強調表示されたファイルをこのファイルに置き換えることで、[My Extensions] を置き換えることができます。または、私の拡張機能を自分の拡張機能にマージすることもできます。
- Azure Managed Cache Script - これをダウンロードしてダブルクリックするだけで、スクリプトを実行できるようになります。
次の設定はスクリプト全体で使用されます。次の変数は、独自の Azure サブスクリプション ID と管理証明書を使用してフォローしているすべての人に必要です。
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"
まず、 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");
これにより、クライアント証明書とx-ms-version
ヘッダーの両方を使用するように HttpClient が構成され、API への最初の呼び出しで、Azure マネージド キャッシュを含む既存の CloudService がフェッチされます。これは空の Azure サブスクリプションを使用していることに注意してください。
var getResult = client.GetAsync("https://" + endpoint + "/" + subscriptionId + "/CloudServices");
getResult.Result.Dump("GET " + getResult.Result.RequestMessage.RequestUri);
このリクエストは を返すので成功StatusCode: 200, ReasonPhrase: 'OK'
です。次に、リクエストから重要な情報 (CloudService 名、キャッシュ名、キャッシュ 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;
}
}
次の PUT 要求のペイロードを含む XML ファイルを事前に作成しました。
<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>
上記のペイロードと、CloudService およびキャッシュ名で構成される URL を使用してHttpRequestMessageを構築します。
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);
StatusCode: 202, ReasonPhrase: 'Accepted'
この要求は、応答を返すため、Azure Service Management API によって名目上受け入れられます。これは基本的に、ペイロードが受け入れられ、オフラインで処理されることを意味します。オペレーション ID を HTTP ヘッダーから解析して、詳細情報を取得できます。
var requestId = putResult.Result.Headers.GetValues("x-ms-request-id").FirstOrDefault();
これrequestId
は、操作のステータスに関する更新をリクエストするために使用できます。
var operation = client.GetAsync("https://" + endpoint + "/" + subscriptionId + "/operations/" + requestId);
operation.Result.Dump(requestId);
XDocument.Load(operation.Result.Content.ReadAsStreamAsync().Result).Dump("Operation " + requestId);
/operations エンドポイントへの要求により、次のペイロードが生成されます。
<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>
そして、これが私が立ち往生している場所です。潜在的なリクエストが500内部サーバーエラーをスローするようにリクエストを微妙に改ざんしている可能性がありますが、より詳細なエラーメッセージやAPIドキュメントがないと、これで行けるところならどこでも。