Dasar sing bisa ditindakake, tanpa buku dolanan sampeyan bakal dadi gumpalan pasta lengket

Aku akeh review saka kode Ansible wong liya lan nulis akeh dhewe. Sajrone nganalisa kesalahan (loro wong liya lan dhewe), uga sawetara wawancara, aku nyadari kesalahan utama sing ditindakake pangguna Ansible - dheweke entuk perkara sing rumit tanpa nguwasani dhasar.

Kanggo mbenerake ketidakadilan universal iki, aku mutusake kanggo nulis introduksi kanggo Ansible kanggo sing wis ngerti. Aku ngelingake sampeyan, iki ora retelling mans, iki longread karo akeh huruf lan ora ana gambar.

Tingkat sing dikarepake saka maca yaiku sawetara ewu baris yamla wis ditulis, ana sing wis diprodhuksi, nanging "kayane kabeh bengkok."

Jeneng

Kesalahan utama pangguna Ansible yaiku ora ngerti apa sing diarani. Yen sampeyan ora ngerti jeneng, sampeyan ora bisa ngerti apa dokumentasi ngandika. Conto urip: sajrone wawancara, wong sing ujar manawa dheweke nulis akeh ing Ansible ora bisa mangsuli pitakon "unsur apa sing kalebu buku dolanan?" Lan nalika aku disaranake sing "jawaban wis samesthine sing playbook kasusun saka play," komentar damning "kita ora nggunakake sing" ngiring. Wong nulis Ansible kanggo dhuwit lan ora nggunakake play. Padha bener nggunakake, nanging ora ngerti apa iku.

Dadi ayo miwiti kanthi prasaja: apa sing diarani. Mungkin sampeyan ngerti iki, utawa mungkin sampeyan ora ngerti, amarga sampeyan ora nggatekake nalika maca dokumentasi.

ansible-playbook nglakokaké playbook. Playbook minangka file kanthi ekstensi yml/yaml, ing njero ana sing kaya mangkene:

---
- hosts: group1
  roles:
    - role1

- hosts: group2,group3
  tasks:
    - debug:

Kita wis ngerti manawa kabeh file iki minangka playbook. Kita bisa nuduhake endi peran lan endi tugas. Nanging ngendi iku muter? Lan apa bedane dolanan lan peran utawa buku dolanan?

Kabeh ana ing dokumentasi. Lan padha kantun. Wiwitan - amarga ana akeh banget lan sampeyan ora bakal ngelingi kabeh bebarengan. Experienced - amarga "sepele". Yen sampeyan duwe pengalaman, waca maneh kaca-kaca iki paling sethithik sapisan saben nem sasi, lan kode sampeyan bakal dadi kelas sing unggul.

Dadi, elinga: Playbook minangka dhaptar sing kalebu play lan import_playbook.
Iki minangka salah sawijining dolanan:

- hosts: group1
  roles:
    - role1

lan iki uga dolanan liyane:

- hosts: group2,group3
  tasks:
    - debug:

Apa iku play? Napa dheweke?

Play minangka unsur kunci kanggo playbook, amarga play lan mung muter nggandhengake dhaptar peran lan / utawa tugas karo dhaptar host sing kudu ditindakake. Ing ambane jero saka dokumentasi sampeyan bisa nemokake sebutno saka delegate_to, plugin lookup lokal, setelan jaringan-cli-spesifik, lompat host, etc. Dheweke ngidini sampeyan rada ngganti papan ing ngendi tugas ditindakake. Nanging, lali babagan. Saben opsi pinter iki nduweni kegunaan khusus, lan mesthi ora universal. Lan kita ngomong babagan dhasar sing kudu dingerteni lan digunakake saben wong.

Yen sampeyan pengin nindakake "soko" "ing endi wae", sampeyan nulis muter. Ora peran. Ora peran karo modul lan delegasi. Sampeyan njupuk lan nulis muter. Ing ngendi, ing lapangan sarwa dumadi sampeyan dhaptar ing endi sing kudu ditindakake, lan ing peran / tugas - apa sing kudu dieksekusi.

Prasaja, ta? Kepiye carane bisa digunakake?

Salah sawijining momen sing khas nalika wong duwe kepinginan kanggo nindakake iki ora liwat dolanan yaiku "peran sing nggawe kabeh." Aku seneng duwe peran sing ngatur loro server saka jinis pisanan lan server saka jinis kapindho.

