SSD Nodes Learn Hosting plans →
تعلیمی Matt Connorتحریر: Matt Connor · اپ ڈیٹ شدہ 2026-08-29

Ansible playbook یا role: کون سا کب استعمال کریں؟

Flat Ansible playbook کب کافی ہے اور role کے لیے directories کب بنائیں؟ role layout، ansible-galaxy init، role calls اور variable precedence کی عملی رہنمائی پڑھیں۔

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 30, 2026.

Ansible playbook اور role میں کیا فرق ہے

Ansible playbook وہ فائل ہے جسے آپ ansible-playbook کے ساتھ چلاتے ہیں۔ یہ hosts کے ایک گروپ کو ان کاموں سے مربوط کرتی ہے جو انہیں انجام دینے ہیں۔ Ansible role ایک مقررہ ساخت والی directory ہے، جس میں tasks، templates، handlers اور default variables شامل ہوتے ہیں، اور playbook اسے نام کے ذریعے call کرتی ہے۔ دونوں کے اندر task syntax یکساں ہوتا ہے، اس لیے سوال یہ نہیں کہ آپ کیا لکھ سکتے ہیں۔ سوال یہ ہے کہ آپ اسے دوبارہ کہاں استعمال کر سکتے ہیں۔

Flat playbook سے شروع کریں۔ ایک site.yml جس میں tasks: فہرست ہو، آپ کی پہلی automation کے لیے درست ساخت ہے، اور یہ توقع سے زیادہ عرصے تک موزوں رہتی ہے۔ جب tasks کے اسی block کو hosts کے دوسرے گروپ کے لیے بھی چلانا پڑے، یا فائل تقریباً 100 lines سے زیادہ بڑھ جائے اور scrolling کے ذریعے task تلاش کرنا مشکل ہو جائے، تو اسے role میں تبدیل کریں۔

اگر آپ نے ابھی تک playbook نہیں لکھی تو ایک single VPS کے خلاف پہلی playbook سے شروع کریں اور جب اس میں اضافہ ہونے لگے تو واپس آئیں۔

جب flat playbook درست انتخاب ہو

flat playbook اس وقت درست ہوتا ہے جب کام صرف ایک بار یا ایک ہی host پر کرنا ہو، یا اسے کوئی دوسرا شخص نہ پڑھے۔ کسی ایک application server کی provisioning کرنا یا maintenance window سے پہلے کسی box پر patch لگانا، ان میں سے کسی کام کے لیے directory tree بنانا ضروری نہیں۔ ایک role سات directories اور indirection کی ایک اضافی سطح شامل کرتا ہے۔ اگر اسے استعمال کرنے والا واحد caller ساتھ موجود playbook ہو، تو یہ indirection کوئی فائدہ نہیں دیتی اور جب بھی آپ کو اصل میں چلنے والی چیز پڑھنی ہو، ہر بار ایک اضافی جگہ پر جانا پڑتا ہے۔

flat playbook ایک خاص مرحلے پر درست انتخاب نہیں رہتا، اور اس مرحلے کو پہچاننا آسان ہے۔ آپ tasks کے ایک block کو دوسرے playbook میں copy کر دیتے ہیں۔ یہی copy اس کی علامت ہے۔ اس کے بعد ہر fix دو جگہ کرنا پڑتا ہے، اور ایک دن ایسا آئے گا جب fix صرف ایک جگہ کیا جائے گا۔

role directory میں اصل میں کیا شامل ہوتا ہے

