DUICUO

Ansible 条件文の紹介と使用

序文

多くの場合、特定のシナリオでは、プレイブックの結果は変数、ファクト、または前のタスクの実行結果に依存します。また、前のタスクから返された結果に基づいて、後続のタスクの実行方法を決定する必要がある場合もあります。このような状況では、条件文が必要になります。

Ansible での条件文の使用例:

  • ターゲット ホストには、タスクを実行するにはターゲット ホストで Red Hat が実行されている必要があるなどのハード制約が定義されます。
  • コマンドの出力をキャプチャし、さまざまな出力結果に基づいてさまざまなタスクをトリガーします。
  • さまざまなターゲット ホストの事実に基づいて、さまざまなタスクが定義されます。
  • ターゲット マシンの CPU またはメモリのサイズに基づいて、関連するアプリケーションのパフォーマンスを最適化します。
  • これは、サービスを再起動する必要があるかどうかを判断するために、サービスの構成ファイルが変更されているかどうかを判断するために使用されます。

次のセクションでは、よく使用される条件判断をいくつか紹介します。

キーワード

1. whenキーワードの使用

Ansibleでは、条件文で最もよく使われるキーワードは「when」です。例えば、パッケージをインストールする場合、ホストのオペレーティングシステムの種類を指定する必要がありますが、「when」ステートメントを使って判断を下すことができます。「when」キーワードの後に​​はPython式が続き、任意の変数またはファクトを使用できます。式が「false」を返した場合、現在のタスクはスキップされます。

例:

 ---
-名前: wgetパッケージをインストールする
ホスト:全員
タスク:
- name : wgetをインストールする
おいしい:
名前: wget
状態:インストール済み
ansible_os_family == "RedHat"の場合

2. 比較演算子と一緒に使用する場合

上記の例では、「==」比較演算子を使用しました。Ansible は以下の比較演算子もサポートしています。

  • ==: 2つのオブジェクトの等価性を比較します。等しい場合はtrueを返します。文字列と数値の比較に使用できます。
  • !=: 2 つのオブジェクトが等しくないかどうかを比較します。等しくない場合、式は true になります。

左側の値が右側の値より大きい場合、式は true になります。

  • <: 2 つのオブジェクトのサイズを比較します。左側の値が右側の値より小さい場合、式は true になります。

=: 2 つのオブジェクトのサイズを比較します。左側の値が右側の値以上の場合は true を返します。

  • <=: 2 つのオブジェクトのサイズを比較します。左側の値が右側の値以下の場合、式は true になります。

のように:

 ansible_disibution == "CentOS"の場合
ansible_machine == "x86_64"の場合
場合: max_memory <= 512

3. 論理演算子

  • AND: 論理 AND。左と右の式の両方が true の場合に true を返します。
  • OR: 論理 OR。左または右の式のいずれかが true の場合に true を返します。
  • NOT: 論理否定。式を否定します。
  • (): 複数の式を組み合わせて 1 つの大きな式を形成する場合、その組み合わせ内のすべての式は論理 AND 演算されます。
 #ロジック
ansible_disibution == "CentOS"かつansible_disibution_major_vsion == "7"の場合
#論理
ansible_disibution == "RedHat"またはansible_disibution == "Fedora"の場合
いつ
- ansible_disibution_vsion == "7.9"
- ansible_kernel == "3.10.0-327.el7.x86_64"
#併用
いつ=>
( ansible_disibution == "RedHat"かつansible_disibution_major_vsion == "7" )
または
( ansible_disibution == "Fedora"かつansible_disibution_major_vsion == "28" )

例:

 - name : forewalld をアンインストールし停止する
ホスト: dbsrvs
タスク:
-名前: firewalldをアンインストールする
yum : pkg = firwalld状態=存在しない
ansible_disibution == "CentOS"かつansible_disibution_major_vsion == "7"の場合
タグ: uninstall_firewalld

- name : iptablesを停止し無効にする
シェル: systemctl stop firewalld . service && systemctl disable firewalld && systemctl stop iptables && systemctl disable iptables
ansible_disibution == "CentOS"かつansible_disibution_major_vsion == "7"の場合
タグ: stop_firewalld
# # #
- name : postfix動作している場合はhttpdを再起動します
ホスト: dbsrvs
タスク:
- name : Postfixサーバーのステータスを取得する
コマンド: / usr / bin / systemctl is -アクティブなpostfix
ignore_errors :はい
レジスタ結果
- name : postfix の状態基づいてapache httpdを再起動する
サービス
名前: httpd
状態:再起動
場合: result.rc == 0

