今回はサーバー管理用の REST API をアクティビティ化してみました。REST API 利用ですので、SDK 等の導入は一切必要ありません。
殆ど似た形になるので今回はベースクラスを作成し、各アクティビティはそれを継承する形にしています。まずはベースとなるアクティビティクラスから。
1: Imports System.Activities
2: Imports System.IO
3: Imports System.Net
4: Imports System.Security.Cryptography.X509Certificates
5:
6: Public MustInherit Class AzureActivityBase
7: Inherits AsyncCodeActivity
8:
9: Protected Const SQL_API_PATH = "https://management.database.windows.net:8443/{0}/servers"
10:
11: Public Property SubscriptionID As String
12: Public Property CertThumbPrint As String
13:
14: Public Property Account As String
15: Public Property Password As String
16: Public Property Location As String
17:
18: Public Property ResultDocument As OutArgument(Of String)
19: Public Property ResultStatus As OutArgument(Of String)
20: Public Property RequestID As OutArgument(Of String)
21:
22: Private Delegate Function AsyncGetWebDataDelegate(ByVal subscription As String,
23: ByVal thumbprint As String,
24: ByVal admAccount As String,
25: ByVal admPassword As String,
26: ByVal locations As String) As String()
27:
28: Protected Overrides Function BeginExecute(context As System.Activities.AsyncCodeActivityContext, callback As System.AsyncCallback, state As Object) As System.IAsyncResult
29: Dim asyncExecute = New AsyncGetWebDataDelegate(AddressOf GetWebData)
30: context.UserState = asyncExecute
31:
32: Return asyncExecute.BeginInvoke(Me.SubscriptionID, Me.CertThumbPrint,
33: Me.Account, Me.Password, Me.Location, callback, state)
34: End Function
35:
36: Protected Overrides Sub EndExecute(context As System.Activities.AsyncCodeActivityContext, result As System.IAsyncResult)
37: Dim asyncExecute = TryCast(context.UserState, AsyncGetWebDataDelegate)
38: Dim getResult = asyncExecute.EndInvoke(result)
39:
40: context.SetValue(Me.ResultDocument, getResult(0))
41: context.SetValue(Me.ResultStatus, getResult(1))
42: context.SetValue(Me.RequestID, getResult(2))
43: End Sub
44:
45: Protected Overridable Function GetWebData(ByVal subscription As String,
46: ByVal thumbprint As String,
47: ByVal admin As String,
48: ByVal pass As String,
49: ByVal loc As String) As String()
50: Dim resultStrings As String = ""
51: Dim resultStatus As String = ""
52: Dim resultRequestID As String = ""
53: Try
54: Dim certificate As X509Certificate2 = CreateCertification(thumbprint)
55:
56: Dim requestUri As Uri = Me.CreateApiPath(subscription)
57: Dim localWebRequest = TryCast(HttpWebRequest.Create(requestUri), HttpWebRequest)
58: localWebRequest.ClientCertificates.Add(certificate)
59: Me.SetHttpMethod(localWebRequest)
60: Me.AddRequestHeader(localWebRequest)
61:
62: Dim bodyString = Me.CreateBodyMessage(admin, pass, loc)
63: If bodyString IsNot Nothing Then
64: Dim sendBytes() As Byte = Text.Encoding.UTF8.GetBytes(bodyString)
65: localWebRequest.ContentLength = sendBytes.Length
66: localWebRequest.ContentType = "application/xml; charset=utf-8"
67: Using reqStream = localWebRequest.GetRequestStream
68: reqStream.Write(sendBytes, 0, sendBytes.Length)
69: End Using
70: End If
71:
72: Using webResponse = TryCast(localWebRequest.GetResponse(), HttpWebResponse)
73: resultStatus = webResponse.StatusCode.ToString
74: resultRequestID = webResponse.Headers("x-ms-request-id")
75: Using responseStream = webResponse.GetResponseStream()
76: Using reader As New StreamReader(responseStream)
77: resultStrings = reader.ReadToEnd
78: End Using
79: End Using
80: End Using
81:
82: Catch ex As Exception
83: resultStrings = ex.Message
84: End Try
85: Return New String() {resultStrings, resultStatus, resultRequestID}
86: End Function
87:
88: Protected Overridable Function CreateApiPath(ByVal subscript As String) As Uri
89: Return New Uri(String.Format(SQL_API_PATH, subscript))
90: End Function
91:
92: Protected Overridable Function CreateCertification(ByVal thumbPrintString As String) As X509Certificate2
93: Dim certStore As X509Store = New X509Store(StoreName.My, StoreLocation.CurrentUser)
94: certStore.Open(OpenFlags.ReadOnly)
95:
96: Dim certCollection As X509Certificate2Collection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbPrintString, False)
97: certStore.Close()
98:
99: If certCollection.Count <= 0 Then
100: Throw New ApplicationException("証明書がありません")
101: End If
102: Return certCollection(0)
103: End Function
104:
105: Protected Overridable Sub AddRequestHeader(ByVal wq As WebRequest)
106: wq.Headers.Add("x-ms-version", "1.0")
107: End Sub
108:
109: Protected Overridable Sub SetHttpMethod(ByVal wq As WebRequest)
110: wq.Method = "POST"
111: End Sub
112:
113: Protected Overridable Function CreateBodyMessage(ByVal adminAccount As String, ByVal adminPassword As String, ByVal locationStrings As String) As String
114: Dim xmlBody = "<?xml version=""1.0"" encoding=""utf-8""?>" + ControlChars.NewLine +
115: "<Server xmlns=""http://schemas.microsoft.com/sqlazure/2010/12/"">" + ControlChars.NewLine +
116: " <AdministratorLogin>" + adminAccount + "</AdministratorLogin>" + ControlChars.NewLine +
117: " <AdministratorLoginPassword>" + adminPassword + "</AdministratorLoginPassword>" + ControlChars.NewLine +
118: " <Location>" + locationStrings + "</Location>" + ControlChars.NewLine +
119: "</Server>"
120: Return xmlBody
121: End Function
122:
123: End Class
かなり力技なロジックですw
そしてこれを継承して作成した SQL Azure サーバー新規作成アクティビティはこうなります。
1: Imports System.Activities
2:
3: Public Class CreateSQLAzureServerActivity
4: Inherits AzureActivityBase
5:
6: Public Sub New()
7: Me.DisplayName = "SQL Azure サーバーを作成する"
8: End Sub
9:
10: End Class
まぁ、ベースロジックはこの新規作成でしたので・・・
続いては SQL Azure サーバーの列挙アクティビティです。
1: Imports System.Activities
2: Imports System.Net
3:
4: Public Class EnumurateSQLAzureServerActivity
5: Inherits AzureActivityBase
6:
7: Public Property ServerName As String
8:
9: Public Sub New()
10: Me.DisplayName = "SQL Azure サーバー一覧を取得する"
11: End Sub
12:
13: Protected Overrides Sub SetHttpMethod(ByVal wq As WebRequest)
14: wq.Method = "GET"
15: End Sub
16:
17: Protected Overrides Function CreateBodyMessage(adminAccount As String, adminPassword As String, locationStrings As String) As String
18: Return Nothing
19: End Function
20: End Class
リクエストのメソッドを GET にし、本体のメッセージは何も送信しないようにしています。
次は SQL Azure サーバーの削除アクティビティ。
1: Imports System.Activities
2: Imports System.Net
3:
4: Public Class DropSQLAzureServerActivity
5: Inherits AzureActivityBase
6:
7: Public Property ServerName As String
8:
9: Public Sub New()
10: Me.DisplayName = "SQL Azure サーバーを削除する"
11: End Sub
12:
13: Protected Overrides Sub SetHttpMethod(ByVal wq As WebRequest)
14: wq.Method = "DELETE"
15: End Sub
16:
17: Protected Overrides Function CreateBodyMessage(adminAccount As String, adminPassword As String, locationStrings As String) As String
18: Return Nothing
19: End Function
20:
21: Protected Overrides Function CreateApiPath(subscript As String) As System.Uri
22: Return New Uri(String.Format(SQL_API_PATH, subscript) + "/" + Me.ServerName)
23: End Function
24:
25: End Class
SQL Azure サーバーの削除は API のパスに対象となるサーバー名が必要になりますので、アドレスを作成している部分をオーバーライドしています。そして最後にパスワード変更アクティビティ。
1: Imports System.Activities
2:
3: Public Class ResetSQLAzurePasswordActivity
4: Inherits AzureActivityBase
5:
6: Public Property ServerName As String
7:
8: Public Sub New()
9: Me.DisplayName = "SQL Azure パスワードを変更する"
10: End Sub
11:
12: Protected Overrides Function CreateBodyMessage(adminAccount As String, adminPassword As String, locationStrings As String) As String
13: Dim xmlBody = "<?xml version=""1.0"" encoding=""utf-8""?>" + ControlChars.NewLine +
14: "<AdministratorLoginPassword xmlns=""http://schemas.microsoft.com/sqlazure/2010/12/"">" + ControlChars.NewLine +
15: adminPassword + ControlChars.NewLine +
16: "</AdministratorLoginPassword>"
17: Return xmlBody
18: End Function
19:
20: Protected Overrides Function CreateApiPath(subscript As String) As System.Uri
21: Return New Uri(String.Format(SQL_API_PATH, subscript) + "/" + Me.ServerName + "?op=ResetPassword")
22: End Function
23:
24: End Class
こちらも先程の削除と似ています。送信する本文として、変更後のパスワードを設定した形で POST メソッドにて送信します。
0 件のコメント:
コメントを投稿