てくなべ (tekunabe)

ansible / network automation / 学習メモ

OSPF トラブルシューティングの勉強会に参加しました

はじめに

2021/12/18 の OSPF トラブルシューティングの勉強会に参加させていただきました。

connpass.com

やすおさん(@chimay_wh)の主催です。

twitter.com

題材

今回は、OSPF 編の初回ということで、レベル的にはやさしいものが扱われました。

題材は、過去に Cisco Live からのものだったようです。全19台のルーターで様々エリアからなるトポロジです。 github.com

やすおさんは CML-P で環境構築されたそうです。今回の環境に限れば 19台なのでPersonal の標準ライセンスでまかなえる範囲ですが、他にも色々されてそうなので、40ノード版(Personal Plus)かも?と妄想していました。

進め方

本題に入る前に、OSPFの理解度チェックがあり「このshowコマンドでどういうものが表示されるか」などをおさらいしました。

show ip protocol や、show ip opsf interface など。結構忘れてしまっているなと感じました・・。

show ip ospf interface brief コマンドは初めて知りました。以下の例は私の環境ですが、自身のルーター起点の情報(インターフェース、IPアドレス、コスト、ネイバーの数など)が一覧で表示されて便利だなと思いました。

# 別環境での例
rt102#show ip ospf interface brief
Interface    PID   Area            IP Address/Mask    Cost  State Nbrs F/C
Gi0/1        1     0               10.1.9.253/24      1     BDR   1/1
Gi0/3        1     0               10.1.1.253/24      1     BDR   1/1

本題のトラブルシューティングは、障害の箇所といくつかのルーターでshowコマンドを実行した結果を提示され、何を疑い次に何をすればいいか、という軽いクイズ形式で進みました。

CommentScreenを使い、参加者とインタラクティブに進める点がおもしろかったです。ニコニコ動画のように、書いたコメントが右から左に流れていきます。👏などのリアクションボタンもあったのでたまに連打してました。

ズバリ答えを書くだけでなく、ちょっとした疑問点や気付きなど、つぶやきレベルのものも気軽に書き込めました。

最後の問題は解けませんでした・・。ip ospf ttl-security コマンド自体を知らず。

人の操作を見るのはおもしろい

人のコマンドライン操作するところは見てて勉強になりますね。show コマンドの結果を絞り込む工夫をよくされて、なるほどと思います。

show hoge | inc hufa のように inc を使うこと自体はよくありますが、表形式で表示されるコマンドの列の見出しもセットで表示させるために、列名|絞り込みたい文字 という指定をされていました。この or 指定の | の前後にスペースを入れないで、一つの正規表現パターンとすることがポイントですね。

# 別環境での例
rt102#show ip ospf interface brief | inc State|9
Interface    PID   Area            IP Address/Mask    Cost  State Nbrs F/C
Gi0/3        1     0               10.1.9.253/24      1     BDR   1/1

おわりに

楽しく参加させていただました。ありがとうございました。

今後も、難易度別にリリースが続くそうです。是非また参加してみたいと思いました。

書籍『インフフラ/ネットワークエンジニアのためのネットワーク「動作試験」入門』がもはや「先輩」だった

はじめに

『インフフラ/ネットワークエンジニアのためのネットワーク「動作試験」入門』を読みました。とても良い本でした。

www.sbcr.jp

Amazon.co.jp はこちら

(電子版が試し読みできます)

なかなか扱われることの少ない動作試験に絞った書籍であることと、「インフラ/ネットワークエンジニアのためのネットワーク技術&設計入門 第2版」や「インフラ/ネットワークエンジニアのためのネットワーク・デザインパターン」など素晴らしい書籍の著者である、みやたひろしさんの書籍であるという点で、とてもたのしみにしていました。

ポートの状態などを確認する単体試験、機器を接続してルーティングなどを確認する結合試験、冗長機能が正常か確認する障害試験、ほか性能試験や長期安定試験について、考え方や手順などが書かれています。

初学者の頃に、現場の先輩に試験の方法を教えてもらい「こういうのありがたいなぁ。あまり書籍に載ってないし。」と思っていたことが、この書籍に載っている、そんな感覚を得ました。

現場目線のノウハウが詰まっていて、書籍の存在が頼れる先輩のように思いました。

特に個人的に刺さったポイントをまとめます。