roles/common/
  defaults/main.yml
  vars/main.yml
  tasks/main.yml
  handlers/main.yml
  templates/99-hardening.conf.j2
  files/
  meta/main.yml
  • tasks/main.yml بنیادی نقطۂ آغاز ہے۔ Ansible اس file کو اس وقت چلاتا ہے جب role کو call کیا جاتا ہے، اور باقی ہر directory اختیاری ہے۔
  • defaults/main.yml میں وہ variables ہوتے ہیں جنہیں caller سے override کرنے کی توقع کی جاتی ہے۔ Ansible میں اس source کی priority سب سے کم ہوتی ہے، اس لیے تقریباً کوئی بھی دوسرا source اس پر غالب آ جاتا ہے۔
  • vars/main.yml میں وہ variables ہوتے ہیں جنہیں caller سے override کرنے کی توقع نہیں کی جاتی۔ priority میں یہ inventory سے اوپر ہوتا ہے، جو ایک مضبوط فیصلہ ہے۔ اسے کم ہی استعمال کریں۔
  • handlers/main.yml میں notify سے trigger ہونے والے tasks ہوتے ہیں۔ handler play کے اختتام پر صرف ایک بار چلتا ہے، چاہے کتنے ہی tasks اسے notify کریں۔
  • files/ میں وہ files ہوتی ہیں جنہیں copy module جوں کا توں copy کرتا ہے، جبکہ templates/ میں وہ Jinja2 templates ہوتے ہیں جنہیں template module render کرتا ہے۔ role کے اندر دونوں کو صرف bare filename کے ذریعے reference کریں، path کے بغیر، کیونکہ Ansible پہلے role کی اپنی directories میں تلاش کرتا ہے۔
  • meta/main.yml role dependencies کا اعلان کرتا ہے اور وہ metadata فراہم کرتا ہے جسے Ansible Galaxy پڑھتا ہے۔

یہ layout محض style کی ترجیح نہیں ہے۔ Ansible انہی exact paths میں تلاش کرتا ہے، اس لیے roles/common/template/ (واحد) میں رکھا گیا template کبھی نہیں ملتا۔

ansible-galaxy init سے مشترکہ role بنائیں

mkdir -p ~/infra/roles
cd ~/infra
ansible-galaxy init --init-path roles common

یہ roles/common کے تحت مکمل skeleton بناتا ہے، جس میں وہ directories بھی شامل ہوتی ہیں جنہیں آپ استعمال نہیں کریں گے، اور main.yml کے ایسے stubs بھی شامل ہوتے ہیں جن میں صرف --- ہوتا ہے۔ جو چیزیں خالی رہ جائیں، انہیں حذف کر دیں۔ خالی vars/main.yml Ansible کے لیے بے ضرر ہوتا ہے، لیکن اس سے یہ واضح نہیں رہتا کہ role میں اصل اہمیت کن files کی ہے۔

اب وہ files مکمل کریں جو کام انجام دیتی ہیں۔ پہلے defaults مکمل کریں، کیونکہ یہی role کا public interface ہیں۔

# roles/common/defaults/main.yml
---
common_packages:
  - ufw
  - fail2ban
  - unattended-upgrades
common_admin_group: admins
common_permit_root_login: "no"
common_password_authentication: "no"

"no" اور "yes" کو quotes میں لکھیں۔ Ansible YAML کو PyYAML کے ذریعے parse کرتا ہے۔ PyYAML ایک سادہ no کو boolean false سمجھتا ہے، اس لیے rendered config line PermitRootLogin False بن جاتی ہے اور sshd اسے مسترد کر دیتا ہے۔ Quotes اس value کو string برقرار رکھتے ہیں۔

# roles/common/tasks/main.yml
---
- name: Install the base packages
  ansible.builtin.apt:
    name: "{{ common_packages }}"
    state: present
    update_cache: true
    cache_valid_time: 3600

- name: Create the admin group
  ansible.builtin.group:
    name: "{{ common_admin_group }}"
    state: present

- name: Install the sshd hardening drop-in
  ansible.builtin.template:
    src: 99-hardening.conf.j2
    dest: /etc/ssh/sshd_config.d/99-hardening.conf
    owner: root
    group: root
    mode: "0644"
    validate: /usr/sbin/sshd -t -f %s
  notify: Restart sshd
# roles/common/handlers/main.yml
---
- name: Restart sshd
  ansible.builtin.service:
    name: ssh
    state: restarted
# roles/common/templates/99-hardening.conf.j2
# Managed by Ansible. Local edits are overwritten on the next run.
PermitRootLogin {{ common_permit_root_login }}
PasswordAuthentication {{ common_password_authentication }}

