Integrasi Satelit dan Menara yang Mungkin

Menggunakan Red Hat Satellite dan Red Hat Anomatisasi Automation Platform? Dimulai dengan Satelit 6.3, mereka dapat diintegrasikan satu sama lain sehingga Inventarisasi Dinamis di Menara yang Mungkin menarik daftar host dari Satelit. Selain itu, jika host RHEL diinisialisasi menggunakan Satelit (yang berarti penyediaan), maka Ansible Tower dapat diintegrasikan ke dalam proses ini sehingga secara otomatis menjalankan skrip konfigurasi pada host baru.



Dalam posting ini, kita akan melihat cara mengkonfigurasi Inventaris Dinamis di Menara yang Mungkin sehingga menarik host dari Satelit, dan kami akan menunjukkan cara menggunakannya dengan contoh. Selain itu, kami akan menunjukkan kepada Anda bagaimana mengatur panggilan otomatis ke Ansible Tower setelah menginisialisasi host baru dari Satellite.

1. Inventory. Satellite, Dynamic Inventory Ansible Tower


Agar Ansible Tower memiliki akses ke daftar host, grup host, dan informasi terkait lainnya, diperlukan akun di Satelit. Entri ini memiliki izin minimal yang cukup, jadi kami akan membuat peran baru di Satelit, memberikannya hanya izin yang diperlukan untuk Ansible Tower, lalu membuat akun baru dan menetapkannya peran ini.

Satelit 6.6 dan yang lebih baru sudah memiliki peran Pembaca Inventaris Menara Anonim yang siap untuk ini, sehingga Anda dapat melewati langkah-langkah di bawah ini untuk membuat peran.

Dalam Satelit 6.3-6.5, peran harus dibuat dengan tangan. Untuk melakukan ini, pergi ke antarmuka web satelit, buka layar Administer, pilih Peran dan klik Buat Peran.

Kami menamai peran ini ansible_tower_integration_role dan menetapkan Lokasi dan Organisasi untuknya :



Klik Kirim untuk membuat peran. Setelah itu, klik namanya dan pergi ke tab Filter. Klik tombol Filter Baru hijau dan tambahkan filter berikut, satu per satu:

Jenis Sumber Daya: Host , Izin: view_hosts
Jenis Sumber Daya: Host Group , Izin: view_hostgroups
Jenis Sumber Daya: Nilai fakta , Izin: view_facts

Akibatnya, filter berikut harus memiliki peran:



Jadi, kami telah menciptakan peran. Sekarang kita akan memulai pengguna baru di Satelit, yang mana kita pergi ke menu Administer , pilih Pengguna dan klik Buat Pengguna . Kami menamai pengguna ini ansible_integration , mengubah parameter Authorized by menjadi INTERNAL dan mengatur kata sandi. Kemudian, pada tab Lokasi dan Organisasi , pilih lokasi / organisasi yang sesuai. Terakhir, buka tab Roles dan berikan pengguna ini peran ansible_tower_integration_role yang baru dibuat (jika Anda memiliki Satelit 6.3 - 6.5) atau peran Pembaca Inventarisasi Menara Anonim yang tertanam di dalamnya(Satelit 6,6 dan lebih tinggi). Terakhir, klik Kirim untuk membuat akun untuk pengguna ini.

Sesuaikan Menara yang Mungkin


Sekarang pergi ke antarmuka web Ansible Tower dan pergi ke layar Kredensial . Klik tombol hijau + (Tambah) untuk membuat entri Kredensial baru. Kami menyebutnya satellite_integration , dan dalam Credential Type kami tentukan Red Hat Satellite 6 . Kemudian kami memasukkan URL (dalam kasus kami Satellite 6), serta nama pengguna (dalam kasus kami ansible_integration ), dan kata sandi adalah yang kami atur di satelit di atas:



Kemudian klik Simpan .

Sekarang pergi ke layar Persediaan , klik tombol hijau + (Tambah) dan pilih Persediaan . Tetapkan satellite_inventory sebagai nama dan klik Simpan untuk membuat inventaris. Setelah itu, buka tab Sumber dari inventaris yang baru dibuat dan klik tombol hijau + (Tambah) . Kami menggunakan satelit sebagai nama sumber , dan menentukan jenis sumber sebagai Red Hat Satellite 6 . Di bidang Kredensial, tentukan satellite_integration , yang telah dibuat pada langkah sebelumnya. Aktifkan kotak centang Timpa ,Timpa Variabel dan Pembaruan saat Peluncuran di grup kontrol Opsi Pembaruan (Anda dapat mempelajari lebih lanjut tentang opsi ini menggunakan tanda tanya di sebelah kanan). Selain itu, di bidang Batas Waktu Cache (Detik) , masukkan 90 dan klik Simpan .