これまでの個人的な経験としては、こういうのは何かを読んで学んだというよりは、現場で教わったり、失敗してから気づいたりしたことが多かったです。

コマンドレベルの詳細なサンプル

本書では、機器を絞って説明がされています。L2スイッチやルーターCisco IOSファイアウォールCisco ASA、負荷分散装置は F5 BIG-IP です。

絞ったことによって、確認すべきコマンドが具体的に示されています。どういう試験で、どういうコマンドを実行して、どこを見ればよいかかまで書かれています。

他にも、試験に使うツールやコマンドとして、curltelnet、nc、wireshark、ExPing なども登場します。

試験に失敗した時の確認ポイント

「設計どおりの状態になっていない場合」のように、試験に失敗したときに、どいう観点で確認していけばよいかも書かれています。

仕様だけでなく「手順」や「段取り」も

技術的な仕様の説明だけでなく、いざ業務で直面したときに必要になる「手順」や「段取り」についての言及がよくありました。

たとえば、

  • サーバー負荷分散試験の段階ではサーバーが用意できてない場合も多いので、試験用端末で仮試験を (P99-100)
  • 障害試験でスタックの復旧試験が完了したら、スタップグループ全体を再起動してアクティブを戻すこと (P217)

また、段取りとは少し違うかも知れませんが、インターフェース試験のところで、ポートの抜き差しするために使わなくなったLANケーブルの片方のコネクタの爪を追って・・(P44)と筆者の経験が書かれていました。私もそうやって教わったなぁと思い出しました。

業務上必要な優先度や合意

時間に限りがある中で試験で品質を上げるためには優先度を考える必要があります。

本書では、障害試験ではもちろんすべての箇所を試験するのがまずベストであるとしつつ、時間がない場合は優先度の高い箇所を選択していきましょう、とあります。その際の考え方についても載っています(P191-192)。

おわりに

経験や口伝だけで成り立っていたかもしれない試験に関するノウハウが、ここまで書籍にまとまっているのはとても価値のあることではないでしょうか。

教わる側、教える側の双方にとっても助けになる一冊だと思いました。

あと、のど飴のくだり、笑ってしまいました。

参考

読書メモツイート(スレッドが続いてます)

[Ansible] 新コンテツの Ansible もくもく会に参加してみた

この記事は、Ansible Advent Calendar 2021 (Adventar版) 17日目の記事です。

はじめに

ひさびさに開催された Ansible もくもく会に参加しました。

ansible-users.connpass.com

今回から新しいコンテンツ。環境は Ansible Automation Platform 2.0 Early Access (ansible-core は 2.11)。

無謀にもメンター枠ではいって、答えられそうなものがあれば答えつつ、新しいコンテンツに取り組もうと思いました。

途中、エラーや疑問が発生したので、やりながら調べた結果も合わせてまとめます。(冷静に調べればもっと正確かもしれません・・)

ネットワーク編に挑戦

ネットワーク編をやりました。コンテンツはこちら。新しいのはまだ英語版のみ。

aap2.demoredhat.com

コマンドライン

あたらしいコンテツらしく、ansible-navigator による環境確認や Playbook 実行がありました。

ansible-playbook コマンドは使いませんでした。

ansible-navigatorコマンドラインとして使い方は難しいものではなさそうですが、実行環境のコンテナ化とそれの運用方法などは、考えることがあるなという感覚です。

GUI

GUI は Automation Controller (旧 Ansible Tower)4.0.0 でした。

コンフィグバックアップのジョブを実行。これは前にもあった気がします。

このジョブが呼び出している Playbook はこちら。

github.com

新しい発見は Survey の複数選択。項目が分かれてるのでわかりやすく感じました。ただ、ペーストしていっぺんに入力はしにくいかもです。

バナーを設定した様子。

Junos のエラー発生と調査

ワークフローは、途中で設定ジョブを複数同時並行で実行させるものでした。ここでrtr3 (ツイートの rtr2 は間違い)の Junosでエラーが発生。

JunosとJunosモジュールの仕様上、不整合が起こらないらように排他処理がかかり、タイミングが重なるとあとからログインしたセッションが負けてエラーになってしまいます。

タイミングによるので、再現率は100%ではありませんでした。10回以上繰り返し実行しましたが再現しませんでした。

インベントリに他のOSのネットワーク機器もあるため、Junosがぶつかりにくかった状態だったようです。