Debian اور Ubuntu میں systemd unit کا نام ssh ہے، جبکہ RHEL family systems میں یہ sshd ہے۔ جس handler میں غلط unit کا نام ہو، وہ صرف اس وقت fail ہوتا ہے جب کوئی چیز template میں واقعی تبدیلی کرے۔ اسی لیے مسئلہ عموماً کئی ہفتوں بعد ظاہر ہوتا ہے۔

اس task میں validate line سب سے زیادہ مفید ہے۔ Ansible template کو temporary file میں render کرتا ہے، %s کی جگہ اس file کا path رکھتا ہے، اور command چلاتا ہے۔ Destination file صرف اسی وقت replace ہوتی ہے جب command کا exit status 0 ہو۔ Template میں کوئی غلط directive شامل کر کے دوبارہ چلائیں۔ Task failed to validate کے ساتھ fail ہو جائے گا، اصل /etc/ssh/sshd_config.d/99-hardening.conf برقرار رہے گا، اور آپ کے پاس اب بھی ایسا server موجود ہوگا جس میں login کیا جا سکتا ہے۔ یاد رکھیں کہ یہ check صرف syntax نہیں جانچتا۔ اگر sshd -t host keys کو read نہ کر سکے تو یہ sshd: no hostkeys available -- exiting. کے ساتھ exit کرے گا، اور Ansible وہی failed to validate report کرے گا۔ اس لیے template کو موردِ الزام ٹھہرانے سے پہلے module کی msg پڑھیں۔

پلے بک رول کو کیسے کال کرتی ہے

# site.yml
---
- name: Base configuration for every server
  hosts: all
  become: true
  roles:
    - common
# inventory.ini
[local]
localhost ansible_connection=local
ansible-playbook -i inventory.ini site.yml

Recap میں play کا اختتام failed=0 پر ہونا چاہیے۔ کال کی جگہ expanded form کے ذریعے parameters دیں۔ اسی طرح ایک ہی role کو hosts کے دو گروپس کے لیے استعمال کیا جا سکتا ہے:

  roles:
    - role: common
      common_admin_group: ops
      common_permit_root_login: prohibit-password

یہاں ordering کا ایک اصول ہے جو تقریباً سب کو حیران کرتا ہے۔ ایک play میں pre_tasks، roles، tasks اور post_tasks شامل ہو سکتے ہیں، اور Ansible انہیں اسی ترتیب سے چلاتا ہے، چاہے آپ نے انہیں فائل میں کسی بھی ترتیب سے لکھا ہو۔ tasks: کو roles: سے پہلے رکھیں، پھر بھی roles پہلے چلیں گے۔ اس لیے اگر کسی کام کو role سے پہلے ہونا ضروری ہو تو اسے pre_tasks: میں رکھیں، tasks: کے شروع میں نہیں۔

- name: Ordering demonstration
  hosts: local
  gather_facts: false
  pre_tasks:
    - name: Runs first
      ansible.builtin.debug:
        msg: pre
  roles:
    - common
  tasks:
    - name: Runs after the role
      ansible.builtin.debug:
        msg: task
  post_tasks:
    - name: Runs last
      ansible.builtin.debug:
        msg: post

roles: key کے بجائے task list کے اندر سے role کال کرنے کے لیے import_role یا include_role استعمال کریں۔

  tasks:
    - name: Static, read when the playbook is parsed
      ansible.builtin.import_role:
        name: common

    - name: Dynamic, resolved when the task runs
      ansible.builtin.include_role:
        name: postgres
      when: "'db' in group_names"

import_role static ہے۔ Ansible parse time پر role پڑھتا ہے اور اس کے tasks play کا حصہ بن جاتے ہیں۔ اسی لیے ansible-playbook --list-tasks site.yml انہیں فہرست میں دکھاتا ہے، اور import پر موجود tag اندر کے ہر task پر لاگو ہوتا ہے۔ include_role dynamic ہے۔ جب تک task run نہ ہو، کچھ بھی نہیں پڑھا جاتا۔ اسی وجہ سے role name کو variable یا loop سے متعین کیا جا سکتا ہے۔ اس کا نقصان یہ ہے کہ یہ tasks --list-tasks اور --start-at-task میں نظر نہیں آتے۔

