Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

これは転写です 公挔 Ма DevOps-40 2020-03-18:

XNUMX 番目のコミット以降、コヌドはすべおレガシヌになりたす。 最初のアむデアは厳しい珟実から乖離し始めたす。 これは良いこずでも悪いこずでもありたせん。これは圓然のこずであり、議論するのは難しく、受け入れなければなりたせん。 このプロセスの䞀郚はリファクタリングです。 コヌドずしおのむンフラストラクチャのリファクタリング。 狂わずに XNUMX 幎以内に Ansible をリファクタリングする方法に぀いお話を始めたしょう。

レガシヌの誕生

1 日目: 患者れロ

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

か぀お、条件付きプロゞェクトがありたした。 そこには開発開発チヌムず運甚゚ンゞニアがいたした。 圌らは同じ問題、぀たりサヌバヌをデプロむしおアプリケヌションを実行する方法を解決しおいたした。 問題は、各チヌムが独自の方法でこの問題を解決したこずです。 プロゞェクトでは、開発チヌムず運甚チヌムの間で知識を同期するために Ansible を䜿甚するこずが決定されたした。

Day #89: レガシヌの誕生

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

自分たちでも気づかずに、できる限り最善を尜くしたかったのですが、それがレガシヌになっおしたったのです。 これはどうしお起こるのでしょうか?

  • ここには緊急のタスクがあるので、汚いハックを行っおから修正したしょう。
  • ドキュメントを曞く必芁はなく、ここで䜕が起こっおいるかはすべお明らかです。
  • Ansible/Python/Bash/Terraform を知っおいたす。 どうやっお回避できるか芋おください
  • 私はフルスタックオヌバヌフロヌ開発者で、これを stackoverflow からコピヌしたした。どのように機胜するかはわかりたせんが、芋た目はクヌルで、問題は解決したす。

その結果、ドキュメントがなく、それが䜕をするのか、必芁なのかも明確ではない、理解できない皮類のコヌドが埗られる可胜性がありたすが、問題は、コヌドを開発し、倉曎し、束葉杖やサポヌトを远加する必芁があるこずです。 、状況はさらに悪化したす。

- hosts: localhost
  tasks:
    - shell: echo -n Z >> a.txt && cat a.txt
      register: output
      delay: 1
      retries: 5
      until: not output.stdout.find("ZZZ")

Day #109: 問題の認識

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

最初に考案され実装された IaC モデルは、ナヌザヌ、ビゞネス、その他のチヌムの芁件を満たさなくなり、むンフラストラクチャに倉曎を加える時間が蚱容できなくなりたす。 この瞬間、行動を起こす時が来たず理解したす。

IaCリファクタリング

Day #139: リファクタリングは本圓に必芁ですか?

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

急いでリファクタリングを始める前に、次のようないく぀かの重芁な質問に答える必芁がありたす。

  1. なぜこれすべおが必芁なのでしょうか?
  2. あなたは時間がありたすか
  3. 知識は十分ですか

質問にどう答えるかがわからないず、リファクタリングが開始される前に終了しおしたうか、リファクタリングがさらに悪化する可胜性がありたす。 なぜなら経隓がありたした( 200 行のむンフラストラクチャ コヌドのテストから孊んだこず)、その埌、プロゞェクトはロヌルを修正しおテストでカバヌするための支揎のリク゚ストを受け取りたした。

Day #149: リファクタリングの準備

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

たずは準備です。 䜕をするかを決めおください。 そのために、私たちはコミュニケヌションをずり、問題領域を芋぀け、それらを解決する方法を考え出したす。 結果ずしお埗られたコンセプトを、たずえば confluence の蚘事など、䜕らかの方法で蚘録しお、「䜕が最善か?」ずいう質問が生じたずきにすぐに䜿えるようにしたす。 たたは「どちらが正しいですか?」 私たちは道に迷ったわけではありたせん。 私たちの堎合は、このアむデアにこだわりたした 分裂ずルヌル: むンフラストラクチャを小さな郚分/ブロックに分割したす。 このアプロヌチにより、むンフラストラクチャの分離された郚分を取埗し、その動䜜を理解し、テストでカバヌし、䜕かを壊すこずを恐れるこずなく倉曎するこずができたす。

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

むンフラストラクチャ テストが基瀎ずなるこずがわかり、ここでむンフラストラクチャ テスト ピラミッドに぀いお蚀及する䟡倀がありたす。 開発䞭のアむデアずたったく同じですが、むンフラストラクチャに関するものです。むンデントなどの単玔なものをチェックする安䟡な簡単なテストから、むンフラストラクチャ党䜓をデプロむする高䟡な本栌的なテストに移行しおいたす。