ためしに、インベントリで他のネットワーク機器を無効化し、Junos のみでワークフローを再実行したら、あっさり再現しました。

直列にしてあげると、安定します。

リストアのエラー発生と調査

このワークフローはもう一エラーが。最後のジョブで設定をリストア仕様とした際に、バックアップファイルが見つからないというエラーです。

これは、最初のジョブで作るバックアップファイル名に、txt がついたりつかなかったりするためのようです。リストアの処理側を正とするなら、バックアップファイルはすべて txt をつけるのが正しいのでしょう。

バックアップのPlaybookの処理を追っていくと、OSごとにタスクファイルが別れていて、ios 向けは txt がついて、他はつかない形になっていました。

※ 2021/12/20 追記 後日、txt が付くように修正して動作確認する様子(スレッドに続きます)

リストアジョブの Survey で気になったこと(意図したコンフィグでリストアできない)

リストアのジョブで、もう一点気になったのが Servey です。ワークフローを組んでいくときに、リストアのジョブを選択すると、ロールバック対象の日時(つまり /backup ディレクトリ配下のディレクトリ名)をどうするか選択します。Survey の設定上、必須なのでなにか選択しないといけません。

f:id:akira6592:20211216221429p:plain
リストアジョブの Survey

この選択肢は、バックアップジョブを実行するたびに追加されます。この段階では、前の Exercise で実行したジョブによって、1つだけ選択肢がある状態なので、それを選択しました。

しかしこれでは選択が固定され、ここで選択した日時のバックアップファイル(今回の場合、/backup/2021-12-16-10-34 配下)が無条件にリストアされてしまいます。これでは、せっかくワークフローの最初のジョブで取得した、「設定直前のバックアップコンフィグ」がリストアに使われないことになります。

ここが気になった点でした。

なお、リストアは IOS については ios_config モジュールの src オプションを利用しています。今回のタスクの場合、もともと「A、B、C」という設定が入っている状態で「A、C」というバックアップファイルでリストアしても変化がありません。このあたりは現象の切り分け時に意識する必要があるかなと思います。

もしこの「意図したコンフィグがリストアで使用されない」現象を解消するのであれば、

  • リストアジョブの日時選択 Survey は必須でなくする
  • バックアップジョブでバックアップファイルを保存したパスを set_statsアーティファクトとして覚えておく
  • それをリストアジョブで利用する

という感じでしょうか。(未検証)

リストアジョブの Survey が画面から開けなくなってしまったのもちょっと気になっています。

f:id:akira6592:20211216224819p:plain
リストアジョブの Survey

まとめ

新しいコンテンツ、環境でハンズオンができてよかったです。CLI のほうで、ansible-playbook を使わないのは新鮮でした。

コンテンツや環境、機会を用意していただいたレッドハットさん、ありがとうございました!

また近いうちに開催予定があるようです。気になった方は、Ansible ユーザー会 の connpass グループに入っておくと通知が来るので便利です。

Ansible ユーザー会 - connpass

また参加したいと思います。

[ansible] ansible-builder で Automation Hub 経由のコレクションをインストールしたイメージをビルドする

この記事は、Ansible Advent Calendar 2021 (Adventar版) 16日目の記事です。

はじめに

ansible-builder では、requirements.yml にインストールしたいコレクションを指定し、Execution Environment 定義ファイル(デフォルトでは execution-environment.yml)に

dependencies:
  galaxy: requirements.yml

のように指定すると、ビルドするイメージ内にコレクションをインストールできます。

Execution Environment Definition — ansible-builder 1.0.1 documentation

デフォルトでは Ansible Galaxy 経由のコレクションです。

Automation Hub 経由のコレクションをインストールするには、少し仕込みが必要です。この記事では手順を紹介します。

  • 動作確認環境
    • ansible-builder 1.0.1

requirements.yml の用意

今回はこんなものを利用します。ansible.controller コレクションが Galaxy になく Automation Hub の方にしかないコレクションです。

---
collections:
  - cisco.ios
  - cisco.iosxr
  - cisco.nxos
  - junipernetworks.junos
  - seiko.smartcs
  - ansible.controller  # Galaxy になく Automation Hub の方にしかないもの

ansible.cfg の用意

(Automation Hub 経由のコレクションをansible-galaxy collection install でインストールしたい場合と同じです)

Automation Hub への接続するためのトークンを取得し、ansible.cfg で接続先やトークンの指定をします。