Conto archetypal yaiku ngawasi. Aku pengin duwe peran ngawasi sing bakal ngatur ngawasi. Peran ngawasi diutus kanggo ngawasi sarwa dumadi (miturut muter). Nanging ternyata kanggo ngawasi kita kudu ngirim paket menyang host sing kita monitor. Apa ora nggunakake utusan? Sampeyan uga kudu ngatur iptables. utusan? Sampeyan uga kudu nulis / mbenerake konfigurasi kanggo DBMS supaya bisa ngawasi. utusan! Lan yen kreatifitas kurang, sampeyan bisa nggawe delegasi include_role ing daur ulang nested nggunakake Filter angel ing dhaftar kelompok, lan nang include_role sampeyan bisa nindakake liyane delegate_to maneh. Lan kita lunga ...

Pangarep-arep sing apik - duwe peran ngawasi siji, sing "nindakake kabeh" - ndadékaké kita menyang neraka lengkap sing paling kerep mung ana siji cara metu: nulis ulang kabeh saka awal.

Ing endi kesalahane kedadeyan ing kene? Nalika sampeyan nemokake yen kanggo nindakake tugas "x" ing host X sampeyan kudu pindhah menyang host Y lan nindakake "y" ing kana, sampeyan kudu nindakake latihan prasaja: pindhah lan nulis play, sing ing host Y nindakake y. Aja nambah soko kanggo "x", nanging nulis saka ngeruk. Malah karo variabel hardcoded.

Iku misale jek sing kabeh ing paragraf ndhuwur ngandika bener. Nanging iki dudu kasus sampeyan! Amarga sampeyan pengin nulis kode sing bisa digunakake maneh sing garing lan kaya perpustakaan, lan sampeyan kudu golek cara kanggo nindakake.

Iki ngendi kesalahan serius liyane lurks. Kesalahan sing ngowahi akeh proyek saka ditulis kanthi trep (bisa uga luwih apik, nanging kabeh bisa ditindakake lan gampang rampung) dadi horor lengkap sing ora bisa dingerteni dening penulis. Iku bisa, nanging Gusti Allah ngalang-alangi sampeyan ngganti apa-apa.

Kesalahan yaiku: peran minangka fungsi perpustakaan. Analogi iki wis ngrusak akeh wiwitan sing apik, mula mung sedhih kanggo nonton. Peran dudu fungsi perpustakaan. Dheweke ora bisa ngitung lan ora bisa nggawe keputusan tingkat play. Ngelingake apa pancasan play ndadekake?

Matur nuwun, sampeyan bener. Play nggawe keputusan (luwih tepat, ngemot informasi) babagan tugas lan peran sing kudu ditindakake ing host sing.

Yen sampeyan utusan kaputusan iki kanggo peran, lan malah karo petungan, sampeyan siksa dhewe (lan wong sing bakal nyoba kanggo parse kode) kanggo orane sengsara. Peran ora mutusake ing ngendi dheweke ditindakake. Kaputusan iki digawe dening muter. Peran nindakake apa sing dicritakake, ing ngendi sing dicritakake.

Apa mbebayani kanggo program ing Ansible lan ngapa COBOL luwih apik tinimbang Ansible, kita bakal ngomong ing bab babagan variabel lan jinja. Saiki, ayo ngomong siji - saben petungan sampeyan ninggalake jejak owah-owahan ing variabel global, lan sampeyan ora bisa nindakake apa-apa. Sanalika loro "jejak" intersected, kabeh wis ilang.

Cathetan kanggo squeamish: peran mesthi bisa mengaruhi aliran kontrol. mangan delegate_to lan nduweni kegunaan sing cukup. mangan meta: end host/play. Nanging! Elinga yen kita mulang dhasar? Kelalen delegate_to. Kita ngomong babagan kode Ansible sing paling gampang lan paling apik. Sing gampang diwaca, gampang ditulis, gampang didebug, gampang dites lan gampang dirampungake. Dadi, sepisan maneh:

muter lan mung muter nemtokaken kang sarwa dumadi apa kaleksanan.

Ing bagean iki, kita ngatasi oposisi antarane dolanan lan peran. Saiki ayo ngomong babagan hubungan tugas vs peran.

Tugas lan Peran