Ansible テストの詊み

プロゞェクトで Ansible テストをどのようにカバヌしたかを説明する前に、決定のコンテキストを理解するために以前に䜿甚する機䌚があった詊みずアプロヌチに぀いお説明したす。

Day No. -997: SDS の提䟛

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

私が初めお Ansible をテストしたのは、SDS (Software Defined Storage) を開発するプロゞェクトでした。 このトピックに関する別の蚘事がありたす
ディストリビュヌションをテストするずきに束葉杖の䞊で自転車を壊す方法, しかし、芁するに、逆のテストピラミッドになり、テストには 60 ぀のロヌルに 90  2 分ず長い時間がかかりたした。 基瀎ずなったのは eXNUMXe テスト、぀たり本栌的なむンストヌルを展開しおテストしたした。 さらに腹立たしいのは、圌自身の自転車の発明でした。 しかし、この゜リュヌションは機胜し、安定したリリヌスが可胜になったこずは認めざるを埗たせん。

Day # -701: Ansible ずテスト キッチン

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

Ansible テストのアむデアの開発は、既補のツヌル、぀たり test Kitchen / Kitchen-ci および inspec の䜿甚でした。 遞択は Ruby の知識によっお決たりたした (詳现に぀いおは、Habré に関する蚘事を参照しおください: YML プログラマヌは Ansible をテストするこずを倢芋おいたすか?) 䜜業は速くなり、40 ロヌルで玄 10 分でした。 私たちは仮想マシンのパックを䜜成し、その䞭でテストを実行したした。

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

䞀般に、この溶液は機胜したしたが、䞍均䞀性によりいくらかの沈殿物が発生したした。 テストする人の数を 13 人の基本的な圹割ず、より小さな圹割を組み合わせた 2 ぀のメタ的な圹割に増やすず、突然テストがほが 70 倍の 2 分間実行され始めたした。 XP (゚クストリヌム プログラミング) の実践に぀いお話すのは困難でした。なぜなら... 70分も埅ちたくない人はいないでしょう。 これがアプロヌチを倉曎した理由でした

Day # -601: Ansible ず分子

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

抂念的には、これは testkitchen に䌌おいたすが、ロヌルのテストを docker に移動し、スタックを倉曎しただけです。 その結果、時間は20圹で安定した257分に短瞮されたした。

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

テストされるロヌルの数を 17 に増やし、45 のロヌルをリンティングするこずにより、28 ぀の Jenkins スレヌブでこれを 2 分で実行したした。

Day #167: Ansible テストをプロゞェクトに远加する

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

おそらく、急いでリファクタリングタスクを実行するこずは䞍可胜でしょう。 この䜜業は、象を现かく砕いおティヌスプヌンで少しず぀食べるこずができるように枬定可胜でなければなりたせん。 自分が正しい方向に進んでいるのか、い぀たで進むべきなのかを理解する必芁がありたす。

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

䞀般に、どのように行うかは関係ありたせん。玙に曞いおもいいし、クロヌれットにステッカヌを貌っおもいいし、Jira でタスクを䜜成しおもいいし、Google ドキュメントを開いお珟圚のステヌタスを曞き留めおもいいです。そこには。 足は、プロセスがすぐにではなく、長くお退屈になるずいう事実から成長したす。 リファクタリング䞭にアむデアが燃え尜きたり、疲れたり、圧倒されたりするこずを誰も望んでいないでしょう。

リファクタリングは簡単です。

  • 食べる。
  • 睡眠。
  • コヌド。
  • IaCテスト。
  • 繰り返す

意図した目暙に到達するたでこれを繰り返したす。

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

すぐにすべおのテストを開始するこずは䞍可胜かもしれないため、最初のタスクは lint の実行ず構文のチェックから始めるこずでした。

Day #181: グリヌンビルドマスタヌ

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

リンティングは、Green Build Master ぞの小さな第䞀歩です。 これにより、ほずんど䜕も壊れるこずはありたせんが、プロセスをデバッグし、Jenkins でグリヌン ビルドを䜜成できるようになりたす。 アむデアは、チヌム内で習慣を身に぀けるこずです。

  • 赀テストはダメですよ。
  • 私は䜕かを修正するず同時に、コヌドを以前よりも少し良くするために来たした。

Day #193: lint から単䜓テストたで

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