Sekarang, tanpa meninggalkan tab Sumber , klik ikon Mulai proses sinkronisasi :



Kami menunggu hingga ikon berubah hijau - ini menandakan penyelesaian sinkronisasi yang berhasil.

Sekarang Anda dapat pergi ke tab Hosts dan melihat data yang telah ditarik dari Satelit:



Anda juga dapat melihat tab Grup:



Seperti yang Anda lihat, sinkronisasi tidak hanya menarik daftar host dari Satelit, tetapi juga membaginya menjadi kelompok-kelompok sesuai dengan tampilan konten yang sesuai di Satelit, grup host, lingkungan siklus hidup, lokasi, dan organisasi. Pengelompokan ini dapat digunakan untuk menargetkan skrip yang mungkin pada host target, dan ini adalah hal yang sangat kuat.

Jika Anda memilih host pada tab Host, kita akan melihat bahwa antara Satellite dan Ansible Tower banyak informasi tambahan tentang host disinkronkan, yang disajikan dalam bentuk variabel. Variabel-variabel ini kemudian dapat digunakan dalam skrip Ansible:



Menggunakan Inventaris Dinamis yang Terikat ke Satelit


Jadi, kami menyinkronkan Satellite dan Ansible Tower. Sekarang kami akan mempertimbangkan bagaimana menggunakannya dalam praktik.

Cara termudah adalah dengan menggunakan satellite_inventory sebagai sumber Inventaris di Ansible Tower Template. Jika host: semua opsi ditentukan dalam skrip , skrip akan dijalankan pada semua host Satelit.

Opsi yang lebih maju adalah dengan menggunakan grup inventaris yang dibuat secara otomatis dalam skrip (bagaimana mereka dibuat - lihat di atas), dengan kata lain, tentukan grup host yang diinginkan di baris host . Misalnya, seperti dalam skenario ini di mana paket layar diinstal:

---
- name: Install screen package
  hosts: "foreman_hostgroup_rhel6"
  tasks:
  - yum:
      name: screen
      state: installed

Di sini kami telah mendaftarkan host: foreman_hostgroup_rhel6 , dengan demikian menunjukkan daftar host yang membentuk grup host rhel6 di Satelit. Dengan demikian, skrip akan dieksekusi hanya pada host ini.

Selain itu, dalam skrip, Anda dapat menentukan di host baris variabel-variabel yang diterima Menara An menara selama sinkronisasi dengan satelit. Misalnya, Anda dapat melakukan ini:

---
- name: Install screen package
  hosts: "{{ hosts_var }}"
  tasks:
  - yum:
      name: screen
      state: installed

Akibatnya, kami akan dapat mengubah templat pekerjaan di Ansible Tower on the fly, yang menunjukkan salah satu grup inventaris melalui variabel eksternal.



Dalam contoh ini, templat hanya akan berjalan di host yang merupakan anggota grup rhel7 di Satelit.

Selain itu, templat pekerjaan dapat dikonfigurasikan sehingga pada saat startup akan meminta pengguna untuk nilai variabel hosts_var (dan pada saat yang sama menampilkan grup inventaris yang tersedia dalam bentuk komentar):



Layar di atas menggambarkan situasi ketika, ketika memulai templat, pengguna diminta untuk memasukkan nama grup inventaris satelit yang host-nya ingin Anda jalankan skrip.

Selain itu, Anda dapat menggunakan variabel host yang ditarik dari Satelit selama sinkronisasi. Misalnya, inilah yang terlihat seperti skrip yang menunjukkan cara mereferensi variabel-variabel ini:

---
- name: Show Satellite variables
  hosts: all
  tasks:
  - name: Show subscription_status
    debug:
      msg: >
        Subscription Status: {{ foreman.subscription_status_label }}
  - name: Show Errata Counts
    debug:
      msg: >
        Bug fixes: {{ foreman.content_facet_attributes.errata_counts.bugfix }},
        Security: {{ foreman.content_facet_attributes.errata_counts.security }},
        Enhancement: {{ foreman.content_facet_attributes.errata_counts.enhancement }},
        Total: {{ foreman.content_facet_attributes.errata_counts.total }}