Coba muter:

- hosts: somegroup
  pre_tasks:
    - some_tasks1:
  roles:
     - role1
     - role2
  post_tasks:
     - some_task2:
     - some_task3:

Ayo dadi ngomong sampeyan kudu nindakake foo. Lan katon kaya foo: name=foobar state=present. Ngendi aku kudu nulis iki? ing pra? kirim? Nggawe peran?

...Lan tugas-tugas kasebut menyang ngendi?

Kita miwiti maneh dhasar - piranti play. Yen sampeyan ngawang ing masalah iki, sampeyan ora bisa nggunakake muter minangka basis kanggo kabeh liya, lan asil bakal "goyang".

Piranti play: sarwa dumadi arahan, setelan kanggo muter dhewe lan pre_tasks, tugas, peran, post_tasks bagean. Parameter sing isih ana kanggo dolanan ora penting kanggo kita saiki.

Urutan bagean kanthi tugas lan peran: pre_tasks, roles, tasks, post_tasks. Awit saking semantik urutan eksekusi punika antawisipun tasks и roles ora cetha, banjur praktik paling apik ujar manawa kita nambah bagean tasks, mung yen ora roles... Yen ana roles, banjur kabeh tugas sing dilampirake diselehake ing bagean pre_tasks/post_tasks.

Kabeh sing isih ana yaiku kabeh wis jelas kanthi semantik: pisanan pre_tasksbanjur rolesbanjur post_tasks.

Nanging kita isih durung mangsuli pitakonan: ngendi telpon modul? foo nulis? Apa kita kudu nulis kabeh peran kanggo saben modul? Utawa luwih apik kanggo duwe peran kandel kanggo kabeh? Lan yen ora peran, banjur ing ngendi aku kudu nulis - ing pra utawa kirim?

Yen ora ana jawaban kanggo pitakonan kasebut, mula iki minangka tandha kekurangan intuisi, yaiku, "pondasi goyang" sing padha. Ayo dipikirake. First, pitakonan keamanan: Yen muter wis pre_tasks и post_tasks (lan ora ana tugas utawa peran), banjur bisa soko break yen aku nindakake tugas pisanan saka post_tasks Aku bakal pindhah menyang mburi pre_tasks?

Mesthine, tembung pitakon kasebut nuduhake manawa bakal rusak. Nanging apa persis?

... Pawang. Maca dhasar nuduhake kasunyatan sing penting: kabeh pawang disiram kanthi otomatis sawise saben bagean. Sing. kabeh tugas saka pre_tasks, banjur kabeh pawang sing diwenehi kabar. Banjur kabeh peran lan kabeh pawang sing diwenehi kabar ing peran kasebut dieksekusi. Sawise post_tasks lan pawange.

Mangkono, yen sampeyan nyeret tugas saka post_tasks в pre_tasks, banjur duweni potensi sampeyan bakal nglakokake sadurunge pawang dieksekusi. contone, yen ing pre_tasks server web diinstal lan diatur, lan post_tasks soko wis dikirim menyang, banjur transfer tugas iki kanggo bagean pre_tasks bakal mimpin kanggo kasunyatan sing ing wektu "ngirim" server durung mlaku lan kabeh bakal break.

Saiki ayo dipikir maneh, kok perlu pre_tasks и post_tasks? Contone, kanggo ngrampungake kabeh sing dibutuhake (kalebu pawang) sadurunge nindakake peran kasebut. A post_tasks bakal ngidini kita bisa nggarap asil saka peran eksekusi (kalebu handler).

Pakar Ansible sing cerdik bakal ngandhani apa iku. meta: flush_handlers, nanging kok kita kudu flush_handlers yen kita bisa gumantung ing urutan eksekusi bagean ing muter? Kajaba iku, panggunaan meta: flush_handlers bisa menehi kita perkara sing ora dikarepke karo panangan duplikat, menehi bebaya aneh nalika digunakake when у block lsp. Sing luwih apik sampeyan ngerti ansible, luwih akeh nuansa sing bisa dijenengi kanggo solusi "angel". Lan solusi prasaja - nggunakake divisi alam antarane pra / peran / kirim - ora nimbulaké nuansa.