条件付き判断をテストする

条件文を使用して、tpath 内のパスが存在するかどうかを判断します。

 -ホスト: dbsrvs
変数:
tpath : / ayunwSky
タスク:
-デバッグ:
メッセージ: "ファイルが存在します"
tpathが存在する場合

パラメータの説明:

  • `is exists`: パスが存在する場合は true を返します。
  • `is not exists`: パスが存在しない場合は true を返します。
  • 条件式全体の前に `not` を使用して否定することもできます。

 - ホスト: dbsrvs
変数:
tパス: /ayunwSky
タスク:
- デバッグ:
メッセージ: 「ファイルが存在しません」
場合: tpathが存在しない

`exists` メソッド以外にも、次のように結果を判断する方法があります。

変数を決定する
  • defined: 変数が定義されているかどうかを判断します。定義されている場合は true を返します。
  • undefined: 変数が未定義かどうかを判断します。定義されていない場合は true を返します。
  • none: 変数の値が空かどうかを判定します。変数が定義されていて、その値が空の場合はtrueを返します。
 -ホスト: dbsrvs
事実収集:いいえ
変数:
tvar : "テスト"
tvar1 :
タスク:
-デバッグ:
メッセージ: "tvar が定義されています"
tvar定義されている場合
-デバッグ:
メッセージ: "tvar2 は未定義です"
tvar2未定義の場合
-デバッグ:
メッセージ: "tvar1 はなしです"
tvar1noneの場合

実行結果を決定する

  • 成功または成功: タスク実行結果から返された情報に基づいて、タスクの実行ステータスを判定します。タスクが正常に実行された場合はtrueを返します。
  • 失敗または失敗: タスクの実行に失敗した場合は true を返します。
  • change または changed: タスクの実行ステータスが変更された場合は true を返します。
  • skip または skipped: タスクがスキップされた場合は true を返します。
 -ホスト: dbsrvs
事実収集:いいえ
変数:
doshell : true
タスク:
-シェル: 'cat /ayunwSky/allenjol'
いつdoshell
レジスタ結果
ignore_errors : true
-デバッグ:
メッセージ: 「成功」
いつ結果成功
-デバッグ:
メッセージ: 「失敗しました」
場合結果失敗です
-デバッグ:
メッセージ: "変更されました"
場合結果変化します
-デバッグ:
メッセージ: "スキップ"
場合:結果スキップ

パスを決定する

  • file: 指定されたパスがファイルかどうかを判断します。ファイルの場合は true を返します。
  • ディレクトリ: 指定されたパスがディレクトリであるかどうかを判断します。ディレクトリである場合は true を返します。
  • link: 指定されたパスがシンボリック リンクかどうかを判断します。シンボリック リンクの場合は true を返します。
  • mount: 指定されたパスがマウント ポイントかどうかを判断します。マウント ポイントの場合は true になります。
  • exists: 指定されたパスが存在するかどうかを確認し、存在する場合は true を返します。

すべてのパス関連の判断は、制御される側のパスではなく、マスター制御側のパスを参照します。

 -ホスト: dbsrvs
事実収集:いいえ
変数:
tpath1 : "/ayunwSky/allenjol"
tpath2 : "/ayunwSky"
タスク:
-デバッグ:
メッセージ: "ファイル"
tpath1ファイル場合
-デバッグ:
メッセージ: "ディレクトリ"
tpath2ディレクトリ場合

文字列を決定する

  • lower: 文字列内のすべての文字が小文字かどうかを判断します。小文字の場合は true を返します。
  • upper: 文字列内のすべての文字が大文字かどうかを判断します。大文字の場合は true を返します。
 -ホスト: dbsrvs
事実収集:いいえ
変数:
s1 : 「アユンウ」
s2 : 「アユンウ」
タスク:
-デバッグ:
メッセージ: "s1 はすべて小文字です"
s1低い場合
-デバッグ:
メッセージ: "s2 はすべて大文字です"
s2上側の場合

割り切れるかどうかを決定する

  • even: 数値が偶数かどうかを判断します。偶数の場合は true になります。
  • odd: 数値が奇数かどうかを判断します。奇数の場合は true を返します。
  • divisibleby(n): 指定された値が指定された値で割り切れるかどうかを判断します。割り切れる場合は true になります。
 -ホスト: dbsrvs
事実収集:いいえ
変数:
n1 : 5
n2 : 10
n3 : 20
タスク:
-デバッグ:
メッセージ: "n1 は偶数です"
n1偶数の場合
-デバッグ:
メッセージ: "n2は奇数です"
n2奇数の場合
-デバッグ:
メッセージ: "n3は正確に割り切れる
: n3( 3 )で割り切れる場合