یہاں ایک اہم trap ہے۔ include_role task پر موجود when: کا جائزہ شامل کیے گئے role کا defaults/main.yml scope میں آنے سے پہلے لیا جاتا ہے۔ Include پر when: common_packages | length > 0 لکھیں تو run 'common_packages' is undefined کے ساتھ رک جاتا ہے، حالانکہ یہ variable اسی role میں defined ہے جسے آپ شامل کر رہے ہیں۔ حل یہ ہے کہ toggle کو role سے باہر منتقل کریں: اسے group_vars/all.yml میں رکھیں، جہاں یہ ہر جگہ scope میں ہو، اور role کے defaults کو ان values کے لیے رہنے دیں جنہیں role خود استعمال کرتا ہے۔

کون سا variable غالب آتا ہے: defaults، group_vars، vars، یا extra vars

Ansible variable precedence کی 20 سے زیادہ سطحوں کی دستاویز فراہم کرتا ہے۔ ان میں سے 4 تقریباً ہر حقیقی اختلاف کا فیصلہ کر دیتی ہیں۔ ذیل میں انہیں کمزور سے مضبوط ترتیب میں دیا گیا ہے۔

  • roles/<name>/defaults/main.yml نچلی سطح کے قریب ہوتا ہے۔ آپ کسی بھی دوسری جگہ جو قدر مقرر کریں گے، تقریباً ہمیشہ اسے override کر دے گی۔ اسی لیے role کے قابلِ تبدیلی اختیارات رکھنے کے لیے یہ مناسب جگہ ہے۔
  • group_vars/ اور host_vars/ درمیانی سطح پر ہوتے ہیں۔ آپ کی site کی اپنی قدریں یہاں ہونی چاہییں، اور یہ role defaults کو واضح طور پر override کرتی ہیں۔
  • roles/<name>/vars/main.yml، host_vars سے بلند سطح پر ہوتا ہے۔ یہاں رکھی گئی قدر inventory سے override نہیں کی جا سکتی۔ اسے ان اقدار کے لیے مخصوص رکھیں جنہیں role کے اندر باہمی مطابقت برقرار رکھنا ضروری ہو، مثلاً ایسا package name جو service name سے مطابقت رکھتا ہو۔
  • call site پر دیا گیا role parameter، vars/main.yml سے غالب آتا ہے، جبکہ command line پر دیا گیا -e ہر چیز پر غالب آتا ہے، بشمول role parameters کے۔

آپ تقریباً 1 منٹ میں اس precedence کو عملی طور پر دیکھ سکتے ہیں۔ ایک چھوٹے role میں 1 default اور 1 role var دیں، پھر host_vars میں یہی names مقرر کریں۔

# roles/prec/defaults/main.yml
---
prec_tunable: from-defaults
prec_internal: from-defaults
# roles/prec/vars/main.yml
---
prec_internal: from-rolevars
# host_vars/localhost.yml
---
prec_tunable: from-hostvars
prec_internal: from-hostvars
# roles/prec/tasks/main.yml
---
- name: Show which value survived
  ansible.builtin.debug:
    msg: "tunable={{ prec_tunable }} internal={{ prec_internal }}"
ansible-playbook -i inventory.ini prec.yml
ansible-playbook -i inventory.ini prec.yml -e prec_internal=from-cli

پہلی run tunable=from-hostvars internal=from-rolevars دکھاتی ہے۔ Inventory نے role default کو override کیا، لیکن role var سے مغلوب ہو گئی۔ دوسری run internal=from-cli دکھاتی ہے، کیونکہ extra vars سب سے بلند سطح پر ہوتے ہیں اور ان کے نیچے کوئی چیز انہیں override نہیں کر سکتی۔ اسی وجہ سے -e ایک مرتبہ کی run کے لیے مناسب ہے، لیکن ایسے script میں غلط ہے جسے آپ برقرار رکھتے ہیں: یہ آپ کی repository میں کیے گئے ہر فیصلے پر خاموشی سے فوقیت حاصل کر لیتا ہے۔