Jika Anda menjalankan skrip ini di Ansible Tower, itu akan menampilkan nilai-nilai variabel:



Dan tentu saja, variabel-variabel ini dapat digunakan dalam konstruksi bersyarat kapan, sehingga tugas diluncurkan hanya dalam kondisi tertentu. Misalnya, jika host tidak memiliki patch keamanan, atau ketika berlangganan host tidak valid.

Untuk meringkas


Satelit Red Hat dan Red Hat Ansible sendiri adalah alat yang sangat kuat, dan integrasi mereka memberikan sinergi nyata. Di atas, kami menunjukkan cara menjadikan Satellite sumber data untuk Inventarisasi Dinamis dalam Ansible dan menggunakannya dalam praktik.
 

Bagian 2. Konfigurasi otomatis host baru melalui penyediaan panggilan balik


Selain banyak fitur lainnya, Satellite juga dapat menginisialisasi host, dengan kata lain, melakukan penyediaan. Ansible Tower, pada gilirannya, dirancang untuk mengkonfigurasi host. Integrasi memungkinkan Anda memastikan bahwa setelah inisialisasi host RHEL baru melalui Satelit, Ansible Tower akan secara otomatis terhubung ke host ini dan menjalankan skrip konfigurasi yang sesuai di dalamnya. Jelas, skema semacam itu menghemat banyak waktu bagi administrator sistem, membantu mereka merespons lebih cepat terhadap kebutuhan organisasi.

Perlu dicatat bahwa skema ini hanya berfungsi jika beberapa kondisi terpenuhi. Pertama, Satelit harus digunakan sebagai sumber data Inventaris Dinamis di Ansible Tower (kami membahas masalah ini di bagian sebelumnya). Kedua, inisialisasi host tidak hanya harus dilakukan melalui satelit, tetapi juga bekerja melalui mekanisme grup host (untuk rincian lebih lanjut, lihat Panduan Penyediaan ).

Di bawah ini kami menunjukkan cara mengkonfigurasi Satellite dan Ansible Tower sehingga setelah menginisialisasi host, ia akan secara otomatis menjalankan skrip konfigurasi Ansible.

Gambaran


Alat otomatisasi TI, seperti Ansible Tower, biasanya jatuh ke dalam salah satu dari dua kategori: beberapa bekerja dengan metode dorong, yang lain dengan metode tarikan. Dalam sistem dorong yang dimiliki Ansible Tower, server otomatisasi memulai koneksi ke host. Dalam sistem tarik, inisiator adalah tuan rumah, yang dengan sendirinya berkomunikasi dengan server otomatisasi.

Dalam kasus kami, dengan skrip otomatis pada host baru, skema campuran digunakan. Tuan rumah yang baru diinisialisasi menghubungi server otomatisasi dengan permintaan untuk "menelepon kembali" ke sana dan mengkonfigurasi. Setelah itu, server otomasi terhubung ke host ini dan menjalankan skrip konfigurasi yang diminta oleh host di atasnya. Oleh karena itu, di Ansible Tower mekanisme ini disebut penyediaan panggilan balik, yang dapat diterjemahkan sebagai "panggilan balik inisialisasi".

Untuk menunjukkan mengapa penyediaan panggilan balik diperlukan sama sekali, pertimbangkan situasi berikut: kami memiliki skrip konfigurasi host tertentu yang berjalan setiap hari di tengah malam. Katakanlah pada jam 8 pagi, kami sedang menginisialisasi beberapa server baru sekaligus melalui Satelit. Pada saat yang sama, Satelit digunakan sebagai sumber data Inventaris Dinamis di Ansible Tower, sehingga host yang dibuat secara otomatis jatuh ke dalam Ansible. Namun, peluncuran skrip otomasi berikutnya hanya akan berlangsung pada tengah malam, yaitu setelah 16 jam. Jelas, ini jauh dari ideal, dan saya ingin skrip dijalankan segera setelah inisialisasi host baru. Untuk tujuan ini, penyediaan panggilan balik juga dipertimbangkan.