その他のテスト方法

  1. version: 2つのバージョン番号の大きさを比較するか、指定されたバージョン番号と比較します。構文はversion("バージョン番号", "比較演算子")です。

バージョンで使用される比較演算子の説明:

  • より大きい: >, gt
  • より大きいか等しい: >=, ge
  • 未満: <, lt
  • 以下: <=, le
  • 等しい: =、==、eq
  • 等しくない: !=, <>, ne
 -ホスト: dbsrvs
変数:
バージョン1 : 1.2
バージョン2 : 1.3
タスク:
-デバッグ:
メッセージ: "v1 は v2 より大きいです"
場合: v1ビジョン( v2">" ) です
-デバッグ:
メッセージ: 「システムバージョン `ansible_distribution_vsion` は 7.3 より大きいです」
ansible_distribution_vsionvsion ( "7.3""gt" )の場合
  1. スーパーセット: あるリストが別のリストの親セットであるかどうかを判断します。
 -ホスト: dbsrvs
事実収集:いいえ
変数:

- 3
- 7
b : [ 1 , 3 , 4 , 5 , 7 , 9 ]
タスク:
-デバッグ:
メッセージ: 「AはBのサブセットです」
場合a部分集合b
-デバッグ:
メッセージ: 「BはAの親セットです」
bスーパーセットである場合( a )
  1. `in`: 文字列が別の文字列内に存在するかどうかを確認します。また、特定の値がリスト内に存在するかどうかを確認するためにも使用できます。
 -ホスト: dbsrvs
変数:
サポートされているディストリビューション:
-レッドハット
セントOS
タスク:
-デバッグ:
メッセージ: 「supported_distros 内の ` ansible_distribution `」
場合: ansible_distribution がサポートされているディストリビューション
  1. number: オブジェクトが数値かどうかを判定し、数値の場合は true を返します。
 -ホスト: dbsrvs
事実収集:いいえ
変数:
変数1 : 1
変数2 : "1"
var3 : a
タスク:
-デバッグ:
メッセージ: "var1 は数値です"
var1数値場合
-デバッグ:
メッセージ: "var2は文字列です"
var2文字列場合
-デバッグ:
メッセージ: "var3 は文字列です"
var3文字列場合

条件文とブロック

ブロック

`when` 文を使って条件を評価する場合、条件が真であれば対応するタスクが実行されます。しかし、これには問題があります。同じ条件で複数のタスクを実行する必要がある場合、タスクごとに全く同じ条件の `when` 文を記述しなければなりません。これは非常に面倒です。Ansible はこの問題を解決するより優れた方法、つまりブロックを提供します。

Ansibleでは、ブロックを使用して複数のタスクを1つのユニットとしてグループ化します。このユニットを条件付きで評価し、条件が満たされた場合にブロック内のすべてのタスクを実行します。

ブロックの使用に関する注意事項:

  • ブロックの名前を定義できます。
  • ブロック上で直接 `when` を使用できますが、ブロック上で直接 `loop` を使用することはできません。
 -ホスト: dbsrvs
タスク:
-名前: /etc/resolv.conf​​​を設定します
テンプレート
ソース: resolv.conf.j2
dest : /etc/resolv.conf
所有者:ルート
グループ:ルート
モード: 0644
-ブロック
- name : Ubuntu 16.04/etc/resolvconf/resolv.conf.d/baseファイルを確認する
テンプレート
ソース: resolv.conf.j2
dest : /etc/resolvconf/resolv.conf.d/base

-名前: Ubuntu 16.04DNS設定
テンプレート
ソース: resolv.conf.j2
dest : /etc/resolv.conf
ansible_distribution == "Ubuntu"かつansible_distribution_major_version == "16"の場合

レスキュー

`when` 文で使用されるだけでなく、`block` 文はエラー処理にも使用できます。ここで `rescue` キーワードが役立ちます。

 -ホスト: dbsrvs
タスク:
-ブロック
-シェル: 'ls /ayunwSky'
救助
-デバッグ:
メッセージ: '/ayunwSky は存在しません'

ブロック内のタスクが失敗した場合、レスキューブロック内のタスクが実行されます。ブロック内のタスクが正常に実行された場合、レスキューブロック内のタスクは実行されません。ブロック内に複数のタスクが含まれている場合、いずれかのタスクが失敗するとレスキューブロックが実行されます。ブロック内に複数のタスクを定義でき、同様にレスキューブロック内にも複数のタスクを定義できます。