عملی اصول یہ ہے: اگر آپ چاہتے ہیں کہ کسی قدر کو مقرر کیا جا سکے، تو اسے defaults/ میں رکھیں۔ اسے vars/ میں رکھنے کا مطلب ہے کہ role کے ہر آئندہ صارف کو بتایا جا رہا ہے کہ inventory اسے تبدیل نہیں کر سکتی۔ کبھی کبھار یہی آپ کی مراد ہوتی ہے، لیکن عموماً یہ غیر ارادی ہوتا ہے۔

کردار کو idempotent ثابت کریں: اسے دو بار چلائیں

قابلِ اعتماد Ansible run دوسری بار وہی نتیجہ پیدا کرتا ہے اور رپورٹ کرتا ہے کہ کچھ بھی تبدیل نہیں ہوا۔ playbook کو دو بار چلائیں اور recap پڑھیں۔

ansible-playbook -i inventory.ini site.yml
ansible-playbook -i inventory.ini site.yml

دوسری recap کچھ اس طرح ہونی چاہیے:

PLAY RECAP *********************************************************************
localhost   : ok=4  changed=0  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0

changed=0 کا مطلب ہے کہ ہر module نے موجودہ state کا جائزہ لیا اور پایا کہ مطلوبہ کام پہلے ہی مکمل ہے۔ دوسری run میں changed=2 کا مطلب ہے کہ دو tasks فرق محسوس نہیں کر سکتے، اس لیے وہ فائلیں دوبارہ لکھتے اور services کو ہمیشہ restart کرتے رہیں گے۔ عام طور پر وجہ command یا shell ہوتی ہے، کیونکہ Ansible کے پاس یہ جاننے کا کوئی طریقہ نہیں ہوتا کہ کسی من مانے command نے کیا کام کیا۔

# traps.yml
---
- name: Command modules do not know what they changed
  hosts: local
  gather_facts: false
  tasks:
    - name: This appends a line on every run
      ansible.builtin.shell: "echo run >> /tmp/grow.txt"

    - name: This appends a line only once
      ansible.builtin.shell: "echo run >> /tmp/guarded.txt"
      args:
        creates: /tmp/guarded.txt

اس playbook کو دو بار چلائیں، پھر wc -l /tmp/grow.txt /tmp/guarded.txt والی lines گنیں۔ /tmp/grow.txt میں دو lines اور /tmp/guarded.txt میں ایک line ہونی چاہیے۔ دوسری run میں guarded task بالکل execute نہیں ہوا، اور اس کے result میں skipped, since /tmp/guarded.txt exists کا message موجود ہے، کیونکہ creates module کو پہلے تلاش کرنے کے لیے ایک قابلِ مشاہدہ نتیجہ فراہم کرتا ہے۔ جب کسی command سے ایسا نتیجہ پیدا نہ ہو تو اس کا output register کریں اور changed_when کے ذریعے خود فیصلہ کریں۔

ansible-playbook --check --diff site.yml تبدیلیاں کیے بغیر ان کی پیش گوئی کرتا ہے، جبکہ --diff وہ exact lines دکھاتا ہے جنہیں template دوبارہ لکھے گا۔ Output پڑھتے وقت ایک بات ذہن میں رکھیں: shell اور command tasks check mode میں skip ہو جاتے ہیں، اس لیے بظاہر صاف plan میں بھی کام چھپا ہو سکتا ہے۔

اس recap میں ایک اور column بھی اسی احتیاط کا تقاضا کرتا ہے: جس host سے Ansible connect نہ کر سکا، اسے failed کے بجائے unreachable کے تحت شمار کیا جاتا ہے، اور اس کے tasks میں سے کوئی بھی run نہیں ہوا۔ اس لیے یہ role چند سے زیادہ machines پر چلانے سے پہلے پہلے سے طے کریں کہ کیا ایک unreachable host کو پوری run روک دینی چاہیے۔

Ansible یہ کیوں کہتا ہے کہ role نہیں ملی

Ansible پہلے playbook فائل کے ساتھ موجود roles/ directory میں تلاش کرتا ہے، پھر roles_path میں۔ تلاش playbook کی پیروی کرتی ہے، آپ کے shell کی نہیں۔

ERROR! the role 'common' was not found in /home/deploy/lonely/roles:/home/deploy/lonely

