Ansibleで、クライアントPCのファイルの存在チェック
Ansibleを使うとき、クライアント側の実行結果をトリガーにして何かする場合、 local_actionとregisterモジュールを組み合わせれば良い。
クライアントPC側で、あるファイルの存在を確認するためには、statモジュールを使う。
使用例
一般的なAnsibleのディレクトリ構造が以下のようにあり、commonは、
config.ymlをリモートマシンに送るrolesである。
tree . . ├── inventory │ └── hosts ├── roles │ └── common │ ├── files │ │ └── config.yml │ └── tasks │ └── main.yml └── site.yml
roles/common/tasks/main.yml の中身は次のように書いた。
ここでは、config.ymlが存在していれば、ファイルをリモートに転送して、
無ければ、ファイルの転送をスキップするように振り分ける。
# roles/common/tasks/main.yml - name: check config.yml exists in local local_action: stat path="roles/common/files/config.yml" register: file ignore_errors: True - name: copy config.yml to remote copy: src=config.yml dest=~/config.yml when: file.stat.exists
config.ymlがある場合
ansible-playbook -i inventory/hosts site.yml PLAY *************************************************************************** TASK [setup] ******************************************************************* ok: [***.***.***.***] TASK [common : check config.yml exists in local] ******************************* ok: [***.***.***.***] TASK [common : copy config.yml to remote] ************************************** changed: [***.***.***.***] PLAY RECAP ********************************************************************* ***.***.***.*** : ok=3 changed=1 unreachable=0 failed=0
config.ymlがない場合
ansible-playbook -i inventory/hosts site.yml PLAY *************************************************************************** TASK [setup] ******************************************************************* ok: [***.***.***.***] TASK [common : check config.yml exists in local] ******************************* ok: [***.***.***.***] TASK [common : copy config.yml to remote] ************************************** skipping: [***.***.***.***] PLAY RECAP ********************************************************************* ***.***.***.*** : ok=2 changed=0 unreachable=0 failed=0
Designate の413エラーの対処
OpenStack Designate で、ゾーン登録時に、エラーが出たので対応方法を残しておく。
下記の作業は、designateが置いてあるホストで、行う。
事象
ゾーン登録時に、下記のエラーが出た。
413 Request Entity Too Large
ソースコードを調べると、どうやら、Designateで持っているゾーン登録の閾値に達しているらしい。
ゾーンの上限値は、10。
$ curl http://localhost:9001/v1/quotas/noauth-project { "api_export_size": 1000, "recordset_records": 20, "zone_records": 500, "zone_recordsets": 500, "zones": 10 }
対応
ゾーン登録の上限値を更新する。
designate.confのapiのquotasを有効にしていることを確認する。
$ grep 'quotas' /var/lib/designate/etc/designate/designate.conf enabled_extensions_v1 = diagnostics, quotas, reports, sync, touch enabled_extensions_v2 = quotas, reports
API経由で、上限値を更新する。
$ curl -X PUT -H 'Accept: application/json' -H 'Content-Type: application/json' -d '{"zones": 100}' http://localhost:9001/v1/quotas/noauth-project { "api_export_size": 1000, "recordset_records": 20, "zone_records": 500, "zone_recordsets": 500, "zones": 100 }
参考
OpenStack Keystoneで、Designateを認証する
Designateは、既にインストールされていることを前提とする。
OpenStack Designate を試す : あかぎメモ
ちなみに、これで、Designate の仮装環境を用意した。
ここで紹介すること
- KeyStone セットアップ
- テナント登録
- DesignateへのKeystone設定
- Keystoneを使った認証デモ
OSは、Ubuntu14.04を使う。
Keystone セットアップ
インストール
# apt-get -y update # apt-get -y install keystone
データベース、ユーザ作成
データベースは、MariaDBを使う。
# mysql -uroot -e "CREATE DATABASE keystone;" # mysql -uroot -e "GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'keystone';" # mysql -uroot -e "GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY 'keystone';"
管理トークン発行
# openssl rand -hex 10
b5fca4a6d7e3ba1d69ac
設定ファイル変更
管理トークン、データベース、ログディレクトリ情報を追記する。
# diff -u /etc/keystone.conf.sample /etc/keystone/keystone.conf --- /etc/keystone.conf.sample 2016-01-14 16:59:04.665864893 +0900 +++ /etc/keystone.conf 2016-01-15 10:58:45.350297815 +0900 @@ -10,6 +10,7 @@ # paste application pipelines (for example, in keystone-paste.ini). (string # value) #admin_token = ADMIN +admin_token = b5fca4a6d7e3ba1d69ac # The base public endpoint URL for Keystone that is advertised to clients # (NOTE: this does NOT affect how Keystone listens for connections). Defaults @@ -141,6 +142,7 @@ # is ignored if log_config_append is set. (string value) # Deprecated group/name - [DEFAULT]/logdir #log_dir = <None> +log_dir = /var/log/keystone # (Optional) Uses logging handler designed to watch file system. When log file # is moved or removed this handler will open a new log file with specified path @@ -560,6 +562,7 @@ # Deprecated group/name - [DATABASE]/sql_connection # Deprecated group/name - [sql]/connection #connection = <None> +connection = mysql://keystone:keystone@127.0.0.1/keystone # The SQLAlchemy connection string to use to connect to the slave database. # (string value)
ログディレクトリ作成
# mkdir /var/log/keystone # chown keystone:keystone /var/log/keystone
テーブル作成
# keystone-manage db_sync
起動
# service keystone restart keystone stop/waiting keystone start/running, process 7461
エンドポイントにアクセスできていれば、正しく起動している。
$ curl -s http://127.0.0.1:5000/v2.0 {"version": {"status": "stable", "updated": "2014-04-17T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}, {"base": "application/xml", "type": "application/vnd.openstack.identity-v2.0+xml"}], "id": "v2.0", "links": [{"href": "http://127.0.0.1:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/content/", "type": "text/html", "rel": "describedby"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf", "type": "application/pdf", "rel": "describedby"}]}}
Keystone へテナント、ユーザ、ロール作成
python-keyclientを使用する。
python-keyclient インストール
# git clone https://github.com/openstack/python-keystoneclient.git # cd ~/python-keystoneclient # python install -r requirements.txt
Keystoneにテナントやユーザ、ロールを作成するPython スクリプト
Designateのエンドポイント http://10.200.19.40:9001/v1 に対して、
DNSaasというテナントを作成する。
adminUserというユーザに対して、パスワードは、secretwordでユーザ作成する。
#!/usr/bin/python # ./keystone_create.py from keystoneclient.v2_0 import client component_url = 'http://10.200.19.40:9001/v1' token = 'b5fca4a6d7e3ba1d69ac' endpoint = 'http://10.200.19.40:35357/v2.0' tenant_name = 'DNSaas' description = 'test' username = 'adminUser' password = 'secretword' role = 'admin' service_name='designate' service_type='dnsaas' keystone = client.Client(token=token, endpoint=endpoint) print keystone print keystone.tenants.create( tenant_name=tenant_name, description=description, enabled=True) tenants = keystone.tenants.list() my_tenant = [x for x in tenants if x.name == tenant_name][0] my_user = keystone.users.create( name=username, password=password, tenant_id=my_tenant.id) role = keystone.roles.create(role) keystone.roles.add_user_role(my_user, role, my_tenant) service = keystone.services.create( name=service_name, service_type=service_type, description=description) keystone.endpoints.create( region='RegionOne', service_id = service.id, publicurl=component_url, adminurl=component_url, internalurl=component_url)
管理用トークンをヘッダーに追加して、登録されたテナントを確認する。
$ curl -H 'X-Auth-Token: b5fca4a6d7e3ba1d69ac' http://10.200.19.40:35357/v2.0/tenants {"tenants_links": [], "tenants": [{"description": "hoge", "enabled": true, "id": "beac3004ba344ddc8d4e9be13e77ce0e", "name": "DNSaas"}]}
Designateで、Keystone認証
designate.confに、以下を追加、変更する。
認証方法に関して、
auth_strategy = keystone
認証トークンに関して、
[keystone_authtoken] auth_host = 127.0.0.1 auth_port = 35357 auth_protocol = http admin_tenant_name = DNSaas admin_user = adminUser admin_password = secretword
Designateを再起動する。
# cd /etc/init.d # ls designate-* | xargs -I@ service @ restart
通常アクセスした時に、認証エラーになることを確認する。
# curl http://127.0.0.1:9001/v1
Authentication required
Keystone 認証
- Keystoneに、ユーザとパスワード情報を渡す。テナントへのアクセストークンを発行する。
- テナントへのアクセストークンとテナント名をKeystoneに渡して、Designateへのアクセストークンを発行する。
- アクセストークンを用いて、Designateのエンドポイントへアクセスする。
# アクセストークンを取得するPython スクリプト
#!/usr/bin/python import json from httplib import HTTPConnection keystone_unscoped = '127.0.0.1:5000' username='adminUser' password='secretword' conn = HTTPConnection(keystone_unscoped) header = {'Content-Type':'application/json'} req = {'auth': {'passwordCredentials': {'username': username, 'password': password }}} json_req = json.dumps(req) conn.request('POST','/v2.0/tokens', json_req, header) json_res = json.loads(conn.getresponse().read()) access_token_id = json_res["access"]["token"]["id"] conn.close() conn = HTTPConnection(keystone_unscoped) header = {'X-Auth-Token': access_token_id, 'Content-Type':'application/json'} conn.request('GET', '/v2.0/tenants', None, header) print json.dumps(json.load(conn.getresponse()), indent=2) conn.close() tenant = raw_input("\ntenant name: ") conn = HTTPConnection(keystone_unscoped) header = {'Content-Type':'application/json'} req = {'auth': {'tenantName': tenant, 'token': {'id':access_token_id}}} json_req = json.dumps(req) conn.request('POST', '/v2.0/tokens', json_req, header) json_res = json.loads(conn.getresponse().read()) print "===== below is access_token =====" print json_res["access"]["token"]["id"] conn.close()
使い方
$ chmod 755 ./get_auth_token.py $ ./get_auth_token.py { "tenants": [ { "enabled": true, "description": "test", "name": "DNSaas", "id": "5a30147f9c184fc6b618fc16e06c2b66" } ], "tenants_links": [] } tenant name: DNSaas ===== below is access_token ===== MIIE-QYJKoZIhvcNAQcCoIIE7jCCBOoCAQExDTALBglghkgBZQMEAgEwggNLBgkqhkiG9w0BBwGgggM8BIIDOHsiYWNjZXNzIjogeyJ0b2tlbiI6IHsiaXNzdWVkX2F0IjogIjIwMTYtMDItMDlUMDM6MjE6NTYuMjM5MTU4IiwgImV4cGlyZXMiOiAiMjAxNi0wMi0wOVQwNDoyMTo1MloiLCAiaWQiOiAicGxhY2Vob2xkZXIiLCAidGVuYW50IjogeyJkZXNjcmlwdGlvbiI6ICJ0ZXN0IiwgImVuYWJsZWQiOiB0cnVlLCAiaWQiOiAiNWEzMDE0N2Y5YzE4NGZjNmI2MThmYzE2ZTA2YzJiNjYiLCAibmFtZSI6ICJEZXNpZ25hdGUgRE5TYWFzIn19LCAic2VydmljZUNhdGFsb2ciOiBbeyJlbmRwb2ludHMiOiBbeyJhZG1pblVSTCI6ICJodHRwOi8vMTAuMjAwLjE5LjQwOjkwMDEvdjEiLCAicmVnaW9uIjogIlJlZ2lvbk9uZSIsICJpbnRlcm5hbFVSTCI6ICJodHRwOi8vMTAuMjAwLjE5LjQwOjUwMDAvdjIuMCIsICJpZCI6ICIwYTdkZGNkZDZmODA0NjllYjMzZDJiZGQ5MmI2YzNkNyIsICJwdWJsaWNVUkwiOiAiaHR0cDovL2xvY2FsaG9zdDo5MDAxL3YxLyJ9XSwgImVuZHBvaW50c19saW5rcyI6IFtdLCAidHlwZSI6ICJkbnNhYXMiLCAibmFtZSI6ICJkZXNpZ25hdGUifV0sICJ1c2VyIjogeyJ1c2VybmFtZSI6ICJhZG1pblVzZXIiLCAicm9sZXNfbGlua3MiOiBbXSwgImlkIjogImNkYTlmYmFhNjZhZTQzNTViZGViOWIwMjJjOTUzMzEzIiwgInJvbGVzIjogW3sibmFtZSI6ICJfbWVtYmVyXyJ9LCB7Im5hbWUiOiAiYWRtaW4ifV0sICJuYW1lIjogImFkbWluVXNlciJ9LCAibWV0YWRhdGEiOiB7ImlzX2FkbWluIjogMCwgInJvbGVzIjogWyI5ZmUyZmY5ZWU0Mzg0YjE4OTRhOTA4NzhkM2U5MmJhYiIsICJkNjY2MGVkMzU0NDE0OWU0Yjc4YWQ1NzUxNzI5ZjIzMCJdfX19MYIBhTCCAYECAQEwXDBXMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVW5zZXQxDjAMBgNVBAcMBVVuc2V0MQ4wDAYDVQQKDAVVbnNldDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tAgEBMAsGCWCGSAFlAwQCATANBgkqhkiG9w0BAQEFAASCAQBWYPlk24npFFVrciVovHYLIUueg5pgV0zRa2cWT8RoWUxXNTcbIbSDCyRh+rbDXx3eCZaafcnddjlYJhGzXp9PD5qgpUhj0tynNN0pZPNklDKAFZvZqtzf8pCGj3RPjmTg-lo2ff5hBpRwsl0TZWnF8S0q-Mx7IemVI48Sairehk0UJ8GkU12cLqeS2K4rRVEYdY81GAuErodlRHvkaRsm5WgjKFjE3TpMNT0xdS+IvKnsE5TRt-6O9pbX+sAp+SGg1fb+XHPIW6L5o6TrFbQtruuoSB7aHLKlY75kYXYaicNyVdsa-gMRuya-93CKdMdwcvDQ0s2IGGVcximTRi+Y
アクセストークンを使って、Designateのエンドポイントにアクセスする。
# ACCESS_TOKEN_ID="<上で出した文字列>" # curl -H "X-Auth-Token: $ACCESS_TOKEN_ID" http://127.0.0.1:9001/v1/servers { "servers": [ { "created_at": "2016-02-08T06:51:46.000000", "id": "06b696c2-b2e0-47ef-b348-de8e221e1b0b", "name": "ns1.example.com.", "updated_at": "2016-02-08T07:30:26.000000" }, { "created_at": "2016-02-08T07:30:26.000000", "id": "2c593756-a82c-4372-9587-c4a4489b6724", "name": "ns2.example.com.", "updated_at": null } ] }
参考
KeystoneのUnscoped TokenとScoped Tokenの違い - めもめも Software Defined Boden: OpenStack Keystone Workflow & Token Scoping
Designateの仮想環境作成は、ここを参考にした。
Jenkinsのジョブをコマンドラインから生成する
Jenkinsのジョブをコマンドラインから、生成する方法を調べてみた。
OSは、Ubuntu14.04。
結論から言うと、XMLファイルをjenkins-cli.jarの create-jobコマンドに与えればよい。
Jenkins CLI - Jenkins - Jenkins Wiki
以下の実行パスや、URLは各自の環境に読み替えること。
jenkins.example.comとなっている箇所は、自身のJenkinsが動作しているURLを指す。
テンプレート用のXMLファイル作成
生成するジョブのテンプレートとなるXMLファイルを作成する。 通常通り、UIからジョブを作成する。
ここでは、echo 'this is 01_job'
をする簡単な01_jobを作成する。
そうすると、サーバ内に、以下のようなファイルが作成される。
jenkins@ubuntu:~$ cat /var/lib/jenkins/jobs/01_job/config.xml <?xml version='1.0' encoding='UTF-8'?> <project> <actions/> <description>this is 01_job</description> <keepDependencies>false</keepDependencies> <properties/> <scm class="hudson.scm.NullSCM"/> <canRoam>true</canRoam> <disabled>false</disabled> <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding> <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding> <triggers/> <concurrentBuild>false</concurrentBuild> <builders> <hudson.tasks.Shell> <command>echo 'this is 01_job'</command> </hudson.tasks.Shell> </builders> <publishers/> <buildWrappers/>
Jenkins CLI
今回は、Jenkins CLIのcreate-jobコマンドを使い、ジョブを生成する。
Jenkins CLI は、コマンドラインから、Jenkinsを操作するためのjarファイルで、Jenkinsにパッケージされている。
まずは、自身のURL/jnlpJars/jenkins-cli.jar から、jenkins-cli.jar
をダウンロードする。
$ wget http://jenkins.example.com/jnlpJars/jenkins-cli.jar
また、http://jenkins.example.com/cli のようなURLで、使えるコマンド一覧、 ヘルプが参照できる。
ダウンロードしたら、実際に使ってみる。
$ java -jar jenkins-cli.jar -s jenkins.example.com/ -i ~/.ssh/id_rsa version 1.627 $ java -jar jenkins-cli.jar -s http://jenkins.example.com/ -i ~/.ssh/id_rsa who-am-i Authenticated as: togashik Authorities: authenticated
-s には、jenkins のURL、-i には、秘密鍵を指定する。 秘密鍵は、ログインユーザに登録した公開鍵とペアになっているものを指定する。
早速、create-job
を使い、ジョブを生成してみる。
最後に与えた02_jobは、新規生成するジョブ名を指す。
$ cat /var/lib/jenkins/jobs/01_job/config.xml | java -jar jenkins-cli.jar -s http://jenkins.example.com/ -i ~/.ssh/id_rsa create-job 02_job
これで、ジョブが生成できたはずなので、get-job
で確認してみる。
$ java -jar jenkins-cli.jar -s http://jenkins.example.com/ -i ~/.ssh/id_rsa get-job 02_job <?xml version='1.0' encoding='UTF-8'?> <project> <actions/> <description>this is 01_job</description> <keepDependencies>false</keepDependencies> <properties/> <scm class="hudson.scm.NullSCM"/> <canRoam>true</canRoam> <disabled>false</disabled> <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding> <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding> <triggers/> <concurrentBuild>false</concurrentBuild> <builders> <hudson.tasks.Shell> <command>echo 'this is 01_job'</command> </hudson.tasks.Shell> </builders> <publishers/> <buildWrappers/>
ただし、これでは、02_jobは01_jobの単なるコピーなので、設定に含めたシェルスクリプトは
echo 'this is 01_job'
のままである。
これを、echo 'this is 02_job'
としたいとき等、読み込むxmlファイルを変更する必要がある。
delete-job
で先ほどのジョブを削除する。
$ java -jar jenkins-cli.jar -s http://jenkins.example.com/ -i ~/.ssh/id_rsa delete-job 02_job
create-job
で、再生成する。
$ sed 's/01_job/02_job/' /var/lib/jenkins/jobs/01_job/config.xml | java -jar jenkins-cli.jar -s http://jenkins.example.com/ -i ~/.ssh/id_rsa create-job 02_job
おまけ
コマンドラインから、生成したジョブを既存のビューに追加する
Jenkins CLIを使う方法を試そうとしたけど、うまくいかなかったので、力づくでやる。
つまり、ビュー構造が定義されているconfig.ymlを手動で変更して、読み込ませる。
02_jobをblogというビューに追加する。
$ sed -n '/^\s*<name>blog/,/^\s*<\/jobNames>/p' /var/lib/jenkins/config.xml <name>blog</name> <filterExecutors>false</filterExecutors> <filterQueue>false</filterQueue> <properties class="hudson.model.View$PropertyList"/> <jobNames> <comparator class="hudson.util.CaseInsensitiveComparator"/> <string>01_job</string> </jobNames> $ sed -i.bak -e '/<string>01_job<\/string>/a\ \ \ \ \ \ \ \ <string>02_job<\/string>' /var/lib/jenkins/config.xml $ sed -n '/^\s*<name>blog/,/^\s*<\/jobNames>/p' /var/lib/jenkins/config.xml <name>blog</name> <filterExecutors>false</filterExecutors> <filterQueue>false</filterQueue> <properties class="hudson.model.View$PropertyList"/> <jobNames> <comparator class="hudson.util.CaseInsensitiveComparator"/> <string>01_job</string> <string>02_job</string> </jobNames>
Jenkinsを安全に再起動する。
$ java -jar jenkins-cli.jar -s http://jenkins.example.com/ -i ~/.ssh/id_rsa safe-restart
参考
Firefoxの証明書警告を自動でスキップする
自動テストで、Seleniumを使っているが、自己割当証明書のドメインをテストする たびに、例外証明書として、登録するのが手間だと思ったので、自動化でできないか調べてみた。
証明書警告とは、このような表示。。
自動で、証明書警告をスキップするためには、FirefoxアドオンのSkip Cert Errorを使う。
インストールしたら、設定を開き次のように設定を済ませる。
Domain whitelist には、ドメインもしくはIPの一部にマッチした場合、証明書の検証をスキップしてくれる。 複数のサブドメインを利用することがある場合は、楽に設定を済ますことが出来る。
もっとおすすめの方法があれば、ぜひ教えてください。
ちなみに、Firefoxプロファイルの設定は、ここらへんが参考になると思います。