例 4: フロー制御の追加 - AWS OpsWorks

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

例 4: フロー制御の追加

重要

AWS OpsWorks Stacks は新規顧客を受け付けなくなりました。既存のお客様は、2024 年 5 月 26 日までは、通常どおり OpsWorks コンソール、API、CLI、および CloudFormation リソースを使用できます。その時点で廃止されます。この移行に備えて、できるだけ早くスタックを AWS Systems Manager に移行することをおすすめします。詳細については、「AWS OpsWorks Stacks サポート終了に関する FAQ」および「AWS Systems Manager アプリケーションマネージャへの AWS OpsWorks Stacks アプリケーションの移行」を参照してください。

単なる Chef リソースの連なりであるレシピもあります。この場合、レシピを実行すると単純にリソースプロバイダーを 1 つずつ順番に実行します。ただし、より洗練された実行パスを持つ方が役に立つ場合が多くあります。以下に一般的なシナリオを 2 つ示します。

  • 同じリソースを異なる属性設定で複数回実行するレシピがほしい。

  • さまざまなオペレーティングシステムで異なる属性設定を使用したい。

レシピに Ruby の制御構造を組み込むことで、このようなシナリオに対処できます。このセクションでは、「例 3: ディレクトリの作成」のレシピを変更して両方のシナリオに対処する方法を説明します。

イテレーション

例 3: ディレクトリの作成」では、directoryリソースを使用してディレクトリまたはディレクトリチェーンを作成する方法を説明しました。ただし別々の 2 つのディレクトリ、/srv/www/config/srv/www/shared を作成したい場合があるかもしれません。各ディレクトリに別々のディレクトリリソースを実装することもできますが、非常に多数のディレクトリを作成する場合はこの方法は面倒です。以下のレシピは、このタスクを処理するよりシンプルな方法を示します。

[ "/srv/www/config", "/srv/www/shared" ].each do |path| directory path do mode 0755 owner 'root' group 'root' recursive true action :create end end

各サブディレクトリに対して別のディレクトリリソースを使用する代わりに、レシピではサブディレクトリのパスを含む文字列コレクションを使用します。Rubyの each メソッドはコレクションの各要素を最初のものから始めてそれぞれ 1 回ずつ実行します。要素の値はリソース内で path 変数で表されます。この場合はディレクトリパスを表します。この例を簡単に応用して、サブディレクトリをいくつでも作成できます。

レシピを実行するには
  1. createdir ディレクトリにとどまります。以下のいくつかの例で、ここのクックブックを使用します。

  2. kitchen destroy をまだ実行していない場合は実行して、新しいインスタンスで始められるようにします。

  3. default.rb のコードを例で置き換えて、kitchen converge を実行します。

  4. インスタンスにログインします。/srv の下に新しく作成されたディレクトリがあります。

ハッシュテーブルを使用して各イテレーションに 2 個の値を指定できます。以下のレシピは /srv/www/config および /srv/www/shared を、別モードでそれぞれ作成します。

{ "/srv/www/config" => 0644, "/srv/www/shared" => 0755 }.each do |path, mode_value| directory path do mode mode_value owner 'root' group 'root' recursive true action :create end end
レシピを実行するには
  1. kitchen destroy をまだ実行していない場合は実行して、新しいインスタンスで始められるようにします。

  2. default.rb のコードを例で置き換えて、kitchen converge を実行します。

  3. インスタンスにログインします。/srv の下に指定したモードで新しく作成されたディレクトリがあります。

注記

AWS OpsWorks スタックのレシピは、通常、このアプローチを使用して、stack configuration and deployment JSON (スタック設定およびデプロイメント JSON) (これは基本的に大きなハッシュテーブル) から値を抽出し、それらをリソースに挿入します。例については「Deploy レシピ」を参照してください。

条件付きロジック

複数の実行ブランチを作成するために Ruby の条件付きロジックを使用することもできます。以下のレシピでは、if-elsif-else ロジックを使用して 1 つ前の例を拡張しています。/srv/www/shared という名前のサブディレクトリを作成しますが、Debian および Ubuntu システムに対してのみです。その他のすべてのシステムの場合は、Test Kitchen の出力に表示するエラーメッセージを記録します。