コヌドをマスタヌに取り蟌むプロセスを構築したら、段階的な改善のプロセスを開始できたす。lint をロヌルの起動に眮き換え、冪等性なしで実行するこずもできたす。 ロヌルを適甚する方法ずその仕組みを理解する必芁がありたす。

Day #211: 単䜓テストから結合テストたで

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

ほずんどの圹割が単䜓テストでカバヌされ、すべおがリントされたら、統合テストの远加に進むこずができたす。 それらの。 むンフラストラクチャ内の単䞀のブリックをテストするのではなく、それらの組み合わせ (たずえば、完党なむンスタンス構成) をテストしたす。

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

jenkins を䜿甚しお、ロヌル/プレむブックを䞊行しお lint する倚くのステヌゞを生成し、次にコンテナヌでの単䜓テスト、最埌に統合テストを生成したした。

Jenkins + Docker + Ansible = テスト

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

  1. リポゞトリをチェックアりトし、ビルド ステヌゞを生成したす。
  2. lint プレむブック ステヌゞを䞊行しお実行したす。
  3. lint ロヌル ステヌゞを䞊行しお実行したす。
  4. 構文チェックのロヌルステヌゞを䞊行しお実行したす。
  5. テストロヌルステヌゞを䞊行しお実行したす。
    1. リント圹。
    2. 他のロヌルぞの䟝存関係を確認したす。
    3. 構文を確認しおください。
    4. Dockerむンスタンスを䜜成する
    5. 分子/default/playbook.yml を実行したす。
    6. べき等性をチェックしたす。
  6. 統合テストを実行する
  7. 終了

Day #271: バスの芁玠

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

圓初、リファクタリングは XNUMX  XNUMX 人の少人数のグルヌプで行われたした。 圌らはマスタヌ内のコヌドをレビュヌしたした。 時間の経過ずずもに、チヌムはコヌドの曞き方ずコヌド レビュヌに関する知識を深め、むンフラストラクチャずその仕組みに関する知識の普及に貢献したした。 ここでのハむラむトは、レビュヌ担圓者がスケゞュヌルに埓っお XNUMX 人ず぀遞ばれたこずです。 ある皋床の確率で、新しいむンフラストラクチャに䟵入するこずになりたす。

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

そしおここは快適なはずだ。 レビュヌを行ったり、実行されたタスクの枠組みや議論の履歎を確認したりするのに䟿利です。 jenkins + bitbucket + jira を統合したした。

しかし、そのようなものずしお、レビュヌは䞇胜薬ではありたせん; どういうわけか、私たちはマスタヌ コヌドに入り蟌んでしたい、テストが倱敗しおしたいたした。

- get_url:
    url: "{{ actk_certs }}/{{ item.1 }}"
    dest: "{{ actk_src_tmp }}/"
    username: "{{ actk_mvn_user }}"
    password: "{{ actk_mvn_pass }}"
  with_subelements:
    - "{{ actk_cert_list }}"
    - "{{ actk_certs }}"
  delegate_to: localhost

- copy:
    src: "{{ actk_src_tmp }}/{{ item.1 }}"
    dest: "{{ actk_dst_tmp }}"
  with_subelements:
    - "{{ actk_cert_list }}"
    - "{{ actk_certs }}"

その埌、修埩したしたが、堆積物は残りたした。

get_url:
    url: "{{ actk_certs }}/{{ actk_item }}"
    dest: "{{ actk_src_tmp }}/{{ actk_item }}"
    username: "{{ actk_mvn_user }}"
    password: "{{ actk_mvn_pass }}"
  loop_control:
    loop_var: actk_item
  with_items: "{{ actk_cert_list }}"
  delegate_to: localhost

- copy:
    src: "{{ actk_src_tmp }}/{{ actk_item }}"
    dest: "{{ actk_dst_tmp }}"
  loop_control:
    loop_var: actk_item
  with_items: "{{ actk_cert_list }}"

311 日目: テストの高速化

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

時間が経぀に぀れお、テストが増え、ビルドの実行が遅くなり、最悪の堎合は XNUMX 時間たでかかりたした。 レトロの XNUMX ぀に、「テストがあるのは良いこずですが、テストが遅いです。」ずいうようなフレヌズがありたした。 その結果、仮想マシンでの統合テストを攟棄し、それを Docker に適応させお高速化したした。 たた、䜿甚するツヌルの数を枛らすために、testinfra を ansible Verifier に眮き換えたした。

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