Lan, bali menyang 'foo' kita. Aku kudu nyelehake ing ngendi? Ing pra, kirim utawa peran? Temenan, iki gumantung apa kita kudu asil handler kanggo foo. Yen ora ana, mula foo ora perlu diselehake ing pra utawa kirim - bagean kasebut duwe makna khusus - nglakokake tugas sadurunge lan sawise kode utama.

Saiki, jawaban kanggo pitakonan "peran utawa tugas" teka menyang apa sing wis diputer - yen ana tugas, sampeyan kudu nambah menyang tugas. Yen ana peran, sampeyan kudu nggawe peran (sanajan saka siji tugas). Ayo kula ngelingake sampeyan yen tugas lan peran ora digunakake bebarengan.

Pangerten dhasar Ansible menehi jawaban sing cukup kanggo pitakonan rasa.

Tugas lan peran (bagean loro)

Saiki ayo ngrembug kahanan nalika sampeyan lagi miwiti nulis buku dolanan. Sampeyan kudu nggawe foo, bar lan baz. Apa telung tugas iki, siji peran utawa telung peran? Kanggo ngringkes pitakonan: ing titik apa sampeyan kudu miwiti nulis peran? Apa gunane nulis peran yen bisa nulis tugas?... Apa sing diarani peran?

Salah siji saka kesalahane paling gedhe (Aku wis ngomong bab iki) iku kanggo mikir sing peran kaya fungsi ing perpustakaan program. Kaya apa deskripsi fungsi umum? Nampa argumen input, sesambungan karo panyebab sisih, nindakake efek samping, lan ngasilake nilai.

Saiki, manungsa waé. Apa sing bisa ditindakake saka peran kasebut? Sampeyan tansah welcome kanggo nelpon efek sisih, iki inti saka kabèh Ansible - kanggo nggawe efek sisih. Duwe sabab sisih? SD. Nanging kanthi "pass nilai lan bali" - sing ora bisa digunakake. Pisanan, sampeyan ora bisa menehi nilai menyang peran. Sampeyan bisa nyetel variabel global kanthi ukuran umur play ing bagean vars kanggo peran. Sampeyan bisa nyetel variabel global kanthi umur main ing peran kasebut. Utawa malah karo umur playbooks (set_fact/register). Nanging sampeyan ora bisa duwe "variabel lokal". Sampeyan ora bisa "njupuk nilai" lan "mbalekake".

Wangsulan: Bab ingkang utama nderek saka iki: sampeyan ora bisa nulis soko ing Ansible tanpa nyebabake efek sisih. Ngganti variabel global tansah efek sisih kanggo fungsi. Ing Rust, contone, ngganti variabel global yaiku unsafe. Lan ing Ansible iku mung cara kanggo pengaruhe nilai kanggo peran. Elinga tembung sing digunakake: ora "liwati nilai menyang peran", nanging "ngganti nilai sing digunakake peran". Ora ana pamisahan antarane peran. Ora ana pamisahan antarane tugas lan peran.

Total: peran dudu fungsi.

Apa sing apik babagan peran kasebut? Kaping pisanan, peran kasebut nduweni nilai standar (/default/main.yaml), kapindho, peran kasebut nduweni direktori tambahan kanggo nyimpen file.

Apa keuntungan saka nilai standar? Amarga ing piramida Maslow, tabel prioritas variabel Ansible sing rada kleru, standar peran minangka prioritas sing paling sithik (minus parameter baris perintah Ansible). Iki tegese yen sampeyan kudu menehi nilai standar lan ora kuwatir yen bakal ngatasi nilai-nilai saka inventaris utawa variabel grup, mula standar peran minangka siji-sijine papan sing cocog kanggo sampeyan. (Aku ngapusi sethithik - ana liyane |d(your_default_here), nanging yen kita ngomong babagan panggonan stasioner, banjur mung standar peran).