以下の過去の記事をご参照ください。

tekunabe.hatenablog.jp

Execution Environment 定義ファイルの用意

Execution Environment 定義ファイル(デフォルトでは execution-environment.yml)内の、ansible_configansible.cfg のパスを指定します。

先程用意した requirements.yml も指定します。

version: 1

build_arg_defaults:
  EE_BASE_IMAGE: 'quay.io/ansible/ansible-runner:stable-2.12-devel'
ansible_config: ansible.cfg  # ポイント1
dependencies:
  galaxy: requirements.yml  # ポイント2

ビルド

ここまで作ったファイルは以下のとおりです。

$ ls -1
ansible.cfg
execution-environment.yml
requirements.yml

この場所で通常通り、ansible-builder build コマンドでビルドします。

ansible-builder build -t localhost/my-ee

確認

ビルドしたイメージに目的のコレクションがインストールされたことを確認します。

ansible-navigator collections で確認する場合

コマンド例

ansible-navigator collections --pp never --eei localhost/my-ee 

今回は、ローカルのイメージを使うので、pull しないオプション --pp never を指定しています。

各オプションは ansible-navigator.yml で指定してもOKです。

結果例

  NAME                    VERSION  SHADOWED  TYPE       PATH
0│ansible.controller      4.1.0       False  contained  /usr/share/ansible/collections/ansible_collections/ansible/controller/
1│ansible.netcommon       2.5.0       False  contained  /usr/share/ansible/collections/ansible_collections/ansible/netcommon/
2│ansible.utils           2.4.3       False  contained  /usr/share/ansible/collections/ansible_collections/ansible/utils/
3│cisco.ios               2.6.0       False  contained  /usr/share/ansible/collections/ansible_collections/cisco/ios/
4│cisco.iosxr             2.6.0       False  contained  /usr/share/ansible/collections/ansible_collections/cisco/iosxr/
5│cisco.nxos              2.8.1       False  contained  /usr/share/ansible/collections/ansible_collections/cisco/nxos/
6│junipernetworks.junos   2.8.0G ON ITFalse  contained  /usr/share/ansible/collections/ansible_collections/junipernetworks/junos/
7│seiko.smartcs           1.4.1       False  contained  /usr/share/ansible/collections/ansible_collections/seiko/smartcs/

ansible.controller コレクション含め、インストールされていることが分かります。

コンテナ内の ansible-galaxy collection list で確認する場合

コマンド例

podman run -it localhost/my-ee ansible-galaxy collection list

結果例

$ podman run -it localhost/my-ee ansible-galaxy collection list

# /usr/share/ansible/collections/ansible_collections
Collection            Version
--------------------- -------
ansible.controller    4.1.0  
ansible.netcommon     2.5.0  
ansible.utils         2.4.3  
cisco.ios             2.6.0  
cisco.iosxr           2.6.0  
cisco.nxos            2.8.1  
junipernetworks.junos 2.8.0  
seiko.smartcs         1.4.1  

n月刊ラムダノート Vol.3, No.2(2021)の「ネットワーク自動化の歩き方」を読んだ

n月刊ラムダノート Vol.3, No.2(2021)の「ネットワーク自動化の歩き方」を読みました。

n月刊ラムダノート Vol.3, No.2(2021)www.lambdanote.com

@taijijijiさんの執筆です。

ネットワーク自動化の難しさ

ネットワークの自動化の難しさとして、CLI によるプロンプト処理の煩雑さや、API がないネットワーク機器の多さなどが挙げられていました。「そうなんですよねぇ」と思う内容でした。

サーバーなど他方面ですでに自動化をされている方に、ネットワーク自動化の難しさを理解していただくためにも良い内容だと思いました。

いろいろな実装サンプルとユースケース

具体的な実装方法として Python ライブラリの netmikoNAPALM や、ツールとしてAnsibleStackStormのサンプルが掲載されていました。

私としては、NETCONF、YANG、OpenConfig の経緯や現状が整理できてよかったです。

ネットワークエンジニアの仕事や自動化の難しさ、実装方法の雰囲気をサクッと読めるボリュームでまとめれています。この分野に興味がある方におすすめしたいです。

n月刊ラムダノート Vol.3, No.2(2021)www.lambdanote.com

[Ansible] Cisco IOS の allowed vlan の 範囲表記をリストにバラす vlan_expander フィルター

この記事は Ansible Advent Calendar 2021 の12日目の記事です。

はじめに

f:id:akira6592:20211204213553p:plain

Cisco IOS の機器などで、インターフェースへのトランクVLANの割り当て時に以下のように、範囲指定を含めて指定ができます。

interface GigabitEthernet1/3
 switchport trunk allowed vlan 1,10-13,100

上記の例の場合は、VLAN 110111213100 を割り当てていることが読み取れます。

Ansibleで、この読み取り方の変換をする ansible.netcommon.vlan_expander フィルターを今年作りました。- による範囲表記を含むカンマ区切りの数字を、連番にバラして数字のリストに変換します。

ansible.netcommon collection の 2.3.0 から利用できます。

もともとは ansible.netcommon.vlan_parser というフィルターがあり、VLAN のリスト(例: [1, 10, 11, 12, 13, 100] を、["1,10-13,100"] にというコンフィグっぽい方向に変換ができたのですが、これの逆をしたかった次第です。

サンプル

簡単なサンプル Playbook をご紹介します。(ansible.netcommon collection 2.4.0 で確認)

文字列 '1,10-13,100'ansible.netcommon.vlan_expander フィルターにかけます。

---
- hosts: localhost
  gather_facts: false
  connection: local

  tasks:
    - name: vlan_expander test
      ansible.builtin.debug:
        msg: "{{ '1,10-13,100' | ansible.netcommon.vlan_expander }}"

実行結果(抜粋)です。 [1, 10, 11, 12, 13, 100] のリストにバラけます。

TASK [vlan_expander test] ****************************
ok: [localhost] => {
    "msg": [
        1,
        10,
        11,
        12,
        13,
        100
    ]
}

コンフィグとしてはないと思いますが、元の文字列が '1, 10-13, 100' のように , の後にスペースがあっても変わりません。

また、'10-13,1,100' のように、順番がバラバラでも結果のリストは昇順ソートします(上記結果と同じ)。


ユースケース: allowed vlan に特定の VLAN が入ってるかチェック

ansible.netcommon.vlan_expander フィルターと、assert モジュールを組み合わせると、allowed vlan に特定の VLAN が 入ってるかどうかをチェックできます。

応用サンプルでは、下準備としてansible/utils/cli_parse モジュールと、パーサー ntc-templates を組みあせて、show interfaces switchport の結果をパースされた構造化データとして取得します。allowed vlan された vlan の情報は、構造化データ内の trunking_vlans 配下にありますので、それに対して ansible.netcommon.vlan_expander フィルターをかけると、リストにバラせます。その後、assert モジュールin を使ってチェックすれば目的のことができます。

なお、パーサーとして ntc-templates を利用するため、あらかじめ pip install ntc-templates でインストールが必要です。

Playbook

以下の Playbook では、Gi1/3 の allowed vlan に 11 があることをチェックします。途中、デバッグのためのタスクも挟んでいます。

---
- hosts: sw01
  gather_facts: false

  tasks:
    # show interfaces switchport の実行とパース
    - name: exec and parse show interfaces switchport
      ansible.utils.cli_parse:
        command: show interfaces switchport
        parser:
          name: ansible.netcommon.ntc_templates
      register: result_switchport
    
    # Gi/3 を抽出して変数にセット
    - name: set_fact for Gi1/3
      ansible.builtin.set_fact:
        parsed_gi1_3: "{{ result_switchport.parsed | selectattr('interface', '==', 'Gi1/3') | first }}"

    # Gi/3 の情報をデバッグ表示
    - name: debug parsed_gi1_3
      ansible.builtin.debug:
        msg: "{{ parsed_gi1_3 }}"

    #  Gi1/3 の allowed vlan に 11 があることを確認
    - name: assert allowed vlan
      ansible.builtin.assert:
        that:
          - 11 in (parsed_gi1_3.trunking_vlans | first | ansible.netcommon.vlan_expander)

実行例

正常(Gi1/3 の allowed vlan に 11 がある)の場合、以下のような実行結果になります。

PLAY [sw01] ********************************************************************

TASK [exec and parse show interfaces switchport] *******************************
ok: [sw01]

TASK [set_fact for Gi1/3] ******************************************************
ok: [sw01]

TASK [debug parsed_gi1_3] ******************************************************
ok: [sw01] => {
    "msg": {
        "access_vlan": "1",
        "admin_mode": "trunk",
        "interface": "Gi1/3",
        "mode": "trunk",
        "native_vlan": "1",
        "switchport": "Enabled",
        "switchport_monitor": "",
        "switchport_negotiation": "On",
        "trunking_vlans": [
            "1,10-13,100"
        ],
        "voice_vlan": "none"
    }
}

TASK [assert allowed vlan] *****************************************************
ok: [sw01] => {
    "changed": false,
    "msg": "All assertions passed"
}

PLAY RECAP *********************************************************************
sw01   : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

assert モジュールの that に与える条件式のバリエーションとしては

含まれることを期待する VLAN をリストで指定する場合は subset

          - "[1, 12] is subset(parsed_gi1_3.trunking_vlans | first | ansible.netcommon.vlan_expander)"

完全一致を期待する場合は

          - "[1, 10, 11, 12, 13, 100] == (parsed_gi1_3.trunking_vlans | first | ansible.netcommon.vlan_expander)"


おわりに

既存のフィルターを駆使しても類似の処理はできそうではありますが、今回はフィルターを作って ansible.netcommon collection にマージしていただきました。(ただ、CI環境の変更の都合で別の方にプルリクを出し直していただいた関係で私の名前はどこか彼方へ)

やはり1つのフィルターとして実装すると再利用しやすくて便利だなと思いました。

[ansible] ansible-runner で ansilbe-playbook コマンドのオプションを指定する --cmdline オプション

この記事は、Ansible Advent Calendar 2021 (Adventar版) 11日目の記事です。

はじめに

ansible-playbook コマンドのオプションを ansible-runner経由の Playbook 実行(ansible-runner run コマンド) でも指定したいことはないでしょうか。

以下のように、一部は対応したオプションが用意されています。

ansible-playbook コマンド ansible-runner コマンド
-l, --limit --limit
-f, --forks --forks
-v -v

(参考)ansible-runner run -h の抜粋

...(略)...
  -v                    increase the verbosity with multiple v's (up to 5) of the ansible-playbook output (default=None)
...(略)...
Ansible Options:
  control the ansible[-playbook] execution environment

  --limit LIMIT         matches Ansible's ```--limit``` parameter to further constrain the inventory to be used (default=None)
  --cmdline CMDLINE     command line options to pass to ansible-playbook at execution time (default=None)
  --hosts HOSTS         define the set of hosts to execute against (default=None) Note: this parameter only works with -m or -r
  --forks FORKS         matches Ansible's ```--forks``` parameter to set the number of concurrent processes (default=None)

しかし、タグを指定する -t オプションなど、その他多くの ansible-playook コマンドのオプションに対応したものはありません。

そんなときに利用できるのが ansble-runner run コマンドの --cmdline オプションです。

--cmdline '-t tag1' のように指定します。簡単な利用例で説明します。

  • 環境
    • ansible-core 2.12.1
    • ansible-runner 2.1.1 (2.0.2 までは --cmdline オプションが効かないのでご注意ください)

サンプル

Playbook

---
- hosts: localhost
  gather_facts: false
  connection: local

  tasks:
    - name: test debug
      ansible.builtin.debug:
        msg: "{{ greeting }}"
      tags:
        - tag1

    - name: test debug 2
      ansible.builtin.debug:
        msg: debug2
      tags:
        - tag2

コマンド実行結果

--cmdline '-e greeting=hello -t tag1' を指定しています。(後述しますが-e に関しては別の方法でも渡せます)

$ ansible-runner run . -p playbooks/test.yml --cmdline '-e greeting=hello -t tag1'

PLAY [localhost] ***************************************************************

TASK [test debug 1] ************************************************************
ok: [localhost] => {
    "msg": "hello"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

コマンドで渡したエクストラ変数 greeting の値 hello が適用されて、タグ tag1 がついているタスクのみが実行されたことが分かります。

--cmdline の後の値は、クォーテーションの囲い方や中に含まれる値によっては、エスケープする必要があるのでご注意ください。

(参考)オプションではなくファイルで用意する場合

コマンドオプションではなく、env/cmdline というファイルに書いておく方法もあります。

例:

-t tag1

コマンドラインエスケープが必要で面倒なときは、こちらの方法のほうが良いかも知れません。

また、エクストラ変数(-e)に限れば、env/extravars ファイルに書く方法もあります。