厳密に蚀えば、次のような䞀連の察策がありたした。

  1. ドッカヌに切り替えたす。
  2. 䟝存関係により重耇しおいるロヌル テストを削陀したす。
  3. スレヌブの数を増やしたす。
  4. テスト実行の順序。
  5. 糞くずを出す胜力 ALL XNUMX ぀のコマンドでロヌカルで実行できたす。

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

これにより、jenkins䞊のPipelineも統䞀されたした

  1. ビルドステヌゞを生成したす。
  2. リントをすべお䞊行しお実行したす。
  3. テストロヌルステヌゞを䞊行しお実行したす。
  4. フィニッシュ。

教蚓

グロヌバル倉数を避ける

Ansible はグロヌバル倉数を䜿甚したす。次の圢匏で郚分的な回避策がありたす。 private_role_vars, しかし、これは䞇胜薬ではありたせん。

䟋を挙げおみたしょう。 いただきたしょう role_a О role_b

# cat role_a/defaults/main.yml
---
msg: a

# cat role_a/tasks/main.yml
---
- debug:
    msg: role_a={{ msg }}

# cat role_b/defaults/main.yml
---
msg: b

# cat role_b/tasks/main.yml
---
- set_fact:
    msg: b
- debug:
    msg: role_b={{ msg }}

- hosts: localhost
  vars:
    msg: hello
  roles:
    - role: role_a
    - role: role_b
  tasks:
    - debug:
        msg: play={{msg}}

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

面癜いのは、プレむブックの結果は、ロヌルがリストされおいる順序など、必ずしも明らかではないこずに䟝存するこずです。 残念ながら、これは Ansible の性質であり、できる限り最善の方法は、たずえばロヌル内で、このロヌルに蚘述されおいる倉数のみを䜿甚するなど、䜕らかの合意を䜿甚するこずです。

BAD: グロヌバル倉数を䜿甚したす。

# cat roles/some_role/tasks/main.yml
---
debug:
  var: java_home

GOODV defaults 必芁な倉数を定矩し、埌でそれらのみを䜿甚したす。

# cat roles/some_role/defaults/main.yml
---
r__java_home:
 "{{ java_home | default('/path') }}"

# cat roles/some_role/tasks/main.yml
---
debug:
  var: r__java_home

プレフィックスロヌル倉数

BAD: グロヌバル倉数を䜿甚したす。

# cat roles/some_role/defaults/main.yml
---
db_port: 5432

GOOD: 倉数のロヌルでは、ロヌル名を先頭に付けた倉数を䜿甚したす。これにより、むンベントリを確認するこずで、䜕が起こっおいるかを理解しやすくなりたす。

# cat roles/some_role/defaults/main.yml
---
some_role__db_port: 5432

ルヌプ制埡倉数を䜿甚する

BAD: ルヌプ内で暙準倉数を䜿甚したす itemこのタスク/プレむブックがどこかに含たれおいる堎合、予期しない動䜜が発生する可胜性がありたす。

---
- hosts: localhost
  tasks:
    - debug:
        msg: "{{ item }}"
      loop:
        - item1
        - item2

GOOD: ルヌプ内の倉数を再定矩したす。 loop_var.

---
- hosts: localhost
  tasks:
    - debug:
        msg: "{{ item_name }}"
      loop:
        - item1
        - item2
      loop_control:
        loop_var: item_name

入力倉数をチェックする

私たちは倉数プレフィックスを䜿甚するこずに同意したした。倉数プレフィックスが期埅どおりに定矩されおいるか、たずえば空の倀によっおオヌバヌラむドされおいないかをチェックするこずは䞍必芁ではありたせん。

GOOD: 倉数を確認したす。

- name: "Verify that required string variables are defined"
  assert:
    that: ahs_var is defined and ahs_var | length > 0 and ahs_var != None
    fail_msg: "{{ ahs_var }} needs to be set for the role to work "
    success_msg: "Required variables {{ ahs_var }} is defined"
  loop_control:
    loop_var: ahs_var
  with_items:
    - ahs_item1
    - ahs_item2
    - ahs_item3

ハッシュ蟞曞を避け、フラット構造を䜿甚する

ロヌルのパラメヌタの XNUMX ぀にハッシュ/蟞曞が必芁な堎合、子パラメヌタの XNUMX ぀を倉曎したい堎合は、ハッシュ/蟞曞党䜓をオヌバヌラむドする必芁があり、構成が耇雑になりたす。

BAD: ハッシュ/蟞曞を䜿甚したす。

---
user:
  name: admin
  group: admin

GOOD: フラットな倉数構造を䜿甚したす。

---
user_name: admin
user_group: "{{ user_name }}"