اس پیغام کا مطلب ہے کہ site.yml اور roles/ ایک دوسرے سے الگ ہو گئے ہیں، اور پیغام میں ان paths کو بھی دکھایا جاتا ہے جنہیں Ansible نے آزمایا۔ دونوں کو ایک ہی directory میں رکھیں۔ Parent directory سے run کرنا درست ہے، کیونکہ فیصلہ playbook path کی بنیاد پر ہوتا ہے:

ansible-playbook -i infra/inventory.ini infra/site.yml

اسی مسئلے کی ایک کم نمایاں صورت بھی ہے۔ اگر موجودہ directory world-writable ہو تو Ansible اس میں موجود ansible.cfg کو نظرانداز کر دیتا ہے، کیونکہ اس machine کا کوئی بھی user وہاں configuration رکھ کر آپ کے run کے نتائج تبدیل کر سکتا ہے۔

[WARNING]: Ansible is being run in a world writable directory (/tmp/infra), ignoring it as an ansible.cfg source.

اس صورت میں آپ کی roles_path اور inventory settings خاموشی سے غیر موجود سمجھی جاتی ہیں، اور role lookup ایسے سبب سے ناکام ہوتا ہے جس کا roles سے کوئی تعلق نہیں۔ ansible --version وہ config file دکھاتا ہے جسے Ansible نے حقیقت میں load کیا، جبکہ ansible-config dump --only-changed ہر وہ setting دکھاتا ہے جو built-in defaults سے مختلف ہو۔ جب run ایسا برتاؤ کرے جیسے آپ کی configuration موجود ہی نہیں، تو دونوں کی جانچ کریں۔

حصوں کا اشتراک: requirements.yml اور متعین ورژن

کسی دوسرے شخص کا لکھا ہوا role نقل نہیں کیا جاتا بلکہ install کیا جاتا ہے۔ اسے ایک بار declare کریں:

# requirements.yml
---
roles:
  - name: postgres
    src: https://github.com/example/ansible-role-postgres
    scm: git
    version: v1.4.0
ansible-galaxy install -r requirements.yml -p galaxy_roles

ہمیشہ version متعین کریں۔ اس کے بغیر command چلانے کے دن default branch میں موجود ورژن حاصل ہوتا ہے۔ اس لیے گزشتہ ماہ کامیاب deployment آپ کی اپنی repository میں کسی تبدیلی کے بغیر بھی ناکام ہو سکتی ہے۔ roles_path کو download directory کی طرف point کریں، اور اس directory کو git سے خارج رکھیں:

# ansible.cfg
[defaults]
inventory = inventory.ini
roles_path = ./galaxy_roles

Playbook کے ساتھ موجود roles/ میں موجود roles پھر بھی مل جاتے ہیں، کیونکہ اس path کو roles_path کے علاوہ ہمیشہ search کیا جاتا ہے۔ اس طرح آپ کے اپنے roles repository میں محفوظ اور review شدہ رہتے ہیں، جبکہ third-party roles tag کے ذریعے متعین reproducible downloads ہوتے ہیں۔

جہاں roles جواب نہیں رہتے

Role ایک ہی Ansible run کے اندر دوبارہ استعمال ہونے والی اکائی ہے۔ یہ آپ کے provider پر servers یا DNS records نہیں بناتا، اور اسے ایسا کرنے پر مجبور کرنے سے playbooks ایسی شکل اختیار کر لیتے ہیں جنہیں کوئی maintain نہیں کرنا چاہتا۔ شروع کرنے سے پہلے Ansible اور Terraform کے درمیان کام کی تقسیم پڑھ لینا مفید ہے۔ Role inventory design کا متبادل بھی نہیں ہے: جب machines کی تعداد چند سے بڑھ جائے تو ان servers کو group اور access کرنے کا طریقہ اس بات سے زیادہ اہم ہو جاتا ہے کہ tasks کو کس طرح file کیا گیا ہے۔

یہ common role جو hardening install کرتا ہے، اس کے لیے بھی الگ فیصلے درکار ہیں۔ اوپر دیا گیا drop-in صرف دو directives set کرتا ہے، اس سے زیادہ نہیں۔ اس لیے ہر host کے role میں شامل کی جانے والی settings طے کرنے سے پہلے کون سی SSH settings واقعی تبدیل کرنے کے قابل ہیں اور Ubuntu کو security updates خودکار طور پر apply کرنے کا طریقہ پڑھیں۔

