Fabric: 'peran' yang kompatibel dengan v2 atau serupa

Dibuat pada 22 Apr 2017  ·  7Komentar  ·  Sumber: fabric/fabric

Ringkasan

Pada saat penulisan, cabang v2 memiliki kelas Group yang seharusnya dapat berfungsi sebagai unit yang sebelumnya dikenal sebagai 'peran', alias "sekelompok host untuk melakukan hal-hal dengan/di".

Namun, belum ada cara khusus untuk mengatur atau melabeli objek Group ; itu "selesai" cukup untuk kasus penggunaan API murni dari pengguna tingkat lanjut yang ingin menggulirkan cara spesifik mereka sendiri untuk membuatnya, tetapi tidak memiliki apa pun untuk pengguna yang berorientasi CLI atau orang perantara yang menginginkan sesuatu yang kerangka kerja untuk dibangun.

Dengan kata lain, kecuali Anda menggulirkan murni dengan API, memiliki objek Grup yang tergeletak di suatu tempat tidak berguna jika bit CLI atau pemanggilan tugas tidak memiliki cara untuk menemukannya!

Latar belakang

Di v1, peran secara efektif adalah satu namespace datar yang memetakan label string sederhana ke apa yang akan menjadi Grup di v2, dan mereka dapat dipilih pada CLI saat runtime ( fab --roles=web,db ) dan/atau terdaftar sebagai target default untuk tugas ( @task('db') \n def migrate(): ), seperti host.

Pengguna mendefinisikannya dalam env.roledefs , sebuah dict sederhana; fungsionalitas menengah hingga lanjutan apa pun berkisar pada memodifikasinya, biasanya saat runtime (melalui pra-tugas atau subrutin), terkadang pada waktu muat modul.

