1
1
package common
2
2
3
3
import (
4
+ "bytes"
4
5
"encoding/base64"
5
6
"encoding/json"
6
7
"fmt"
@@ -22,17 +23,24 @@ type SimAPIResponse struct {
22
23
Count int `json:"Count"`
23
24
}
24
25
25
- // GetUsedIPAddressesInMGW
26
- // MGW 内での利用されている IP アドレス一覧を取得する
27
- // 利用されている IPアドレス一覧を取得
28
- func GetUsedIPAddressesInMGW (accessToken string , accessTokenSecret string , zone string , mgwID string ) (map [string ]struct {}, error ) {
29
- // ベーシック認証
30
- auth := fmt .Sprintf ("%s:%s" , accessToken , accessTokenSecret )
26
+ // BASIC認証のAuthorizationヘッダが設定されたhttp.Header{}インスタンスを作成
27
+ func createHeadersWithBasicAuth (user string , password string ) http.Header {
28
+ auth := fmt .Sprintf ("%s:%s" , user , password )
31
29
encodedAuth := base64 .StdEncoding .EncodeToString ([]byte (auth ))
32
30
headers := http.Header {
33
31
"Authorization" : []string {"Basic " + encodedAuth },
34
32
}
35
33
34
+ return headers
35
+ }
36
+
37
+ // GetUsedIPAddressesInMGW
38
+ // MGW 内での利用されている IP アドレス一覧を取得する
39
+ // 利用されている IPアドレス一覧を取得
40
+ func GetUsedIPAddressesInMGW (accessToken string , accessTokenSecret string , zone string , mgwID string ) (map [string ]struct {}, error ) {
41
+ // BASIC認証
42
+ headers := createHeadersWithBasicAuth (accessToken , accessTokenSecret )
43
+
36
44
// モバイルゲートウェイ配下のSIMを全件取得するための URL の組み立て
37
45
baseURL := fmt .Sprintf ("https://secure.sakura.ad.jp/cloud/zone/%s/api/cloud/1.1/appliance/%s/mobilegateway/sims" , zone , mgwID )
38
46
queryParams := url.Values {}
@@ -152,3 +160,278 @@ func incrementIP(ip net.IP) {
152
160
}
153
161
}
154
162
}
163
+
164
+ type SimRegisterInfo struct {
165
+ ICCID string
166
+ PassCode string
167
+ }
168
+
169
+ // SIM作成APIのレスポンス
170
+ type SimCreateAPIResponse struct {
171
+ CommonServiceItem struct {
172
+ ID string `json:"ID"`
173
+ }
174
+ Success bool `json:"Success"`
175
+ IsOK bool `json:"is_ok"`
176
+ }
177
+
178
+ // APIのis_okレスポンス
179
+ type SimApiIsOkResponse struct {
180
+ IsOK bool `json:"is_ok"`
181
+ }
182
+
183
+ // APIのis_fatalレスポンス
184
+ type SimApiIsFatalResponse struct {
185
+ IsFatal bool `json:"is_fatal"`
186
+ Serial string `json:"serial"`
187
+ Status string `json:"status"`
188
+ ErrorCode string `json:"error_code"`
189
+ ErrorMsg string `json:"error_msg"`
190
+ }
191
+
192
+ // SIMの作成
193
+ func createSim (accessToken string , accessTokenSecret string , simID string , simPasscode string ) (string , error ) {
194
+ // BASIC認証
195
+ headers := createHeadersWithBasicAuth (accessToken , accessTokenSecret )
196
+
197
+ // SIM作成リクエストの組み立て
198
+ baseURL := "https://secure.sakura.ad.jp/cloud/zone/is1a/api/cloud/1.1/commonserviceitem"
199
+ body := fmt .Sprintf (`
200
+ {
201
+ "CommonServiceItem": {
202
+ "Name": "%s",
203
+ "Status": {
204
+ "ICCID": "%s"
205
+ },
206
+ "Remark": {
207
+ "PassCode": "%s"
208
+ },
209
+ "Provider": {
210
+ "Class": "sim"
211
+ }
212
+ }
213
+ }` , simID , simID , simPasscode )
214
+ bytesBody := []byte (body )
215
+ bufBody := bytes .NewBuffer (bytesBody )
216
+
217
+ // リクエスト送信
218
+ req , err := http .NewRequest ("POST" , baseURL , bufBody )
219
+ if err != nil {
220
+ return "" , fmt .Errorf ("HTTPクライアントの初期化に失敗しました...%s" , err .Error ())
221
+ }
222
+ req .Header = headers
223
+
224
+ client := & http.Client {}
225
+ resp , err := client .Do (req )
226
+ if err != nil {
227
+ return "" , fmt .Errorf ("HTTPクライアントの実行に失敗しました...%s" , err .Error ())
228
+ }
229
+ defer resp .Body .Close ()
230
+
231
+ // レスポンスの確認
232
+ respBody , err := io .ReadAll (resp .Body )
233
+ if err != nil {
234
+ return "" , fmt .Errorf ("SIM作成のレスポンスの読み込みに失敗しました...%s" , err .Error ())
235
+ }
236
+ if resp .StatusCode != http .StatusCreated {
237
+ // 認証情報の間違い
238
+ if resp .StatusCode == http .StatusUnauthorized {
239
+ return "" , fmt .Errorf ("アクセストークン、アクセストークンシークレットを確認してください。SIM作成に失敗しました" )
240
+ }
241
+
242
+ // 作成済み
243
+ if resp .StatusCode == http .StatusConflict {
244
+ // エラーにしないけどリソースIDは空
245
+ return "" , nil
246
+ }
247
+
248
+ // 認証エラーじゃない場合
249
+ var apiFatalRes SimApiIsFatalResponse
250
+ err = json .Unmarshal (respBody , & apiFatalRes )
251
+ if err != nil {
252
+ return "" , fmt .Errorf ("SIM作成のレスポンスのパースに失敗しました...%s" , err .Error ())
253
+ }
254
+ // レスポンスに含まれているエラーメッセージを返す
255
+ return "" , fmt .Errorf ("%s: (%s)%s" , apiFatalRes .Serial , apiFatalRes .Status , apiFatalRes .ErrorMsg )
256
+ }
257
+
258
+ var apiResponse SimCreateAPIResponse
259
+ err = json .Unmarshal (respBody , & apiResponse )
260
+ if err != nil {
261
+ return "" , fmt .Errorf ("SIM作成のレスポンスのパースに失敗しました...%s" , err .Error ())
262
+ }
263
+
264
+ // SIMのリソースIDを返す
265
+ return apiResponse .CommonServiceItem .ID , nil
266
+ }
267
+
268
+ // SIMのIPアドレス設定
269
+ func assignIPAddressToSim (accessToken string , accessTokenSecret string , simID string , ipAddress string ) error {
270
+ // BASIC認証
271
+ headers := createHeadersWithBasicAuth (accessToken , accessTokenSecret )
272
+
273
+ // 『SIMのIPアドレス指定』のリクエストの組み立て
274
+ baseURL := fmt .Sprintf ("https://secure.sakura.ad.jp/cloud/zone/is1a/api/cloud/1.1/commonserviceitem/%s/sim/ip" , simID )
275
+ body := fmt .Sprintf (`{
276
+ "sim": {
277
+ "ip": "%s"
278
+ }}` , ipAddress )
279
+ bytesBody := []byte (body )
280
+ bufBody := bytes .NewBuffer (bytesBody )
281
+
282
+ // リクエスト送信
283
+ req , err := http .NewRequest ("PUT" , baseURL , bufBody )
284
+ if err != nil {
285
+ return fmt .Errorf ("HTTPクライアントの初期化に失敗しました...%s" , err .Error ())
286
+ }
287
+ req .Header = headers
288
+
289
+ client := & http.Client {}
290
+ resp , err := client .Do (req )
291
+ if err != nil {
292
+ return fmt .Errorf ("HTTPクライアントの実行に失敗しました...%s" , err .Error ())
293
+ }
294
+ defer resp .Body .Close ()
295
+
296
+ // レスポンスの確認
297
+ respBody , err := io .ReadAll (resp .Body )
298
+ if err != nil {
299
+ return fmt .Errorf ("SIMのIPアドレス設定のレスポンスの読み込みに失敗しました...%s" , err .Error ())
300
+ }
301
+ if resp .StatusCode != http .StatusOK {
302
+ // 認証情報の間違い
303
+ if resp .StatusCode == http .StatusUnauthorized {
304
+ return fmt .Errorf ("アクセストークン、アクセストークンシークレットを確認してください。SIMのIPアドレス設定に失敗しました" )
305
+ }
306
+ // 認証エラーじゃない場合
307
+ var apiFatalRes SimApiIsFatalResponse
308
+ err = json .Unmarshal (respBody , & apiFatalRes )
309
+ if err != nil {
310
+ return fmt .Errorf ("SIMのIPアドレス設定のレスポンスのパースに失敗しました...%s" , err .Error ())
311
+ }
312
+ // レスポンスに含まれているエラーメッセージを返す
313
+ return fmt .Errorf ("%s: (%s)%s" , apiFatalRes .Serial , apiFatalRes .Status , apiFatalRes .ErrorMsg )
314
+ }
315
+
316
+ // 設定の成否を返す
317
+ var apiOkRes SimApiIsOkResponse
318
+ err = json .Unmarshal (respBody , & apiOkRes )
319
+ if err != nil {
320
+ return fmt .Errorf ("SIMのIPアドレス設定のレスポンスのパースに失敗しました...%s" , err .Error ())
321
+ }
322
+
323
+ if ! apiOkRes .IsOK {
324
+ return fmt .Errorf ("SIMのIPアドレス設定が失敗しました" )
325
+ }
326
+
327
+ return nil
328
+ }
329
+
330
+ // モバイルゲートウェイにSIMを登録
331
+ func assignSimToMgw (accessToken string , accessTokenSecret string , zone string , mgwID string , simID string ) error {
332
+ // BASIC認証
333
+ headers := createHeadersWithBasicAuth (accessToken , accessTokenSecret )
334
+
335
+ // 『モバイルゲートウェイにSIMを登録』のリクエストの組み立て
336
+ baseURL := fmt .Sprintf ("https://secure.sakura.ad.jp/cloud/zone/%s/api/cloud/1.1/appliance/%s/mobilegateway/sims" , zone , mgwID )
337
+ body := fmt .Sprintf (`{
338
+ "sim": {
339
+ "resource_id": "%s"
340
+ }}` , simID )
341
+ bytesBody := []byte (body )
342
+ bufBody := bytes .NewBuffer (bytesBody )
343
+
344
+ // リクエスト送信
345
+ req , err := http .NewRequest ("POST" , baseURL , bufBody )
346
+ if err != nil {
347
+ return fmt .Errorf ("HTTPクライアントの初期化に失敗しました...%s" , err .Error ())
348
+ }
349
+ req .Header = headers
350
+
351
+ client := & http.Client {}
352
+ resp , err := client .Do (req )
353
+ if err != nil {
354
+ return fmt .Errorf ("HTTPクライアントの実行に失敗しました...%s" , err .Error ())
355
+ }
356
+ defer resp .Body .Close ()
357
+
358
+ // レスポンスの確認
359
+ respBody , err := io .ReadAll (resp .Body )
360
+ if err != nil {
361
+ return fmt .Errorf ("モバイルゲートウェイにSIMを登録のレスポンスの読み込みに失敗しました...%s" , err .Error ())
362
+ }
363
+
364
+ if resp .StatusCode != http .StatusOK {
365
+ // 認証情報の間違い
366
+ if resp .StatusCode == http .StatusUnauthorized {
367
+ return fmt .Errorf ("認証に失敗しました...%s" , err .Error ())
368
+ }
369
+ // 認証エラーじゃない場合
370
+ var apiFatalRes SimApiIsFatalResponse
371
+ err = json .Unmarshal (respBody , & apiFatalRes )
372
+ if err != nil {
373
+ return fmt .Errorf ("モバイルゲートウェイにSIMを登録のレスポンスのパースに失敗しました...%s" , err .Error ())
374
+ }
375
+ // レスポンスに含まれているエラーメッセージを返す
376
+ return fmt .Errorf ("%s: (%s)%s" , apiFatalRes .Serial , apiFatalRes .Status , apiFatalRes .ErrorMsg )
377
+ }
378
+
379
+ // 設定の成否を返す
380
+ var apiOkRes SimApiIsOkResponse
381
+ err = json .Unmarshal (respBody , & apiOkRes )
382
+ if err != nil {
383
+ return fmt .Errorf ("モバイルゲートウェイにSIMを登録のレスポンスのパースに失敗しました...%s" , err .Error ())
384
+ }
385
+
386
+ if ! apiOkRes .IsOK {
387
+ return fmt .Errorf ("SIMのIPアドレス設定が失敗しました" )
388
+ }
389
+
390
+ return nil
391
+ }
392
+
393
+ // リスト内のSIMを登録する
394
+ func RegisterSimFromList (accessToken string , accessTokenSecret string , zone string , mgwID string , simList []SimRegisterInfo , ipList []string ) error {
395
+
396
+ if len (simList ) > len (ipList ) {
397
+ return fmt .Errorf ("登録対象のSIM %d 枚に対して割り当て可能なIPアドレスが %d 個しかありません" , len (simList ), len (ipList ))
398
+ }
399
+
400
+ ipListIndex := 0
401
+ for _ , sim := range simList {
402
+ // SIMを作成
403
+ fmt .Printf ("SIM登録(ICCID: %s)" , sim .ICCID )
404
+ simResourceId , err := createSim (accessToken , accessTokenSecret , sim .ICCID , sim .PassCode )
405
+ if err != nil {
406
+ fmt .Printf ("[FAILED]\n " )
407
+ return err
408
+ }
409
+ if simResourceId == "" {
410
+ //登録済みだからスキップ
411
+ fmt .Printf ("[SKIP]\n " )
412
+ continue
413
+ }
414
+ fmt .Printf ("[OK]" )
415
+
416
+ // MGWにSIMを登録
417
+ fmt .Printf (", モバイルゲートウェイに追加" )
418
+ err = assignSimToMgw (accessToken , accessTokenSecret , zone , mgwID , simResourceId )
419
+ if err != nil {
420
+ fmt .Printf ("[FAILED]\n " )
421
+ return err
422
+ }
423
+ fmt .Printf ("[OK]" )
424
+
425
+ // SIMにIPアドレスを設定
426
+ fmt .Printf (", IPアドレスを設定(%s)" , ipList [ipListIndex ])
427
+ err = assignIPAddressToSim (accessToken , accessTokenSecret , simResourceId , ipList [ipListIndex ])
428
+ if err != nil {
429
+ fmt .Printf ("[FAILED]\n " )
430
+ return err
431
+ }
432
+ fmt .Printf ("[OK]\n " )
433
+
434
+ ipListIndex ++
435
+ }
436
+ return nil
437
+ }
0 commit comments