if platform?("debian", "ubuntu") directory "/srv/www/shared" do mode 0755 owner 'root' group 'root' recursive true action :create end else log "Unsupported system" end
レシピの例を実行するには
  1. インスタンスが実行中の場合は、kitchen destroy を実行してシャットダウンします。

  2. default.rb のコードを例のコードで置き換えます。

  3. .kitchen.yml を編集してプラットフォームの一覧に CentOS 6.4 システムを追加します。ファイルの platforms セクションはこのようになります。

    ... platforms: - name: ubuntu-12.04 - name: centos-6.4 ...
  4. kitchen converge を実行すると、インスタンスを作成し .kitchen.yml のプラットフォームごとのレシピを順次実行します。

    注記

    1 個のインスタンスのみをコンバージする場合は、インスタンス名をパラメータとして追加します。例えば、Ubuntu プラットフォームのレシピのみをコンバージするには、kitchen converge default-ubuntu-1204 を実行します。プラットフォーム名を忘れた場合は、kitchen list を実行します。

Test Kitchen の出力の CentOS 部分にログメッセージがあります。以下のようなものになります。

... Converging 1 resources Recipe: createdir::default * log[Unsupported system] action write[2014-06-23T19:10:30+00:00] INFO: Processing log[Unsupported system] action write (createdir::default line 12) [2014-06-23T19:10:30+00:00] INFO: Unsupported system [2014-06-23T19:10:30+00:00] INFO: Chef Run complete in 0.004972162 seconds

これでインスタンスにログインし、ディレクトリが作成されている (または作成されていない) ことを確認できます。ただし、単純に kitchen login を実行することはできません。たとえば kitchen login default-ubuntu-1204 のようにプラットフォーム名を追加してインスタンスを指定する必要があります。

注記

Test Kitchen コマンドがインスタンス名をとる場合、完全な名前を入力する必要はありません。Test Kitchen は Ruby の正規表現としてインスタンス名を処理しますので、ユニークな一致ができる文字数があれば十分です。例えば kitchen converge ub を実行して Ubuntu のインスタンスのみをコンバージすることもできますし、kitchen login 64 を実行して CentOS のインスタンスにログインすることもできます。

ここまでで、レシピがどのように実行中のプラットフォームを見分けているか疑問に思うことでしょう。Chef は実行のたびに Ohai というツールを実行してプラットフォームを含むシステムデータを収集し、ノードオブジェクトという構造の中で一連の属性として示します。Chef platform? メソッドはかっこ内のシステムを Ohai のプラットフォームの値と比較して、一致すれば true を返します。

node['attribute_name'] を使用してコード内で直接ノード属性の値を参照できます。プラットフォームの値は、例えば、node['platform'] で表されます。たとえば、前述の例を以下のように記述することもできます。

if node[:platform] == 'debian' or node[:platform] == 'ubuntu' directory "/srv/www/shared" do mode 0755 owner 'root' group 'root' recursive true action :create end else log "Unsupported system" end

レシピに条件付きロジックを含める一般的な理由は、異なる Linux ファミリーが時としてパッケージやディレクトリに異なる名前を使用していることに対応するためです。たとえば Apache のパッケージ名は CentOS システムでは httpd であり、Ubuntu システムでは apache2 です。

異なるシステム用に異なる文字列が必要な場合、Chef value_for_platform メソッドは、if-elsif-elseよりも簡単なソリューションです。以下のレシピは CentOS システムでは /srv/www/shared ディレクトリ、Ubuntu システムでは /srv/www/data ディレクトリ、その他の場合は /srv/www/config を作成します。

data_dir = value_for_platform( "centos" => { "default" => "/srv/www/shared" }, "ubuntu" => { "default" => "/srv/www/data" }, "default" => "/srv/www/config" ) directory data_dir do mode 0755 owner 'root' group 'root' recursive true action :create end

value_for_platformdata_dir に適切なパスを割り当て、directory リソースはその値を使用してディレクトリを作成します。

レシピの例を実行するには
  1. インスタンスが実行中の場合は、kitchen destroy を実行してシャットダウンします。

  2. default.rb のコードを例のコードで置き換えます。

  3. kitchen converge を実行し、その後各インスタンスにログインして適切なディレクトリがあることを確認します。