Secara umum, penyediaan panggilan balik dikonfigurasikan dan berfungsi sebagai berikut:

  1. Ansible Tower credential root, Satellite . Tower , .
  2. Job Template Ansible Tower provisioning callback. URL Host Config Key, Ansible.
  3. Satellite , provisioning callback Ansible Tower, : URL- Ansible Tower, Host Config Key Ansible.
  4. Satellite /etc/systemd/system/ansible-callback.service ( RHEL 7 8; RHEL 6 ). provisioning callback Ansible Tower, , (URL-, Host Config Key ).
  5. Ansible Tower Host Config Key. , Tower , root, Job Template. , .

Ansible Tower Provisioning Callback


Mari kita mulai dengan membuat skrip konfigurasi pada server Ansible Tower yang mengubah konten / etc / motd, membuat beberapa jenis pengguna, dan menginstal paket tertentu. Kemudian kita akan menggunakan skrip ini untuk mengkonfigurasi host baru segera setelah diinisialisasi.

Dalam kehidupan nyata, skrip otomatisasi kemungkinan besar disimpan di beberapa sistem kontrol versi, tetapi untuk kesederhanaan, kami menganggap bahwa skrip tersebut terletak langsung di server Ansible Tower. Oleh karena itu, kami memasuki server Ansible Tower melalui SSH dan membuat direktori / var / lib / awx / proyek / ketentuan untuk mereka dengan menjalankan perintah berikut:

# mkdir /var/lib/awx/projects/provision

Kemudian kita buat skrip kita di direktori ini, sebut itu provision.yaml dan tulis konten berikut ke dalamnya:

---

- name: Provision new host

  hosts: all

  tasks:

  - name: Set content in /etc/motd 

    copy:

      content: Authorized use only!

      dest: /etc/motd

      mode: 644

      owner: root

      group: root


  - name: Create brian user account

    user:

      name: brian

      uid: 10000

      state: present


  - name: Install tmux package

    yum:

      name: tmux

      state: present


Sekarang pergi ke antarmuka web Tower dan pergi ke layar Kredensial. Klik tombol tanda tambah hijau untuk membuat entri kredensial baru, berikan nama provisioning_root, dan atur Jenis Kredensial ke Mesin. Di bidang Nama Pengguna, tulis root, dan di bidang Kata Sandi, tentukan kata sandi yang ditentukan dalam Satelit untuk digunakan pada host baru grup host terkait di Satelit (namanya dapat ditemukan di antarmuka web Satelit pada tab Sistem Operasi). Dengan menggunakan entri ini, Ansible Tower akan dapat masuk ke host baru yang dibuat selama inisialisasi melalui Satelit.



Setelah itu, di antarmuka Ansible Tower, buka layar Projects dan klik tanda tambah hijau untuk membuat proyek baru. Sebut saja ketentuan, ubah Jenis SCM ke Manual, dan tentukan ketentuan sebagai Direktori Playbook:



Kemudian, di antarmuka Ansible Tower, buka layar Templates, klik tanda plus hijau untuk membuat Template Pekerjaan baru. Kami akan menyebutnya ketentuan, di bidang Inventaris, kami akan menulis Satelit, di bidang Proyek - penyediaan, di bidang Playbook - provision.yaml, dan di bidang Kredensial - provisioning_root. Selain itu, Anda perlu mengaktifkan kotak centang Izinkan Panggilan Provisi dan klik ikon tongkat ajaib di sebelah kanan bidang Host Config Key untuk menghasilkan kunci rahasia. Kunci ini diperlukan untuk meminta panggilan balik penyediaan tidak bisa siapa pun, tetapi hanya seseorang yang mengetahui Kunci Konfigurasi Host. Tanpa kunci yang benar, server Ansible Tower tidak akan menanggapi permintaan.



Sekarang kita perlu mengingat untuk masa depan nilai Host Config Key, serta ID Templat, yang dapat ditemukan dari URL Templat Pekerjaan ini:

https://tower.example.com/#/templates/job_template/11

Dalam contoh ini, ID-nya adalah 11.

Mengkonfigurasi Satelit untuk Panggilan Balik Provisi


Sekarang pergi ke antarmuka web satelit, pergi ke layar Konfigurasi dan klik Grup Host. Kami memilih grup host yang ada, yang digunakan saat menginisialisasi host baru, dalam contoh kami, ini adalah RHEL 8.