いつも

rescue ブロック内のタスクはブロックが失敗した場合にのみ実行されますが、always ブロック内のタスクはブロックが成功するか失敗するかに関係なく実行されます。

 - ホスト: dbsrvs
タスク:
- ブロック:
- シェル: 'ls /ayunwSky'
レスキュー:
- デバッグ:
メッセージ: '/ayunwSky は存在しません'
いつも:
- デバッグ:
メッセージ: 'このタスクは常に実行されます'

条件文とエラー処理

失敗モジュール

シェルスクリプトでは、スクリプト実行の特定の段階で条件をチェックし、条件が満たされた場合にスクリプトを直ちに終了させる必要がある場合があります。シェルスクリプトでは、「exit」を呼び出すだけで終了できます。実際、プレイブックにも同様の機能を持つ fail モジュールがあります。

failモジュールは、現在のプレイブックの実行を終了するために使用されます。通常、条件文と組み合わせて使用​​され、条件が満たされたときに現在のプレイブックを終了します。

fail モジュールには、終了前にメッセージを印刷する msg という 1 つのパラメーターのみがあります。

 #failモジュールを使用してプレイブックの出力を中断する
-ホスト: dbsrvs
タスク:
-シェル: echo "テストです--エラー"
レジスタ結果

-失敗
メッセージ: 「条件が確立されました。プレイブックの実行を中断します」
場合: "result.stdout に 'error' があります"

-デバッグ:
メッセージ: 「プレイブックが停止したため、実行されません」

失敗したとき

`fail` と `when` を併用する場合、さらにシンプルな記述方法があります。それは `failed_when` です。Ansible は特定の条件が満たされると、自動的に失敗をトリガーします。

command_result でエラーが発生し、エラー出力に文字列「FAILED」が含まれている場合は、失敗ステータスが返されます。

 - name :このコマンドは失敗したときFAILEDと出力します
コマンド: / usr / bin /-コマンド- x - y - z
レジスタ: command_result
failed_when : "command_result.stderr で 'FAILED' が発生しました"

fail モジュールと when 条件文を直接使用します。

 - name :このコマンドは失敗したときFAILEDと出力します
コマンド: / usr / bin /-コマンド- x - y - z
レジスタ: command_result
ignore_errors : True

- name :コマンド成功しなかっ場合は再生失敗します
失敗:メッセージ= "コマンドが失敗しました"
when : " command_result.stderr および command_result.stderr 内の 'FAILED'"
  • Ansibleが実行中に失敗を返した場合、後続の操作は中止されます。そのため、`failed_when` は、特定の条件が満たされたときにプレイブックの実行を積極的に停止する方法としてよく使用されます。
  • Ansibleのデフォルトのエラー処理メカニズムは、エラーが発生すると実行を停止します。しかし、場合によってはエラーが計画的に発生することもあります。そのようなエラーを無視して、プレイブックの実行を継続させたい場合もあります。この場合、`ignore_errors` を使用することでエラーを無視し、プレイブックの実行を継続させることができます。

変更されたとき

リモートホストを制御して特定のタスクを実行させる場合、タスクがリモートホスト上で正常に実行され、ステータスが変化した場合には変更ステータス応答が返されます。ステータスが変化しなかった場合にはOKステータス応答が返されます。タスクがスキップされた場合はスキップステータス応答が返されます。`changed_when` を使用することで、レスポンスの変更ステータスを手動で変更できます。

 -シェル: / usr / bin / billybass -- mode = "私を川に連れて行って"
レジスタ: bass_result
#このタスクは、実行後にbass_result.rc の値が 2 でない場合にのみ、変更された状態に戻ります
changed_when : "bass_result.rc != 2"

#これは「変更」ステータスを報告しませ
-シェル壁の「ビープ」
# changed_when が false の場合、このタスクは実行後に変更された状態に戻ることはありません。
changed_when : False

ループ文での条件文の使用

  1. 10 より大きい値のみを出力します。

タスク:
- コマンド: echo `item`
ループ: [ 0, 2, 4, 6, 8, 10, 100, 130, 150 ]
場合: アイテム > 10

  1. MariaDB サーバーがルート パーティションにインストールされており、ルート パーティションに 200 MB 以上の空き領域があることを確認します。

 - 名前: ルートに十分なスペースがある場合は nginx をインストールします
おいしい:
名前: nginx
状態;最新
ループ: "` ansible_mounts `
item.mount == "/" かつ item.size_available > 200000000 の場合

これらが判断を下すためのほとんどの方法です。