Kasus penggunaan / kebutuhan / subfitur khusus

  • Pemetaan dasar dan naif untuk digunakan/referensi di tempat lain dalam sistem: masukkan nama, dapatkan kembali beberapa iterable Group s dan/atau Connection s.

    • Aliasing sering kali ingin mengikutinya, jadi misalnya Lexicon bukannya dict .

    • Bahkan konstruksi yang lebih dalam, seperti 'bundling', misalnya Anda memiliki pemetaan langsung bernama db , web , lb , tetapi kemudian nama tingkat ke-2 disebut prod yang selalu merupakan gabungan dari tiga lainnya. Saya lupa apakah saya sudah menambahkannya ke Lexicon . Mungkin ada subkelas peta lain di luar sana yang sudah melakukannya juga.

    • Selain itu/bergantian, hal-hal seperti globbing atau sintaks string lainnya, meskipun saya pribadi lebih suka memanfaatkan fakta bahwa Python tidak "diketik secara string"...

  • 'Pemetaan terbalik' yang berguna sehingga Anda dapat mengidentifikasi grup mana yang dimiliki Koneksi tertentu.

    • Bermasalah: karena saat ini tidak ada status bersama global, jawaban naif untuk ini - menggunakan identitas - gagal karena Anda secara teknis dapat membuat beberapa objek Koneksi yang identik.

    • Terutama karena Grup dapat membuatnya secara implisit atas nama Anda jika Anda hanya memberikan string host singkatan, meskipun itu hanya opsi kenyamanan.

    • Namun, mengingat batasan tidak adanya status global, saya tidak dapat melihat masalah yang jelas dengan menggunakan pengujian kesetaraan, jadi itu seharusnya bisa dilakukan, misalnya if cxn in group akan berfungsi bahkan jika cxn adalah objek yang berbeda dari anggota yang sama di dalam group .

    • Satu-satunya hal yang terlintas dalam pikiran adalah jika ada tautan yang kuat dan stateful dari Koneksi ke Grup (harus berupa grup, jamak) yang menahannya, alih-alih sebaliknya, tetapi saya tidak dapat melihat alasan bagus untuk itu begitu saja.

  • Sangat terkait dengan yang sebelumnya: kemampuan untuk memeriksa/menampilkan apa "peran yang berjalan saat ini" (sesuatu yang diinginkan orang untuk waktu yang lama di v1 yang tidak sepele karena desainnya)

    • Masalah utama adalah bahwa ini benar-benar dua pertanyaan semi berbeda: "peran apa yang menjadi bagian Host saat ini, secara umum" (pada dasarnya, kasus penggunaan sebelumnya dari pencarian terbalik) tetapi juga "peran apa adalah mesin eksekusi yang secara khusus diminta untuk melawan".

    • Dengan kata lain, host 'foo' yang diberikan milik peran A, B dan C: dalam tugas tertentu yang konteksnya 'foo', tetapi dijalankan karena permintaan untuk 'mengeksekusi pada peran A', adalah yang dicari pengguna jawaban "A, B dan C" (peran 'foo' secara keseluruhan) atau hanya "A" (peran yang sedang dijalankan)?

    • Ini benar-benar terasa seperti dua panggilan API yang berbeda, meskipun permintaan fitur yang saya ingat menggabungkan keduanya.

  • Pemilihan target pada CLI, secara global dan/atau per tugas

    • Perpanjangan sistem CLI Invoke untuk memperhitungkan "tanda bahwa semua tugas berada di atas apa yang mereka tetapkan" mungkin berguna atau diperlukan untuk ini. Yang jatuh dengan kuat ke dalam wilayah pyinvoke/invoke#205, pada kenyataannya, sehingga mendapat prioritas lebih tinggi daripada yang sudah ada (yang cukup tinggi.)

  • Ditto default tingkat tugas

    • Meskipun default target tingkat tugas benar-benar ingin menjadi salah satu dari: koneksi, koneksi, grup obj, grup objs, atau nama yang mengevaluasi _to_ grup objs (yang terakhir adalah satu-satunya hal yang secara langsung berkaitan dengan tiket ini, bisa dibilang)

  • Default tingkat koleksi Ditto (BARU di v2!)

    • Yaitu "semua tugas di $submodule default untuk dijalankan melawan peran db "

    • Kesepakatan yang sama seperti poin sebelumnya - default ini ingin mengizinkan sejumlah nilai yang berbeda, bukan hanya kunci string.

  • Adakah hal baru dan menarik lainnya yang dimungkinkan oleh pendekatan OO yang benar-benar ingin sejalan dengan ini? Ingat penekanan harus pada blok bangunan dan memungkinkan pengguna tingkat lanjut, bukan pada misalnya benar-benar menciptakan kembali sistem seperti Chef atau Ansible.

