はじめに
BIG-IPのData Group Listの更新を行なっている人には、このテンプレ的な作業をiCRで行いたい(例えば自動化したい)、という需要があると思いますが、ちょっと思ったようにはいかないので。
なお、ここで取り扱うData Group Listは、BIG-IP内にレコードを登録するInternalタイプのものであり、外部ファイルを取り込むexternalタイプのData Group Listではありません。
参照情報
このページの内容は、DevCentralの以下のURLで説明されています。F5の技術者によるサンプルコードもあるので、この問題に取り組む人は参照するのが良いかと思います。
DevCentral: add value in data group via REST API
免責事項
本ページの内容に誤り等があり、参考にされた方がなんらかの損害を被った場合、一切の責任は負いません。
問題
例えば、下記のような「test-data-group」という名前のData Group Listがあるとします。すでにレコードが3件入っています。
(tmos)# list ltm data-group internal test-data-group
ltm data-group internal test-data-group {
records {
www1.example.co.jp {
data Pool_www1
}
www2.example.co.jp {
data Pool_www2
}
www3.example.co.jp {
data Pool_www3
}
}
type string
}
ここに新規レコードとして、name="www3.example.co.jp", value="Pool_www4" を追加するとします。
この追加作業をtmshで行う場合、以下のようなコマンドになります。
(tmos)# modify ltm data-group internal test-class records add { "www4.example.co.jp" { data "Pool_www4" } }
iCRではどうなるでしょう。上記のtmshコマンドを移植しようと考えた場合、modifyコマンドなので、PATCHメソッドを使えば移植できる気がするので、次のようなHTTPリクエストが考えられます。
curl -sku admin:admin -H "Content-Type: application/json" \
-X PATCH \
-d '{"records":[{"name":"www4.example.co.jp", "data":"Pool_www4"}]}' \
https://bigip-ve/mgmt/tm/ltm/data-group/internal/test-data-group
しかし、上記のようなリクエストを実行して、変更後のData Group Listを確認してみると、
(tmos)# list ltm data-group internal test-data-group
ltm data-group internal test-data-group {
records {
www4.example.co.jp {
data Pool_www4
}
}
type string
}
このとおり、Data Group Listのレコードは、元々存在していたレコードが全て消えてしまい、追加しようとした一件だけになってしまいます。
解説
iCRにおいて、Data Group Listのレコードは、一つの大きな配列として扱われます(少なくともv12では)。iCRでData Group listの更新を行う場合、レコード全体が一つの設定値になるというイメージで、全部のレコードを送信する必要があります。上記の例では追加したいレコードのみを送信した為に、そのレコードでData Group Listが上書きされてしまったわけです。
つまり、Data Group Listにレコードを追加する手順は、次の3ステップになります。
- 変更前のData Group Listの全レコードを受け取る
- そこに新規追加のレコードを追加する
- 変更後となる全レコードを送信する
サンプルコード
Pythonで、上記の3ステップを行うサンプルコードを作成しました。
# (準備)iControlのセッションを用意
import requests
import json
b = requests.session()
b.auth = ('admin', 'admin')
b.verify = False
b.headers.update({'Content-Type':'application/json'})
# 1. 変更前のData Group Listの全レコードを取得
data_group_str = b.get('https://bigip-ve/mgmt/tm/ltm/data-group/internal/test-data-group')
data_group = json.loads(data_group_str.text)
records = data_group['records']
このタイミングでは、recordsは次のようにになっています。
[{'data': 'Pool_www1', 'name': 'www1.example.co.jp'},
{'data': 'Pool_www2', 'name': 'www2.example.co.jp'},
{'data': 'Pool_www3', 'name': 'www3.example.co.jp'}]
recordsに新規レコードを追加します。
new_record = {'name':'www4.example.co.jp', 'data':'Pool_www4'}
records.append(new_record)
これにより、recordsは次のようになります。
[{'data': 'Pool_www1', 'name': 'www1.example.co.jp'},
{'data': 'Pool_www2', 'name': 'www2.example.co.jp'},
{'data': 'Pool_www3', 'name': 'www3.example.co.jp'},
{'data': 'Pool_www4', 'name': 'www4.example.co.jp'}]
最後に、recordsを、JSONに変換してiControlで送信します。
payload['records'] = records
res = b.patch('https://bigip-ve/mgmt/tm/ltm/data-group/internal/test-data-group', data=json.dumps(payload))
tmshコマンドで確認してみます。
(tmos)# list ltm data-group internal test-data-group
ltm data-group internal test-data-group {
records {
www1.example.co.jp {
data Pool_www1
}
www2.example.co.jp {
data Pool_www2
}
www3.example.co.jp {
data Pool_www3
}
www4.example.co.jp {
data Pool_www4
}
}
type string
}
無事、元のレコード3件に、新しいレコード1件が追加されました。
このページの内容は、以上です。