Apa maneh sing apik babagan peran? Amarga padha duwe katalog dhewe. Iki minangka direktori kanggo variabel, loro konstan (yaiku diwilang kanggo peran) lan dinamis (ana pola utawa anti-pola - include_vars bebarengan karo {{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml.). Iki minangka direktori kanggo files/, templates/. Uga, ngidini sampeyan duwe modul lan plugin dhewe (library/). Nanging, dibandhingake karo tugas ing playbook (sing uga bisa duwe kabeh iki), mung entuk manfaat ing kene yaiku file kasebut ora dibuwang dadi siji tumpukan, nanging sawetara tumpukan sing kapisah.

Rincian liyane: sampeyan bisa nyoba nggawe peran sing bakal kasedhiya kanggo digunakake maneh (liwat galaksi). Kanthi tekane koleksi, distribusi peran bisa dianggep meh dilalekake.

Mangkono, peran duwe rong fitur penting: padha duwe standar (fitur unik) lan ngidini sampeyan ngatur kode sampeyan.

Bali menyang pitakonan asli: nalika nindakake tugas lan nalika nindakake peran? Tugas ing playbook paling asring digunakake minangka "lem" sadurunge / sawise peran, utawa minangka unsur bangunan independen (banjur ora ana peran ing kode). Tumpukan tugas normal sing dicampur karo peran yaiku sloppiness sing ora jelas. Sampeyan kudu netepi gaya tartamtu - salah siji tugas utawa peran. Peran nyedhiyakake pamisahan entitas lan standar, tugas ngidini sampeyan maca kode luwih cepet. Biasane, luwih akeh kode "stasioner" (penting lan kompleks) dilebokake ing peran, lan skrip tambahan ditulis kanthi gaya tugas.

Sampeyan bisa nindakake import_role minangka tugas, nanging yen sampeyan nulis iki, banjur siyap kanggo nerangake kanggo rasa kaendahan dhewe apa sampeyan pengin nindakake iki.

Sing maca sing pinter bisa ngomong yen peran bisa ngimpor peran, peran bisa duwe dependensi liwat galaxy.yml, lan ana uga sing elek lan elek. include_role - Aku ngelingake sampeyan sing kita Ngapikake skills ing Ansible dhasar, lan ora ing senam tokoh.

Handler lan tugas

Ayo ngrembug bab liyane sing jelas: pawang. Ngerti carane nggunakake kanthi bener iku meh seni. Punapa punika prabédan antarane handler lan seret?

Amarga kita ngelingi dhasar, iki contone:

- hosts: group1
  tasks:
    - foo:
      notify: handler1
  handlers:
     - name: handler1
       bar:

Pawang peran dumunung ing rolename/handlers/main.yaml. Handler rummage antarane kabeh peserta muter: pre / post_tasks bisa narik pawang peran, lan peran bisa narik pawang saka muter. Nanging, panggilan "cross-role" menyang pawang nyebabake luwih akeh tinimbang mbaleni pawang sing ora pati penting. (Elemen liya saka praktik paling apik yaiku nyoba ora mbaleni jeneng pawang).

Bentenipun utama iku tugas tansah kaleksanan (idempotently) (plus / minus tags lan when), lan pawang - dening owah-owahan negara (ngabari geni mung yen wis diganti). Apa tegese iki? Contone, yen sampeyan miwiti maneh, yen ora ana owah-owahan, mula ora bakal ana panangan. Napa kita kudu nindakake pawang nalika ora ana owah-owahan ing tugas ngasilake? Contone, amarga ana sing rusak lan diganti, nanging eksekusi ora tekan pawang. Contone, amarga jaringan sementara mudhun. Konfigurasi wis diganti, layanan durung diwiwiti maneh. Ing wektu sabanjuré sampeyan miwiti, config ora diganti maneh, lan layanan tetep karo versi lawas saka config.

Kahanan karo config ora bisa ditanggulangi (luwih tepat, sampeyan bisa invent protokol restart khusus kanggo dhewe karo panji file, etc., nanging iki ora ana maneh 'ansible dhasar' ing sembarang wangun). Nanging ana crita umum liyane: kita nginstal aplikasi kasebut, direkam .service-file, lan saiki kita pengin daemon_reload и state=started. Lan panggonan alam kanggo iki misale jek sing handler. Nanging yen sampeyan nggawe ora handler nanging tugas ing mburi tasklist utawa peran, banjur bakal kaleksanan idempotently saben wektu. Malah yen playbook pecah ing tengah. Iki ora ngrampungake masalah sing diwiwiti maneh (sampeyan ora bisa nindakake tugas kanthi atribut sing diwiwiti maneh, amarga idempotensi ilang), nanging mesthine kudu ditindakake negara = diwiwiti, stabilitas sakabèhé playbook mundhak, amarga nomer sambungan lan negara dinamis sudo.

Properti positif liyane saka pawang yaiku ora ngalangi output. Ora ana owah-owahan - ora ana tambahan sing dilewati utawa ok ing output - luwih gampang diwaca. Iku uga sifat negatif - yen sampeyan nemokake salah ketik ing tugas linear kaleksanan ing roto pisanan, banjur pawang bakal kaleksanan mung nalika diganti, i.e. ing sawetara kahanan - arang banget. Contone, kanggo pisanan ing gesang kawula limang taun mengko. Lan, mesthi, bakal ana salah ketik ing jeneng lan kabeh bakal rusak. Lan yen sampeyan ora mbukak kaping pindho, ora ana owah-owahan.

Kapisah, kita kudu ngomong babagan kasedhiyan variabel. Contone, yen sampeyan ngandhani tugas kanthi loop, apa sing bakal ana ing variabel kasebut? Sampeyan bisa guess analytically, nanging ora tansah ora pati penting, utamané yen variabel teka saka macem-macem panggonan.

... Dadi pawang luwih kurang migunani lan luwih akeh masalah tinimbang sing katon. Yen sampeyan bisa nulis kanthi apik (tanpa embel-embel) tanpa pawang, luwih becik nindakake tanpa dheweke. Yen ora bisa metu apik, iku luwih apik karo wong-wong mau.

Pembaca korosif kanthi bener nuduhake manawa kita durung ngrembug listensing handler bisa nelpon notifikasi kanggo handler liyane, sing handler bisa kalebu import_tasks (sing bisa nindakake include_role karo with_items), sing sistem handler ing Ansible punika Turing-lengkap, sing handler saka include_role intersect ing cara penasaran karo handler saka muter, lsp..d. - kabeh iki jelas dudu "dhasar").

Senajan ana siji WTF tartamtu sing bener fitur sing kudu mbudidaya. Yen tugas wis kaleksanan karo delegate_to lan wis ngabari, banjur pawang cocog kaleksanan tanpa delegate_to, i.e. ing inang ngendi muter diutus. (Sanajan pawang, mesthi, bisa uga duwe delegate_to padha).

Dhewe, aku pengin ngomong sawetara tembung babagan peran sing bisa digunakake maneh. Sadurunge koleksi muncul, ana gagasan sing bisa nggawe peran universal sing bisa ansible-galaxy install lan lunga. Bisa digunakake ing kabeh OS saka kabeh varian ing kabeh kahanan. Dadi, panemuku: ora bisa. Sembarang peran karo massa include_vars, ndhukung 100500 kasus, wis pinasthi jurang saka sudhut kewan omo. Bisa ditutupi karo tes gedhe, nanging kaya tes apa wae, sampeyan duwe produk Cartesian saka nilai input lan fungsi total, utawa sampeyan duwe "skenario individu sing dilindhungi." Mratelakake panemume, luwih apik yen peran kasebut linier (kerumitan cyclomatic 1).

Yen luwih sithik (eksplisit utawa deklaratif - ing wangun when utawa wangun include_vars dening set variabel), luwih apik peran kasebut. Kadhangkala sampeyan kudu nggawe cabang, nanging, aku mbaleni, sing luwih sithik, luwih apik. Dadi misale jek kaya peran apik karo galaksi (kerjane!) karo Bunch saka when bisa uga luwih disenengi tinimbang peran "dhewe" saka limang tugas. Wektu nalika peran karo galaksi luwih apik yaiku nalika sampeyan miwiti nulis. Wayahe nalika dadi luwih elek yaiku nalika ana sing rusak lan sampeyan duwe curiga amarga "peran karo galaksi". Sampeyan mbukak, lan ana limang inklusi, wolung lembar tugas lan tumpukan when'ov... Lan kita kudu ngerti iki. Tinimbang 5 tugas, dhaftar linear kang ana apa-apa kanggo break.

Ing bagean ngisor iki

  • A sethitik babagan persediaan, variabel grup, host_group_vars plugin, hostvars. Carane dasi simpul Gordian karo spageti. Cakupan lan precedence variabel, model memori Ansible. "Dadi ing ngendi kita nyimpen jeneng pangguna kanggo database?"
  • jinja: {{ jinja }} - nosql nosense plastisin alus. Ana ing endi wae, sanajan sampeyan ora nyana. A sethitik babagan !!unsafe lan yaml éca.

Source: www.habr.com

Add a comment