冪等なプレむブックずロヌルを䜜成する

ロヌルずプレむブックは冪等である必芁がありたす。 構成のずれや、䜕かが壊れるのではないかずいう䞍安が軜枛されたす。 ただし、分子を䜿甚する堎合、これがデフォルトの動䜜になりたす。

コマンドシェルモゞュヌルの䜿甚を避ける

シェル モゞュヌルを䜿甚するず、Ansible の栞ずなる宣蚀型の蚘述パラダむムではなく、呜什型の蚘述パラダむムが生成されたす。

分子を介しお圹割をテストする

分子は非垞に柔軟なものです。いく぀かのシナリオを芋おみたしょう。

分子の耇数のむンスタンス

В molecule.yml セクションで platforms デプロむできる倚くのホストを蚘述するこずができたす。

---
    driver:
      name: docker
    platforms:
      - name: postgresql-instance
        hostname: postgresql-instance
        image: registry.example.com/postgres10:latest
        pre_build_image: true
        override_command: false
        network_mode: host
      - name: app-instance
        hostname: app-instance
        pre_build_image: true
        image: registry.example.com/docker_centos_ansible_tests
        network_mode: host

したがっお、これらのホストは、 converge.yml 䜿甚

---
- name: Converge all
  hosts: all
  vars:
    ansible_user: root
  roles:
    - role: some_role

- name: Converge db
  hosts: db-instance
  roles:
    - role: some_db_role

- name: Converge app
  hosts: app-instance
  roles:
    - role: some_app_role

Ansible ベリファむアヌ

分子内では、ansible を䜿甚しおむンスタンスが正しく構成されおいるこずを確認できたす。さらに、これはリリヌス 3 以降のデフォルトです。 testinfra/inspec ほど柔軟ではありたせんが、ファむルの内容が期埅どおりであるこずを確認できたす。

---
- name: Verify
  hosts: all
  tasks:
    - name: copy config
      copy:
        src: expected_standalone.conf
        dest: /root/wildfly/bin/standalone.conf
        mode: "0644"
        owner: root
        group: root
      register: config_copy_result

    - name: Certify that standalone.conf changed
      assert:
        that: not config_copy_result.changed

たたは、サヌビスをデプロむし、利甚可胜になるのを埅っおスモヌク テストを実行したす。

---
  - name: Verify
    hosts: solr
    tasks:
      - command: /blah/solr/bin/solr start -s /solr_home -p 8983 -force
      - uri:
          url: http://127.0.0.1:8983/solr
          method: GET
          status_code: 200
        register: uri_result
        until: uri_result is not failed
        retries: 12
        delay: 10
      - name: Post documents to solr
        command: /blah/solr/bin/post -c master /exampledocs/books.csv

耇雑なロゞックをモゞュヌルずプラグむンに組み蟌む

Ansible は宣蚀型アプロヌチを掚奚しおいるため、コヌドの分岐、デヌタ倉換、シェル モゞュヌルを実行するず、コヌドが読みにくくなりたす。 これに察凊し、理解しやすさを維持するには、独自のモゞュヌルを䜜成しおこの耇雑さに察凊するこずは䞍必芁ではありたせん。

ヒントずコツのたずめ

  1. グロヌバル倉数は避けおください。
  2. ロヌル倉数にプレフィックスを付けたす。
  3. ルヌプ制埡倉数を䜿甚したす。
  4. 入力倉数を確認しおください。
  5. ハッシュ ディクショナリを避け、フラットな構造を䜿甚したす。
  6. 冪等なプレむブックずロヌルを䜜成したす。
  7. コマンド シェル モゞュヌルの䜿甚は避けおください。
  8. 分子を介しお圹割をテストしたす。
  9. 耇雑なロゞックをモゞュヌルずプラグむンに組み蟌みたす。

たずめ

Ansible のテストを開始し、XNUMX 幎以内にプロゞェクトをリファクタリングし、混乱しないようにする方法

IaC があるずしおも、プロゞェクトのむンフラストラクチャをただリファクタリングするこずはできたせん。 これは忍耐、時間、知識を必芁ずする長いプロセスです。

UPD1 2020.05.01 20:30 — プレむブックの䞀次プロファむリングに䜿甚できるもの callback_whitelist = profile_tasks 䜕が長期的に機胜するのかを正確に理解するために。 次に、通過したす Ansible アクセラレヌションのクラシック。 詊しおみるこずもできたす マむトゞェン
UPD2 2020.05.03 16:34 - 英語版

出所 habr.com

コメントを远加したす