Sebagai pengembang perangkat lunak inti di Cloudify.co, saya sering bekerja pada host jarak jauh yang diterapkan pada layanan cloud seperti AWS atau Openstack. Jenis pekerjaan ini, membuat Anda bertanya-tanya: bagaimana cara menjalankan perintah (skrip) yang sama pada semuanya secara otomatis? Jawabannya biasanya menggunakan Ansible atau Fabric. Pada artikel ini, saya memutuskan untuk fokus pada solusi Fabric.

Apa itu Kain?

Fabric adalah pustaka Python tingkat tinggi (2.7, 3.4+) yang dirancang untuk menjalankan perintah shell dari jarak jauh melalui SSH, menghasilkan objek Python yang berguna sebagai imbalannya (situs web Fabric).

Mari kita melakukan coding dengannya. (Saya menggunakan Python 3.6 dan Fabric 2.5.0)

Memulai — Membuat koneksi:

Karena kita menggunakan python, cara terbaik untuk menunjukkan kemampuan Fabric adalah dengan menggunakan sebuah objek yang kita sebut `Host`.

class Host(object):
    def __init__(self,
                 host_ip,
                 username,
                 key_file_path):
        self.host_ip = host_ip
        self.username = username
        self.key_file_path = key_file_path

    def _get_connection(self):
        connect_kwargs = {'key_filename': self.key_file_path}
        return Connection(host=self.host_ip, user=self.username, 
                          port=22,
                          connect_kwargs=connect_kwargs)

Pada kode di atas, `Host` digunakan sebagai “host jarak jauh”, dan fungsi `_get_connection` digunakan untuk membuat koneksi SSH ke sana. (“untuk membaca lebih lanjut tentang `Koneksi`»). Kami akan menggunakan Connection sebagai pengelola konteks karena memiliki siklus hidup dasar “buat, sambungkan/buka, lakukan pekerjaan, putuskan/tutup” (dari dokumen).

Menjalankan perintah:

Sekarang kita memiliki Koneksi, kita dapat menjalankan perintah pada host jarak jauh kita. Fungsi berikut ditambahkan ke objek `Host`:

def run_command(self, command):
    try:
        with self._get_connection() as connection:
            print('Running `{0}` on {1}'.format(command,   
                   self.host_ip))
            result = connection.run(command, warn=True, 
                                    hide='stderr')
    except (socket_error, AuthenticationException) as exc:
        self._raise_authentication_err(exc)

    if result.failed:
        raise ExampleException(
            'The command `{0}` on host {1} failed with the error: '
            '{2}'.format(command, self.host_ip, str(result.stderr)))

def put_file(self, local_path, remote_path):
    try:
        with self._get_connection() as connection:
            print('Copying {0} to {1} on host {2}'.format(
                local_path, remote_path, self.host_ip))
            connection.put(local_path, remote_path)
    except (socket_error, AuthenticationException) as exc:
        self._raise_authentication_err(exc)

def _raise_authentication_err(self, exc):
    raise ExampleException(
        "SSH: could not connect to {host} "
        "(username: {user}, key: {key}): {exc}".format(
            host=self.host_ip, user=self.username,
            key=self.key_file_path, exc=exc))

Pada kode di atas, fungsinya:

`run_command` digunakan untuk menjalankan perintah pada host jarak jauh. Anda dapat meneruskan fungsi `Connect.run` banyak parameter berbeda (seperti yang dijelaskan di sini), tetapi yang saya perlukan untuk mekanisme "penangkapan kesalahan" adalah:

  • `warn=True`: Jangan memunculkan pengecualian ketika perintah yang dijalankan keluar dengan status bukan nol (artinya gagal).
  • `hide='stderr'`: Jangan salin stderr subproses ke terminal pengontrol.

Perilaku default `Connection.run` adalah menyalin stdout dan stderr subproses ke terminal pengontrol.

`put_file` digunakan untuk menyalin file dari host lokal ke host jarak jauh. (“untuk membaca lebih lanjut tentang `Connection.put`»)

Penting untuk diperhatikan, kelas Connection bersifat “lazy”, artinya ketika kita memulainya, kelas tersebut tidak mencoba terhubung ke host. Oleh karena itu, kami menempatkan perintah kami di blok coba-kecuali yang menangkap kesalahan koneksi.

Ringkasan:

Keputusan untuk memilih antara Ansible dan Fabric sering kali bergantung pada apa yang ingin Anda jalankan di host jarak jauh? Jika skripnya sederhana, maka Fabric seharusnya cukup bagus, jika tidak, Ansible mungkin merupakan pilihan yang lebih baik. Apa pun pilihannya, Cloudify Manager memungkinkan Anda memilih solusi mana pun yang sesuai untuk Anda menggunakan plugin Ansible dan Fabric. Selamat bersenang-senang! :)

Lampiran:

Berikut adalah contoh kode lengkap yang dapat Anda gunakan (ingat untuk mengganti parameter `Host` agar sesuai dengan parameter Anda):