FAQ

مجھے Ansible playbook کو role میں کب تبدیل کرنا چاہیے؟

جب tasks کے اسی block کو دوسری play میں، یا hosts کے دوسرے group کے خلاف چلانا ہو۔ playbooks کے درمیان tasks copy کرنا اس کی علامت ہے، کیونکہ اس کے بعد ہر اصلاح دو جگہ لاگو کرنی پڑتی ہے، اور کسی دن یہ صرف ایک جگہ لاگو ہوگی۔ تقریباً 100 lines سے کم ایک ایسا playbook جو ہمیشہ صرف ایک group کو target کرتا ہو، role سے کوئی فائدہ حاصل نہیں کرتا؛ اضافی directories اسے پڑھنا مشکل بنا دیتی ہیں۔

کیا اسی play میں موجود tasks سے پہلے roles چلتے ہیں؟

ہاں۔ Ansible پہلے pre_tasks چلاتا ہے، پھر roles: کے تحت درج تمام چیزیں، اس کے بعد tasks:، اور پھر post_tasks:۔ یہ آپ کی file میں ان keys کی ترتیب کو نظرانداز کرتا ہے۔ tasks: کو roles: سے اوپر لکھنے سے یہ tasks پہلے نہیں چلیں گے۔ اگر کوئی چیز role سے پہلے ہونی ضروری ہو تو اسے pre_tasks: میں رکھیں۔

میرے group_vars کی value role کو override کیوں نہیں کرتی؟

دیکھیں کہ variable role کے vars/main.yml میں set ہے یا defaults/main.yml میں۔ Ansible کی precedence order میں vars/، group_vars اور host_vars سے اوپر ہوتا ہے، اس لیے inventory اسے override نہیں کر سکتی۔ Variable کو defaults/main.yml میں منتقل کریں۔ یہ precedence order کے نچلے حصے کے قریب ہے اور ایسی ہر value کے لیے درست جگہ ہے جسے caller تبدیل کر سکے۔ یہ تصدیق کرنے کے لیے کہ وجہ precedence ہے، typo نہیں، ایک بار -e name=value کے ساتھ چلائیں۔ اس کی precedence ہر دوسرے source سے زیادہ ہے۔

Ansible یہ کیوں کہتا ہے کہ role نہیں ملا؟

Search playbook file کے ساتھ والی directory سے شروع ہوتی ہے، اس لیے site.yml اور roles/ ایک ہی directory میں ہونے چاہییں۔ Error ان paths کو دکھاتا ہے جنہیں اس نے آزمایا، جیسا کہ the role 'common' was not found in /home/deploy/lonely/roles:/home/deploy/lonely میں ہے۔ Parent directory سے playbook چلانا درست ہے، کیونکہ search playbook path کی پیروی کرتی ہے، shell کی working directory کی نہیں۔ اگر آپ ansible.cfg سے roles_path پر انحصار کرتے ہیں تو ansible --version کے ساتھ تصدیق کریں کہ وہ file load ہوئی ہے، کیونکہ world-writable working directory کی صورت میں Ansible اسے ignore کر دیتا ہے۔

کیا role بنانے کے لیے ansible-galaxy init ضروری ہے؟

نہیں۔ Role صرف متوقع ناموں والی directories پر مشتمل ہوتا ہے، اس لیے mkdir -p roles/common/tasks اور tasks/main.yml پہلے ہی ایک working role فراہم کرتے ہیں۔ ansible-galaxy init --init-path roles common typing کم کرتا ہے اور مکمل skeleton فراہم کرتا ہے، جس میں meta/main.yml اور README stub بھی شامل ہیں۔ جن directories کو خالی چھوڑیں انہیں delete کر دیں، کیونکہ خالی vars/main.yml یہ سمجھنا مشکل بنا دیتا ہے کہ role میں واقعی کون سی files کام کرتی ہیں۔

#ansible#roles#playbook#structure#automation