Ide/masalah implementasi

  • Jika kita menggunakan sistem konfigurasi sebagai vektor penyimpanan utama, nilai "ingin" menjadi primitif sehingga dapat disimpan dalam yaml, json dll, tetapi itu adalah sekaleng worm yang diakhiri dengan "simpan semua kwargs Grup/Koneksi dalam ukuran besar' list-o-dicts", dll.
  • Jika kita mengharapkan definisi terutama dalam Python, kita cukup mengatakan "membuat instance objek Grup", dan kemudian kita memiliki opsi untuk menggabungkan data itu ke dalam sistem konfigurasi atau membiarkannya berdiri sendiri.

    • Saya pikir saya lebih suka yang terakhir karena memasukkan semuanya ke dalam dicts konfigurasi bersarang terasa seperti itu akan mengarah pada berita buruk.

  • Konstruksi yang lebih dalam seperti aliasing dan bundling menambah kompleksitas & masalah pemesanan (yaitu bayangkan pengaturan alias sepele di mana nilai key1 adalah grup tetapi nilai key2 adalah key1; sekarang Anda harus merayapi struktur dua kali untuk menyelesaikan atau memeriksa key2)

    • meskipun jika kita menggunakan sebagian besar pendekatan "lakukan di-python", itu menjadi seperti API sistem konfigurasi, di mana Anda dapat memulai dengan struktur deklaratif tetapi apa pun yang lebih diaktifkan oleh pemanggilan metode setelah pengaturan awal itu. Saya tidak berpikir itu mengerikan? EDIT: dan saya pikir itulah cara kerja Lexicon.

  • Terlepas dari formatnya, kita harus mencari tahu bagaimana pengguna tingkat lanjut ingin membuatnya dengan cepat dari sumber eksternal atau yang serupa; ini ditambah masalah dengan aliasing dan semacamnya, menyiratkan bahwa kita mungkin tidak menginginkan ini dalam struktur naif "disimpan" di suatu tempat, tetapi sebagai API pada beberapa objek atau objek yang dipanggil untuk membuatnya.

    • Saya menduga kami mungkin ingin bekerja 'ke bawah' dari pemilihan peran/grup, sampai pada API tingkat tertinggi apa pun untuk "mengubah apa yang disediakan pengguna menjadi unit target yang dapat ditindaklanjuti", karena pengguna paling mahir pasti ingin memiliki kendali penuh atas implementasi panggilan API itu. Kemudian kita seperti biasa dapat memberikan apa yang terasa seperti kasus umum yang berguna tetapi yang ditandai dengan jelas sebagai "hanya satu cara untuk melakukannya".

    • @RedKrieg memiliki ide bagus di sepanjang baris ini di mana kami memiliki @group seperti @task , dan fungsinya bukan unit kerja yang dapat dieksekusi, tetapi menghasilkan objek Grup.

    • Pendekatan ini secara asli menggunakan kembali hierarki tugas (Koleksi), yang praktis (mengapa menemukan kembali roda) dan elegan (karena dalam kasus dunia nyata, definisi peran/grup sering DO memetakan sangat dekat dengan tugas yang menggunakannya!)



      • Ini juga berfungsi dengan baik bahkan jika grup Anda TIDAK memetakan ke tugas Anda, karena Anda cukup menulis definisi di tingkat koleksi root Anda. Mudah.



    • Tidak jelas bagi saya apakah ini yang terbaik untuk mengembalikan satu Grup dari setiap fungsi, atau jika kami ingin kemampuan untuk menghasilkan beberapa grup (atau koneksi), atau apakah yang terbaik untuk melakukannya bukan sebagai fungsi yang didekorasi sama sekali tetapi hanya sebagai panggilan API Koleksi (seperti bagaimana konfigurasi tingkat koleksi disimpan).

    • Misalnya, kasus penggunaan di mana data grup/peran bersifat dinamis dan di luar Fabric masih perlu diselesaikan di sini (itulah sebabnya sebelumnya saya mencatat bahwa pertama-tama kita harus mengidentifikasi API tingkat tertinggi untuk ruang ini; kemudian kita perlu melihat bagaimana kaitan itu dengan ide tingkat menengah ini.)

Feature

Komentar yang paling membantu

Hai, saya tidak tahu apa yang terjadi pada perangkat lunak ini setelah bertahun-tahun, tetapi saya sangat merindukan konsep "peran" di [email protected] , terutama saat menjalankan $ fab -R dev

Semua 7 komentar

Dari milis:

Kami menerapkan API REST internal kami sendiri yang mengisi env.roledefs secara dinamis tergantung pada proyek yang diterapkan dan sangat bergantung pada tidak menyematkan string host ke fabfile proyek atau menetapkannya di CLI.

Kasus penggunaan kami adalah:

  1. Basis kode bebas lingkungan https://12factor.net/config. Lingkungan (peran) dan string host masing-masing disimpan dalam database terpusat. Setiap fabfile.py memiliki sesuatu seperti ini (ini mengisi env.roledefs ketika file diimpor):