Pada layar edit grup host, buka tab Parameter dan buat 4 parameter baru:

ansible_host_config_key - di sini kita masukkan Host Config Key dari Template Menara yang Mungkin.
ansible_job_template_id - di sini kita menulis ID Templat, yang sebelumnya kita temukan dari URL templat.
ansible_tower_fqdn adalah nama domain yang sepenuhnya memenuhi syarat dari server Ansible Tower.
ansible_tower_provisioning - set true.



Periksa bagaimana semuanya bekerja


Sekarang inisialisasi host baru dari Satelit dan verifikasi bahwa panggilan balik penyediaan berfungsi dan secara otomatis menjalankan skrip kami pada host itu.

Di antarmuka web Satelit, buka layar Hosts, klik Buat Host dan verifikasi bahwa grup yang baru saja kita buat 4 parameter baru digunakan, yaitu grup RHEL 8.



Setelah inisialisasi host selesai, kita perlu memastikan bahwa template di dalamnya telah berhasil diluncurkan. Untuk melakukannya, buka layar Templates di antarmuka web Ansible Tower, cari templat kami di daftar dan lihat apakah kuadrat paling kiri dari indikatornya berubah menjadi hijau:



Kami klik kotak hijau ini untuk melihat detail peluncuran, yang dalam kasus kami berhasil. Harap perhatikan bahwa tugas ini memiliki batas (Batas) - peluncuran hanya host baru yang dibuat selama inisialisasi. Yah, ini tidak mengherankan, karena mekanisme panggilan balik penyediaan hanya menjalankan templat pada host yang memintanya.



Sekarang mari kita pergi ke host yang baru dibuat dan memeriksa apakah cocok dengan apa yang tertulis dalam skrip:

[root@provision-test-rhel8 ~]# rpm -qa | grep tmux
tmux-2.7-1.el8.x86_64

[root@provision-test-rhel8 ~]# id brian
uid=10000(brian) gid=10000(brian) groups=10000(brian)

[root@provision-test-rhel8 ~]# cat /etc/motd
Authorized use only!

Penyelesaian masalah


Jika template Ansible Tower tidak dimulai secara otomatis pada host baru yang diinisialisasi melalui satelit, ada beberapa hal yang perlu diperiksa.

Langkah pertama adalah untuk mengetahui apakah Ansible Tower menerima permintaan untuk panggilan balik penyediaan, bagaimana skrip berjalan dan apakah itu dimulai sama sekali. Untuk melakukan ini, di antarmuka Tower, buka layar Templates dan lihat warna indikator di sebelah nama templat: hijau - peluncuran berhasil, merah - peluncuran gagal.



Jika kotak berwarna merah, maka kami mengkliknya dan mencari informasi tambahan untuk memahami mengapa peluncuran gagal (ini bisa merupakan kesalahan sintaksis dalam skrip dan masalah lainnya).

Jika kotak berwarna hijau, maka kami klik dan lihat pula, karena tugas tersebut dapat melaporkan eksekusi yang berhasil, tetapi sebenarnya tidak dimulai pada host kami. Misalnya, jika baris host dalam skrip menunjukkan host dan grup tertentu, tetapi tidak menyertakan host yang dibuat selama inisialisasi, maka tugas akan melaporkan keberhasilan, tetapi informasi tambahan akan mengatakan "melompati: tidak ada host yang cocok".

Jika kotak indikator tidak hijau atau merah, maka Anda harus mulai dengan memeriksa parameter grup host di Satelit. Pastikan URL server Ansible Tower, Host Config Key, dan template ID ditentukan dengan benar di sana.

Selanjutnya, buka host yang baru diinisialisasi dan periksa apakah ada file /etc/systemd/system/ansible-callback.service (pada sistem RHEL 7 atau 8) atau file /root/ansible_provisioning_call.sh (RHEL 6).

Jika file tidak ada, verifikasi bahwa parameter ansible_tower_provisioning disetel ke true untuk grup host ini, dan bahwa pola inisialisasi pada server satelit belum diubah.
Jika file /etc/systemd/system/ansible-callback.service ada di host, kemudian buka dan cari URL tempat permintaan panggilan balik penyediaan dikirimkan:

[root@provision-test-rhel8 ~]# cat /etc/systemd/system/ansible-callback.service
[Unit]
Description=Provisioning callback to Ansible Tower
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/curl -k -s --data "host_config_key=aa5ebe82-491c-4fbb-bd36-a6657549451e" https://tower.example.com/api/v2/job_templates/11/callback/
ExecStartPost=/usr/bin/systemctl disable ansible-callback

[Install]
WantedBy=multi-user.target

Anda dapat menjalankan curl dan secara manual menduplikasi perintah yang ditentukan dalam file ini untuk secara manual memulai panggilan balik penyediaan:

[root@provision-test-rhel8 ~]# /usr/bin/curl -k -s --data "host_config_key=aa5ebe82-491c-4fbb-bd36-a6657549451e" https://tower.example.com/api/v2/job_templates/11/callback/

Jika Kunci Konfigurasi Host tidak valid ditentukan, kami akan menerima pesan kesalahan berikut:

[root@provision-test-rhel8 ~]# /usr/bin/curl -k -s --data "host_config_key=wrong-key-here" https://tower.example.com/api/v2/job_templates/11/callback/

{"detail":"You do not have permission to perform this action."}

Jika ID Templat tidak ditentukan dengan benar (di sini - 43 bukannya 11), maka jawabannya adalah sebagai berikut:

[root@provision-test-rhel8 ~]# /usr/bin/curl -k -s --data "host_config_key=wrong-key-here" https://tower.example.com/api/v2/job_templates/43/callback/

{"detail":"Not found."}

Anda juga dapat menonaktifkan mode senyap (-s) dalam perintah curl sehingga menampilkan kesalahan yang terkait dengan penyelesaian nama host, seperti dalam contoh di bawah ini, di mana kami mengganti nama yang benar ansible.example.com dengan ansible-tower.example.com yang salah :

[root@provision-test-rhel8 ~]# /usr/bin/curl -k  --data "host_config_key=wrong-key-here" https://ansible-tower.example.com/api/v2/job_templates/11/callback/

curl: (6) Could not resolve host: ansible-tower.example.com

Selain itu, ketika mengetahui penyebab kesalahan, file /var/log/tower/tower.log pada server Ansible Tower mungkin berguna.
Misalnya, file ini mencatat penggunaan Kunci Konfigurasi Host yang tidak valid:

2019-11-19 23:19:17,371 WARNING  awx.api.generics status 403 received by user AnonymousUser attempting to access /api/v2/job_templates/11/callback/ from 192.168.0.138

Ini juga memperbaiki penggunaan ID Templat yang tidak valid:

2019-11-19 23:19:49,093 WARNING  awx.api.generics status 404 received by user AnonymousUser attempting to access /api/v2/job_templates/43/callback/ from 192.168.0.138

2019-11-19 23:19:49,095 WARNING  django.request Not Found: /api/v2/job_templates/43/callback/

Untuk meringkas


Integrasi Satellite dan Ansible Tower dapat sangat mengoptimalkan inisialisasi dan konfigurasi host baru, yang menghemat banyak waktu bagi administrator sistem, membantu mereka merespons lebih cepat terhadap kebutuhan organisasi.

Pada 24 Maret, mulai pukul 11: 00-12: 30 Red Hat akan mengadakan webinar "Apa yang Harus Anda Ketahui tentang Otomasi: Keterampilan Dasar Dasar"

Otomasi adalah topik yang semakin populer dan jumlah permintaan untuk transformasi digital. Kami akan memberi tahu Anda tentang pandangan kami tentang otomatisasi - bersama dengan Ansible dan Ansible Tower - dan ini akan menjadi informasi dasar yang akan membuka Anda pintu menuju dunia baru alat otomasi deklaratif yang berani.
Setelah webinar ini, Anda akan memahami entitas Ansible dasar, seperti buku pedoman, inventaris, modul. Bersama Anda, kami akan menguasai sintaks dasar YAML sehingga Anda dapat menulis skrip Anda sendiri. Ini juga akan mempertimbangkan meluncurkan skrip dan meningkatkan hak istimewa.

Sebagai hasilnya, Anda akan mendapatkan seperangkat keterampilan dasar yang akan memungkinkan Anda untuk berhasil mempelajari dokumentasi dan literatur lainnya tanpa perasaan terus-menerus bahwa Anda kehilangan sesuatu. Daftarkan dan datang!

All Articles