import / removed / moved は現実を動かさずに帳簿だけを書き換える
IaCの差分エンジンは「コードとstateがずれていたら現実を動かして揃える」機械である。リソースの名前を変えればstateに無い名前が現れ、Createが出る。旧い名前はdesiredから消えるのでDeleteが出る。つまり素朴に作ると、コードの整理がそのまま本番の作り直しになる。
import / removed / moved はこの結びつきを切る。3つともstateだけを書き換えて、クラウド側のAPIを一切叩かない。
| ブロック | stateに対して | 現実に対して |
|---|---|---|
import | 既存リソースをstateに登録する | 何もしない(既にある) |
removed | stateから登録を外す | 何もしない(残り続ける) |
moved | 登録のアドレスを付け替える | 何もしない(同じ物) |
なぜこれが重要か
コードの構造と、動いている実体の寿命が分離できるからである。
この分離が無いと、リファクタリングの費用が「エディタ上の手間」ではなく「本番の停止時間」になる。名前が気に入らないだけでDBが作り直されるなら、誰も名前を直さない。モジュールを切り直すとVPCが消えるなら、構造は腐ったまま凍結される。コードの整理にリスクが乗った瞬間、整理されなくなる。
裏返せば、この3つは「あとで直せる」を保証する機構である。IaCは一度書いたら長く生きるコードなので、最初の設計が最適であることより、後から作り替えられることのほうが効いてくる。
import はさらにもう一方向を開く。IaCの外で生まれた実体を、後から管理下に入れられる。 これが無いと「最初からIaCで作ったものしか管理できない」ことになり、手で作った既存環境は永久に手作業のままになる。移行の経路がある。
効果としての位置づけ
Carinaではこの3つも Effect の一種として、他の7種と同じ列に並ぶ。ただし出自が違う。差分エンジンが選ぶのは Read / Create / Update / Delete / Wait の5種で、Import / Remove / Move は差分エンジンが一切出さない。ユーザーが書いたブロックから、plan生成後の後処理(add_state_block_effects)が付け足す。
この後処理は付け足すだけでなく、差分エンジンが出した命令を撤回する。removed の対象に対応するDeleteを消し、import の対象に対応するCreateを消す。撤回こそがこの機構の本体である — 放っておけば差分エンジンが出してしまう「現実を動かす命令」を、ユーザーの宣言で取り下げている。
そして撤回された結果もまたplanに載る。planは効果の列という平らな値なので、「stateだけが動いて現実は動かない」ことがapplyの前に目で確認できる。帳簿の書き換えが黙って起きるのではなく、命令として明示される。
危うさも同じ場所から来る
現実を動かさないということは、stateと現実がずれる方向にも動かせるということでもある。removed を書けばリソースは残ったまま管理から外れ、誰も面倒を見ない実体になる。import のidを間違えれば、別の実体を掴んだまま以後のplanが嘘をつく。
差分エンジンの出す命令は「stateを現実に近づける」方向にしか動かないので間違えても収束するが、state blocksはその保証の外側にある。ユーザーが直接命令を書いている以上、正しさの根拠はユーザーの意図だけである。planに出ることが唯一の防波堤になる。