EnvironmentDatabaseAPIClient(
    'https://rest.api.url/schema/',
    env.service_name,
).apply_env()
  1. Jumlah lingkungan server - beberapa lingkungan pengujian (beberapa di antaranya bersifat pribadi, beberapa publik) dan beberapa lingkungan produksi (untuk klien yang berbeda). Setiap lingkungan terdiri dari satu atau lebih host dan dipetakan ke peran fabric.

  2. Setiap layanan ( env.service_name dalam contoh di atas) memiliki set lingkungan yang berbeda.

  3. Kami juga memiliki meta-roles (kelompok peran). Mereka diawali dengan group- : group-production , group-test , group-external , group-internal , group-all . Ini memungkinkan kita untuk menerapkan ke beberapa peran server tanpa menentukannya satu per satu, misalnya group-all menyebarkan ke semua peran, baik produksi maupun pengujian.

  4. Kami memiliki tugas fabric khusus untuk mencetak informasi tentang grup peran, peran, dan pembawa acara.

  5. Kami juga sangat bergantung pada string host pemetaan terbalik kembali ke nama peran (string host unik per service_name). Ini digunakan untuk pencatatan dan pemberitahuan penerapan. Pada dasarnya, kami mencatat penerapan layanan ke setiap host dan mengirim pemberitahuan Slack saat layanan telah diterapkan ke semua host dalam suatu peran. Server EnvironmentDatabaseAPI bertanggung jawab untuk ini (ia menyimpan log dan status penerapan). Ini dilakukan dengan mendekorasi tugas fabric dengan dekorator yang mengirimkan env.host , env.port dan env.service_name (ditambah info komit) kembali ke server API.

  6. Kami berencana untuk menambahkan otentikasi penerapan di masa mendatang, juga sangat mungkin untuk menarik lebih banyak variabel env dari server untuk membuatnya tersedia dalam konteks tugas.

Terima kasih @max-Arnold! Saya mengenali banyak dari mereka dari kasus penggunaan saya sendiri di masa lalu juga. Bit pemetaan terbalik khususnya saya ingat muncul di v1 beberapa kali, jadi saya menambahkannya ke daftar.

Agar Fabric v2 berguna bagi saya, saya memerlukan cara untuk memberi tahu fab kumpulan host mana yang akan menjalankan tugas.

Sebelumnya saya mendefinisikan peran dan kemudian menjalankan fab -R ... . (Sebenarnya peran didefinisikan secara terprogram menggunakan rentang alamat IP, tetapi itu bukan persyaratan dan daftar statis di dalam file YAML akan baik-baik saja.)

Saya gagal menemukan yang setara di Fabric v2, dan saya juga gagal meniru fitur ini menggunakan:

  • file konfigurasi fabric.yaml berisi
active_hostset: null
hostsets:
  myhostset:
  - ...
  • active_hostset = config["hostsets"][config["active_hostset"]] dalam fabfile.py
  • env INVOKE_ACTIVE_HOSTSET=myhostset fab ...

Alih-alih daftar host yang diharapkan, saya mendapatkan KeyError: 'active_hostset' .

Kami memetakan kumpulan host yang berbeda ke setiap peran untuk setiap lingkungan kami di fabric v1, dan lingkungan diatur dengan menjalankan tugas role.environment:staging untuk menentukannya. Jadi tugas ini memengaruhi host yang digunakan oleh tugas-tugas berikut.

Di v2 kami mencoba menggunakan Tugas khusus, tetapi masalahnya adalah Executor.expand_calls berjalan sebelum tugas role.environment berjalan sehingga tidak ada tugas berikut yang mengetahui lingkungan untuk membangun daftar host mereka secara dinamis.

Menjadikan Executor.expand_calls sebagai generator memungkinkan eksekusi tugas memengaruhi eksekusi tugas selanjutnya. Jadi contoh saya di atas berfungsi, di mana kami memiliki Task yang perlu mengetahui lingkungannya untuk memperluas peran dengan benar ke host. misalnya fab role.environment dev deploy.app - tugas role.environment sekarang dijalankan sebelum deploy.app diperluas, sehingga deploy.app mengetahui lingkungan dan dapat mengonfigurasi host-nya dan kemudian diperluas ke kumpulan tugas yang benar.

Saya membuat prototipe ini di garpu saya:
https://github.com/pyinvoke/invoke/compare/master...rectalogic :expand-generator
https://github.com/fabric/fabric/compare/master...rectalogic :expand-generator

Hai, saya tidak tahu apa yang terjadi pada perangkat lunak ini setelah bertahun-tahun, tetapi saya sangat merindukan konsep "peran" di [email protected] , terutama saat menjalankan $ fab -R dev

Kami juga menggunakan peran untuk mewakili rangkaian operasi yang sama di lingkungan yang berbeda. Mungkin memisahkan konsep peran bernama dan lingkungan bernama akan berguna? Seperti, peran web di lingkungan dev.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat