Sunday, 1 November 2026

Ansible automation &Azure Devops

  • Using VS Code with Azure DevOps Git Repos
  • Azure DevOps Git Workflow Using VS Code | Step‑by‑Step from Scratch
  • PRAKRITI AMLI 16 9 4cr
  • What is the primary purpose of the lineinfile module, and how does it differ from replace or blockinfile?
    • ansible.builtin.lineinfile is used to manage a single line in a text file. It ensures a specific line is present, absent, or modified based on regular expressions.
    • blockinfile manages a multi-line block of text surrounded by customizable marker lines.
    • replace uses regular expressions to modify all occurrences of a pattern within a file, whereas lineinfile typically manages a single targeted line.
  • Explain the difference between regexp and search_string.
    • regexp uses a Python regular expression to scan the file. If a match is found, that line is replaced by the line parameter.
    • search_string performs a literal, exact match lookup without regex parsing. It is much faster and safer when you do not need pattern matching and want to avoid escaping special regex characters.

Advanced Scenarios & Parameters
  • How does the backrefs parameter change the behavior of lineinfile?
    • By default (backrefs=no), if the regexp matches, the entire line is replaced by your line string. If the regex does not match, the line is appended to the end of the file.
    • When backrefs=yes, the line parameter can use regex backreferences (e.g., \1, \2) to keep parts of the matched line. Crucially, if the regexp does not match, the file remains completely unchanged (the line is not appended).
  • What is the role of the validate parameter, and why is it critical in production?
    • It prevents broken configuration files from taking down services. Before saving the file, Ansible copies it to a temporary location and runs the validation command specified (e.g., validate: '/usr/sbin/visudo -cf %s'). If the command fails (returns a non-zero exit code), the playbook fails, and the original file is left untouched.
  • How do insertafter and insertbefore behave if the regexp matches versus when it doesn't?
    • If regexp matches: The insertafter / insertbefore parameters are completely ignored. The matched line is replaced in place.
    • If regexp does not match: The new line is inserted relative to the insertbefore or insertafter expression. If those are also missing, it defaults to the end of the file.

Comparison Matrix
Scenarioregexp Match Found?Resulting Behavior
backrefs: no (Default)YesLine replaced in place
backrefs: no (Default)NoNew line appended to the end of the file
backrefs: yesYesLine replaced in place (supports \1 groups)
backrefs: yesNoFile is not changed at all

Best Practices & Pitfalls
  • What is a common pitfall when using lineinfile to modify multiple parameters in the same file?
    • Running multiple lineinfile tasks sequentially against the same file can cause unexpected results if your regex expressions are too vague. One task might inadvertently match and overwrite a line created by a previous task. For managing entire configuration states, templates (ansible.builtin.template) are preferred over multiple lineinfile statements.
  • How do you ensure a line is completely removed from a file?
    • Set the state parameter to absent and provide the regexp targeting the line you want gone.


Q: Interpretation failed_when: fail_lc.rc!=0 and fail_lc.rc!=1 i
failed_when: fail_lc.rc != 0 and fail_lc.rc != 1 is an Ansible task condition used to control when a task should be marked as a failed status.
In plain English, it means: "Fail this task only if the return code (rc) is neither 0 nor 1." If the return code is exactly 0 or exactly 1, Ansible will treat the task as successful and continue execution.
Here is a breakdown of how this is used in Ansible interviews:

Core Concept & Breakdown
In standard shell and Linux execution, a return code of 0 means success, and any non-zero code (like 1, 2, 255) means an error. Ansible automatically fails a task if rc is not 0.
However, some CLI tools use a return code of 1 or other numbers to indicate a non-error state (e.g., grep returns 1 if no lines match; some configuration check tools return 1 if changes are found but no error occurred).
  • fail_lc: This is the variable holding the registered output of a previous task (usually a shell or command module task).
  • fail_lc.rc: This extracts the return code integer from that registered output.
  • != 0 and != 1: This creates a specific condition. If rc is 2, both conditions are true (2 != 0 AND 2 != 1), so the task fails. If rc is 1, the second condition is false, so the overall failed_when evaluates to false, and the task succeeds.

Q: How do you handle a command in Ansible that returns a non-zero exit code but shouldn't trigger a task failure?
A: You can override Ansible's default failure behavior using the failed_when conditional modifier. By registering the output of the task into a variable, you can inspect its return code (rc) and define exactly which numbers constitute a true failure.
For example, if a command legally returns either 0 or 1, you can write:
yaml
- name: Run custom check script
  ansible.builtin.shell: /opt/scripts/check_status.sh
  register: fail_lc
  failed_when: fail_lc.rc != 0 and fail_lc.rc != 1
Q: Can you write failed_when: fail_lc.rc != 0 and fail_lc.rc != 1 using an alternative Jinja2 syntax?
A: Yes. You can use the not in operator to check against a list of acceptable return codes, which is often cleaner and easier to read:
yaml
failed_when: fail_lc.rc not in [0, 1]
Q: What is the difference between using failed_when like this versus ignore_errors: true?
  • ignore_errors: true: The task still formally fails in the Ansible output (turns red), but the playbook execution simply bypasses it and continues to the next task. Downstream handlers will not run unless specified.
  • failed_when: This changes the evaluation logic itself. If the condition isn't met, the task status is marked as successful (turns yellow or green), meaning Ansible genuinely does not register it as a failure.


What is EMCLI?
EMCLI stands for Enterprise Manager Command Line Interface. It is a command-line tool provided by Oracle for Oracle Enterprise Manager (OEM). It allows administrators to automate tasks, run scripts, and manage targets without using the OEM web-based graphical user interface.

Top EMCLI Interview Questions and Answers
1. Where is EMCLI located on the OMS server?
  • Answer: EMCLI is pre-installed on the Oracle Management Server (OMS) and is located in the $OMS_HOME/bin directory.
2. What are the three operating modes of EMCLI?
  • Answer: EMCLI operates in three main modes:
    • Standard Mode: Running single EMCLI commands (verbs) directly from the shell or command prompt.
    • Interactive Mode: Starting an interactive shell session where you connect to the OMS and run multiple commands sequentially.
    • Scripting Mode: Running scripts (typically using Python or Jython) that contain series of EMCLI verbs to automate complex administrative workflows.
3. How do you log in to the OMS using EMCLI?
  • Answer: You can log in using the emcli login command:
    bash
    $OMS_HOME/bin/emcli -login -username=SYSMAN
    
    The system will prompt you for the password securely. Alternatively, you can pass the password inline (though less secure due to shell history):
    bash
    $OMS_HOME/bin/emcli -login -username=SYSMAN -password=YOUR_PASSWORD
    
    4. What is the purpose of emcli sync?
  • Answer: The emcli sync command synchronizes EMCLI client definitions, verbs, and metadata with the active OMS. You should run this after patching, upgrading, or adding new custom verbs to OMS.
5. How do you check the help documentation or syntax for a specific EMCLI verb?
  • Answer: You can use the emcli help command:
    • For a general summary: $OMS_HOME/bin/emcli help
    • For a specific verb (e.g., get_targets): $OMS_HOME/bin/emcli help get_targets
6. What scripting language is used when writing EMCLI scripts?
  • Answer: EMCLI uses Python (specifically running on a Jython interpreter) for its scripting and interactive modes.
7. How do you log out of the OMS session in EMCLI?
  • Answer: You terminate the session using the logout command:
    bash
    $OMS_HOME/bin/emcli -logout
    
    8. Can EMCLI be installed on a machine other than the OMS host?
  • Answer: Yes. You can set up and configure an EMCLI client on a remote machine by downloading or configuring the client software to communicate with the central OMS over HTTPS.

What is ansible.builtin.set_fact?
The ansible.builtin.set_fact module is used to define or modify variables on a host-by-host basis dynamically during runtime (on the fly) rather than statically beforehand in inventory files or vars: blocks. 
  • Scope: Variables created with set_fact are available to subsequent tasks and plays for that specific host during the same playbook run. 
  • Persistence (Optional): Setting cacheable: yes can persist the fact into an external fact cache if enabled in your configuration. 

Understanding emctl_home in this Context
emctl_home is a custom or application-specific variable name (often pointing to an Oracle Enterprise Manager emctl binary directory, e.g., /u01/app/oracle/product/mw/oms/bin) assigned via set_fact.
Example Playbook Task:
yaml
- name: Set EMCTL Home path dynamically
  ansible.builtin.set_fact:
    emctl_home: "/u01/app/oracle/product/mw/oms/bin"
  when: ansible_os_family == "RedHat"
Common Interview Questions & Answers
Q1: What is the difference between ansible.builtin.set_fact and regular variables (vars / include_vars)?
  • set_fact: Values are evaluated and assigned dynamically at runtime (often derived from task output via register, conditional logic, or facts). High host-level variable precedence. 
  • vars / include_vars: Values are static and known beforehand before the play execution begins. Lower precedence than set_fact. 
Q2: How do you make a variable created by set_fact persist across multiple playbook runs?
  • You add the cacheable: true parameter inside the set_fact task:
    yaml
    - ansible.builtin.set_fact:
        emctl_home: "/u01/app/oracle/product/mw/oms/bin"
        cacheable: true
    

  • Note: Fact caching must be enabled in ansible.cfg (using redis, jsonfile, etc.) for this to work across separate runs. 
Q3: Where does a set_fact variable sit in Ansible's variable precedence order?
  • Standard set_fact variables have a very high precedence (overriding inventory vars, group vars, and role defaults, though lower than extra-vars passed via -e).
  • If cacheable: true is used, it changes behavior to act more like a gathered fact, shifting its precedence lower in subsequent runs


Q1: What is the purpose of the ansible.builtin.fail module?
Answer: The ansible.builtin.fail module is used to intentionally abort the execution of a playbook for the current host. It is almost always paired with a when conditional statement to enforce preconditions, validate user inputs, or catch dangerous system states before subsequent tasks cause catastrophic failures or corrupt infrastructure. 
  • Syntax Example:
    yaml
    - name: Ensure target OS is supported
      ansible.builtin.fail:
        msg: "This deployment playbook only supports Ubuntu systems."
      when: ansible_facts['os_family'] != "Debian"
    
    Q2: What is the difference between ansible.builtin.fail and failed_when?
Answer: While both mechanisms mark a play or task as failed, they are used in entirely different contexts:
Attribute / Featureansible.builtin.fail Modulefailed_when Task Directive
TypeAn independent task/module.A task-level modifier or attribute.
Primary Use CaseDedicated guard clauses, input validations, or environment checks.Overriding the default failure evaluation criteria of an existing task.
Trigger MechanismTriggers immediately when its when conditional evaluates to true.Evaluates after the task finishes execution by analyzing a registered variable.
Output FocusCustom human-readable text specified by the msg parameter.Inspecting stdout or exit codes of an executed shell/command module.
Q3: How do ansible.builtin.fail and ansible.builtin.meta: end_play or end_host differ?
Answer: The core difference lies in the failure state of the playbook execution:
  • ansible.builtin.fail: Aborts the execution for the host and explicitly marks the task state as FAILED. This will trigger any rescue blocks or cause the overall playbook run to return a non-zero exit status. 
  • ansible.builtin.meta: end_host / end_play: Gracefully stops execution for a specific host or the entire play without throwing an error. The run is treated as a success (non-failure status). 

Scenario-Based Interview Questions
Scenario 1: Input & Variable Validation
"How would you use the fail module to ensure a junior engineer doesn't run a deployment playbook without specifying a target environment variable (e.g., dev, staging, prod)?"
Answer: You can place an input validation check at the very beginning of the playbook tasks using ansible.builtin.fail and a when condition checking if the variable is defined and matches allowed choices. 
yaml
- name: Validate that environment variable is explicitly provided
  ansible.builtin.fail:
    msg: "Variable 'target_env' is missing or invalid. Pass it via '-e target_env=dev|staging|prod'"
  when: target_env is not defined or target_env not in ['dev', 'staging', 'production']
Scenario 2: Integration with Block and Rescue
"Can you explain how the fail module interacts with block and rescue structures?"
Answer: If the ansible.builtin.fail module is invoked inside a block, it immediately halts the remaining tasks within that block and diverts execution to the rescue section. The rescue block allows you to execute compensating actions—such as a rollback script—to safely handle the intentional failure. 
yaml
- block:
    - name: Run health check script
      ansible.builtin.command: /opt/check_health.sh
      register: health_result

    - name: Force failure if critical check fails
      ansible.builtin.fail:
        msg: "System health check failed. Aborting deployment."
      when: "'CRITICAL' in health_result.stdout"

  rescue:
    - name: Execute rollback operations
      ansible.builtin.command: /opt/rollback.sh
Top Tips for the Interview
  • Blast Radius Avoidance: Emphasize that you use fail to reduce the blast radius of a bad deployment. Interviewers look for candidates who write robust, defensive playbooks rather than hoping tasks succeed. 
  • Use FQCN: Always name it as ansible.builtin.fail instead of the short-form fail to demonstrate adherence to modern Ansible collection standards. 
If you would like, let me know:
  • The seniority level of the interview you are preparing for (e.g., Associate, Senior DevOps, or Systems Architect).
  • If you need specific examples combining fail with complex Jinja2 filters or regex validations. 
  • Whether you want to explore any_errors_fatal behaviors when the fail module triggers. 

Q: What is a block in Ansible, and what happens when you add a when condition to it?
  • Answer:
    • A block groups multiple tasks together so you can apply shared directives (like when, ignore_errors, or error handling with rescue/always) to all of them at once.
    • When you add a when condition to a block, Ansible evaluates that condition for the block. 
Q: How does when behavior on a block differ from applying when on individual tasks?
  • Answer:
    • Dry-up code: Instead of repeating when: ansible_os_family == 'RedHat' on 5 different tasks, you write it once on the block.
    • Evaluation nuance: A when condition on a block is evaluated for each task inside the block, not just once at the entry point of the block. If a task inside the block changes a variable that the when condition depends on, later tasks in the same block re-evaluate the condition. 

Example Playbook Usage
yaml
- name: Deploy application stack conditionally
  block:
    - name: Install Nginx on Debian
      ansible.builtin.apt:
        name: nginx
        state: present

    - name: Copy custom configuration
      ansible.builtin.copy:
        src: nginx.conf
        dest: /etc/nginx/nginx.conf
  when: ansible_os_family == 'Debian'
  rescue:
    - name: Handle installation or config failure
      ansible.builtin.debug:
        msg: "Failed to deploy Nginx on Debian host."
Common Follow-up Questions Interviewers Ask
  1. Can you combine block with rescue and always?
    Yes. block acts like a try block, rescue runs if any task in the block fails (like catch), and always runs regardless of whether the block succeeded or failed (like finally).
     
  2. What happens if a variable used in a block's when statement gets modified midway through the block?
    Because Ansible re-evaluates when conditions per task, changing the variable mid-block can cause subsequent tasks inside the same block to be skipped.
     


Question :  explanation and interpretation  of ansible.builtin.set_fact: timestamp : {{ lookup ('pipe','date +%Y%m%d')}} 
Direct Answer
The Ansible expression ansible.builtin.set_fact: timestamp: {{ lookup('pipe','date +%Y%m%d') }} executes the shell command date +%Y%m%d on the Ansible control node (not the target managed node), captures the resulting date output (e.g., 20261104), and stores it as a host fact named timestamp available for the rest of the playbook run

Detailed Breakdown & Component Interpretation
  • ansible.builtin.set_fact:
    • An Ansible module used to dynamically create or override host variables (facts) during execution. Facts created this way remain in memory for the duration of the playbook run and can be referenced in later tasks, templates, or conditionals. 
  • timestamp:
    • The custom variable name being assigned the evaluated value. You can reference it later anywhere in the playbook using Jinja2 syntax: {{ timestamp }}. 
  • lookup('pipe', ...):
    • The pipe lookup plugin tells Ansible to execute an external command via a shell pipe and return the standard output (stdout) directly into the Jinja2 expression.
    • Crucially: Pipe lookups always execute on the Ansible control node, never on the remote/target managed nodes. 
  • date +%Y%m%d:
    • A standard Linux/Unix shell command.
    • +%Y%m%d is the formatting argument where %Y is the 4-digit year, %m is the 2-digit month, and %d is the 2-digit day.
    • On November 4, 2026, this outputs the string 20261104. 

Execution Flow Step-by-Step
  1. Evaluation: When Ansible reaches this task, the Jinja2 template engine evaluates {{ lookup('pipe','date +%Y%m%d') }}.
  2. Shell Execution: The control node runs the bash/sh command date +%Y%m%d.
  3. Capture: The stdout (20261104) is piped back into Ansible. 
  4. Fact Assignment: The set_fact module assigns timestamp: 20261104 to the host's runtime variables. 
  5. Usage: In subsequent tasks (such as appending a date tag to a backup file, log directory, or cloud resource name), calling {{ timestamp }} resolves to 20261104. 

Alternative Approaches & Best Practices
  • Why use pipe instead of ansible_date_time?
    • Built-in facts like ansible_date_time are captured once when gather_facts runs at the very beginning of a playbook. If your playbook runs for a long time or spans across midnight, ansible_date_time stays stale, whereas lookup('pipe', ...) fetches the live time at the exact moment the task executes. [
  • Modern Alternative:
    • In newer Ansible versions, you can also use Jinja2 native time functions like ansible.builtin.set_fact: timestamp="{{ lookup('pipe', 'date +%Y%m%d') }}" or the Jinja now() filter ({{ now().strftime('%Y%m%d') }}) which avoids spawning an external shell process. 

Question: What are Ansible Tags, why do we use them, and how do you implement them in a playbook?
Expert Answer:
  • Definition: Ansible tags are labels or markers assigned to tasks, plays, or roles inside a playbook. They allow an operator to execute or skip specific portions of a playbook instead of running the entire workflow from top to bottom.
  • Core Use Case: They are heavily used in large-scale CI/CD pipelines, long-running configuration jobs, or debugging scenarios where you only want to rerun a quick fix (e.g., updating a single configuration file or restarting a specific service) rather than re-provisioning an entire server stack.

Practical Example
Here is a playbook with tags applied to individual tasks:
yaml
---
- name: Configure Web Server and Application
  hosts: webservers
  become: yes
  tasks:
    - name: Install Nginx web server
      ansible.builtin.apt:
        name: nginx
        state: present
      tags:
        - install
        - nginx

    - name: Copy custom configuration file
      ansible.builtin.copy:
        src: files/nginx.conf
        dest: /etc/nginx/nginx.conf
      tags:
        - configuration

    - name: Restart Nginx service
      ansible.builtin.service:
        name: nginx
        state: restarted
      tags:
        - configuration
        - service
How to Execute Using Tags from the Command Line:
  1. Run only tasks with a specific tag (e.g., run only configuration tasks):
    bash
    ansible-playbook -i inventory.ini site.yml --tags "configuration"
    

  2. Run tasks with multiple tags:
    bash
    ansible-playbook -i inventory.ini site.yml --tags "install,service"
    

  3. Skip specific tasks using tags (e.g., skip the installation step):
    bash
    ansible-playbook -i inventory.ini site.yml --skip-tags "install"
    
Pro-Tips for the Interviewer
  • Special Tags: Mention special built-in tags like always (runs the task regardless of what tags are called, unless explicitly skipped with --skip-tags) and never (task won't run unless explicitly called with --tags).
  • Dry Run Integration: You can combine --tags with the check mode flag (--check or -B) to preview specific task changes safely.
Q1: What is a dictionary variable in Ansible, and how is it different from a list?
  • Answer:
    • A dictionary stores data using key-value pairs (e.g., user: {name: "Alice", role: "admin"}). You reference values by their key name.
    • A list (or array) stores an ordered collection of single items indexed by numbers starting from 0 (e.g., users: ["Alice", "Bob"]). 
Q2: What are the two ways to access values inside an Ansible dictionary?
  • Answer: You can access dictionary items using either dot notation or bracket notation:
    • Dot notation: {{ user.name }}
    • Bracket notation: {{ user['name'] }} 

Detailed Example Playbook
This example defines a dictionary variable named web_server, accesses specific keys using both dot and bracket notations, and loops through the dictionary key-value pairs. 
yaml
---
- name: Dictionary Variable Example Playbook
  hosts: localhost
  gather_facts: false

  vars:
    # Defining a dictionary variable
    web_server:
      host: "web01.example.com"
      port: 8080
      environment: "production"
      ssl_enabled: true

  tasks:
    - name: Access using Dot Notation
      ansible.builtin.debug:
        msg: "Connecting to host {{ web_server.host }} on port {{ web_server.port }}"

    - name: Access using Bracket Notation
      ansible.builtin.debug:
        msg: "The server is running in {{ web_server['environment'] }}"

    - name: Iterate over dictionary key-value pairs
      ansible.builtin.debug:
        msg: "Key: {{ item.key }} -> Value: {{ item.value }}"
      loop: "{{ web_server | dict2items }}"
Key Takeaways for Interviews
  • Nesting: Dictionaries can be nested inside other dictionaries or lists for complex infrastructure data (e.g., {{ application.frontend.port }}). 
  • Filter dict2items: When you need to iterate through a dictionary in a standard Ansible loop, you typically convert it to a list of key-value structures using the dict2items filter.


What is a loop in Ansible?
A loop allows a single task to run multiple times with different values or items. Instead of writing the same task over and over for different files, users, or packages, you pass a list or dictionary to the loop keyword. 
yaml
- name: Install required packages
  ansible.builtin.apt:
    name: "{{ item }}"
    state: present
  loop:
    - git
    - vim
    - htop
What is loop_control in Ansible?
loop_control is a set of options used to modify or control how a loop behaves. By default, loops use the variable name item to represent the current value, and Ansible prints the raw value of item in the terminal output. loop_control lets you customize these behaviors. 

Common Interview Questions & Answers
Q1: What is the purpose of loop in Ansible, and how does it differ from older directives?
  • Answer: The loop keyword is the modern, standardized way to iterate over a list in Ansible playbooks. Older constructs like with_items, with_dict, or with_file still work for backward compatibility, but loop provides cleaner syntax, better performance with Jinja2 expressions, and works seamlessly with loop_control.

Q2: Why and when would you use loop_control?
  • Answer: You use loop_control when you need to fine-grained control over loop variables or output display. The two most common use cases are:
    1. loop_var: Changing the default loop variable name from item to something custom. This is vital when you nest loops (for example, when calling include_tasks inside a loop), so the inner loop does not overwrite the outer loop's item.
    2. label: Simplifying or hiding sensitive/verbose output in the console. By default, Ansible prints the entire value of item on screen. Using label allows you to print a cleaner identifier (such as a username or package name instead of a long dictionary). 

Q3: Provide an example of using loop_control with a custom loop_var and label.
  • Answer:
yaml
- name: Create user accounts
  ansible.builtin.user:
    name: "{{ user_item.name }}"
    shell: "{{ user_item.shell }}"
  loop:
    - { name: 'alice', shell: '/bin/bash' }
    - { name: 'bob', shell: '/bin/sh' }
  loop_control:
    loop_var: user_item
    label: "{{ user_item.name }}"
  • In this example, loop_var: user_item prevents conflicts with any outer item, and label: "{{ user_item.name }}" ensures the Ansible log only prints the username (alice, bob) instead of the entire dictionary.

Q4: What happens if you nest loops in Ansible without using loop_control?
  • Answer: If you nest loops (e.g., using include_tasks inside a loop), both the outer loop and the inner loop will try to use the default variable name item. The inner loop will overwrite the item variable of the outer loop, leading to unexpected behavior or syntax errors. Setting loop_var inside loop_control on the inner (or outer) loop prevents this collision. 


Q1 : What is notify and listen

The notify and listen keywords are used together in Ansible to trigger and group handlers (special tasks that run only when a change occurs). 

Key Differences & Core Concepts
Featurenotifylisten
Where it is usedInside a regular taskInside a handler definition
Primary purposeCalls or triggers a handler (or a topic) when the task reports a changed state.Groups multiple handlers under a shared topic name so one notification triggers all of them.
Does it replace the name?No, it references the handler's name or a listen topic name.No, a handler can still have a unique name alongside its listen topic(s).

How They Work Together (Example)
You use notify to broadcast an event name, and one or more handlers can use listen to catch and respond to that event. 
yaml
tasks:
  - name: Update Nginx configuration
    ansible.builtin.template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: "restart web services"  # <--- Trigger the topic

handlers:
  - name: Restart Apache
    ansible.builtin.service:
      name: apache2
      state: restarted
    listen: "restart web services"  # <--- Listens to the topic

  - name: Restart Nginx
    ansible.builtin.service:
      name: nginx
      state: restarted
    listen: "restart web services"  # <--- Listens to the same topic
  • What happens: When the template task changes /etc/nginx/nginx.conf, it executes notify: "restart web services". Any handler listening to "restart web services" (in this case, both Apache and Nginx) will be queued to run at the end of the play. [1]

Common Interview Questions & Answers
Q1: What is the difference between a regular task and an Ansible handler?
  • Answer: A regular task runs sequentially during the playbook execution every time the playbook runs (subject to conditionals). A handler is a special task that is dormant and only executes if it is explicitly notified by a task that reports a changed state, and it typically runs at the end of the play. 
Q2: What problem does the listen keyword solve?
  • Answer: Traditionally, a notify statement could only call a single handler name. If you needed multiple different services or actions to happen from one change, you had to list multiple handler names under notify. The listen keyword lets you create a topic/group name so that a single notify call can trigger multiple distinct handlers at once. 
Q3: Do handlers run immediately when they are notified?
  • Answer: No. By default, handlers are queued and executed at the end of each play, not immediately after the task that notifies them. If you need them to run mid-play, you must force them using meta: flush_handlers. 
Q4: What happens if a handler is notified multiple times by different tasks in the same play?
  • Answer: Ansible collapses duplicate notifications. Even if 10 different tasks notify the exact same handler (or the same listen topic), the handler will only execute once at the end of the play. 

Q1: What is the notify keyword in Ansible, and how does it work?
  • Answer:
    • The notify keyword is used inside a regular task to reference a handler.
    • It only triggers the handler if the task reports a changed status. If the task skips or reports ok (no changes made), the handler is ignored.
    • Multiple tasks can notify the same handler, but Ansible ensures the handler executes only once at the end of the play. 
Q2: What is a handler in Ansible, and why do we use them?
  • Answer:
    • A handler is a special task defined in a separate handlers: section of a play.
    • They look and act like regular tasks (using modules like ansible.builtin.service), but they do not run sequentially where they are listed.
    • Use Case: They solve the problem of unnecessary repetition—such as restarting a nginx or apache service multiple times if five different configuration files get updated in the same playbook. Instead of restarting the service 5 times, you notify the restart handler, and it runs once at the end. 
Q3: When do handlers actually run during a playbook execution?
  • Answer:
    • By default, handlers run at the end of each play.
    • You can also force them to run earlier in the playbook by using the meta: flush_handlers task if a subsequent task depends on the service already being restarted. 
Q4: What happens to handlers if a playbook fails midway?
  • Answer:
    • If a playbook or play fails before reaching the point where handlers are triggered (or fails out completely), handlers will not run.
    • Tip for interviews: This can cause issues during outages if a config file is updated, a service restart handler is queued, and a later task fails—leaving the service running on old or broken configuration unless handled properly. 
Q5: Can a single task notify multiple handlers, or can multiple tasks notify one handler?
  • Answer:
    • Multiple tasks -> One handler: Yes, completely normal. (e.g., Task A, Task B, and Task C all update config snippets and all notify: restart nginx). nginx will restart only once.
    • One task -> Multiple handlers: Yes, you can pass a list under notify: 
      yaml
      notify:
        - Restart nginx
        - Reload firewall
Q1: What is a dictionary variable in Ansible, and when should you use it?
  • Answer: A dictionary variable stores a collection of key-value pairs. Use a dictionary when you need to group related attributes (e.g., a user's name, role, and ssh_key) under a single variable name, rather than creating separate loose variables.
  • Example Definition: 
  • yaml
    vars:
      user_info:
        name: "alice"
        role: "admin"
        shell: "/bin/bash"
    
Q2: How do you reference or access values inside an Ansible dictionary?
  • Answer: You can access values using two main notations:
    1. Dot Notation: {{ user_info.name }} (Clean and easy to read)
    2. Bracket Notation: {{ user_info['name'] }} (Required if the key contains spaces, special characters, or collides with built-in dictionary/Python methods like keys or values)

Q3: What is the difference between a list variable and a dictionary variable?
  • Answer:
    • List Variable (Array): Stores an ordered sequence of peer items accessed by an index number (e.g., fruits[0]).
    • Dictionary Variable (Hash): Stores unordered data mapped by unique keys rather than numeric indices (e.g., user_info['role']).

Q4: How do you merge or override dictionary variables in Ansible?
  • Answer: You can use the combine filter to merge two dictionaries. If keys overlap, the dictionaries merged later in the expression override the earlier ones.
  • Example:
    yaml
    vars:
      default_settings:
        timeout: 30
        port: 80
      custom_settings:
        port: 8080
      merged_settings: "{{ default_settings | combine(custom_settings) }}"
    
    (In this case, merged_settings.port becomes 8080 while timeout remains 30). 

Q5: How do you iterate over a dictionary in an Ansible task or loop?
  • Answer: In modern Ansible, you can convert a dictionary into a list of key-value objects using the dict2items filter so you can loop through it cleanly with loop or ansible.builtin.debug.
  • Example: 
    yaml
    tasks:
      - name: Print all keys and values
        ansible.builtin.debug:
          msg: "Key is {{ item.key }}, value is {{ item.value }}"
        loop: "{{ user_info | dict2items }}"

1. What is a block in Ansible, and why apply a when condition to it?
A block allows you to logically group multiple tasks together. Applying a when conditional at the block level means the entire group of tasks will only execute if the condition evaluates to true.
The Core Problem it Solves (Interview Gold)
  • Performance/Efficiency: Without blocks, if you have 5 tasks that should only run on an Ubuntu server, you have to add when: ansible_facts['os_family'] == "Debian" to every single task. Ansible would evaluate that condition 5 distinct times. 
  • Readability: Grouping them in a block evaluates the when condition once. If it's false, Ansible immediately skips the entire block, saving processing overhead and keeping the playbook logs clean. 
Example Syntax:
yaml
- name: Install and configure Nginx on Debian systems
  block:
    - name: Install Nginx
      ansible.builtin.apt:
        name: nginx
        state: present

    - name: Start Nginx service
      ansible.builtin.service:
        name: nginx
        state: started
  when: ansible_facts['os_family'] == "Debian"  # Applied to the whole block
2. How do block, rescue, and always handle errors?
Interviewers frequently ask: "How do you handle exceptions or implement try/catch/finally logic in Ansible?"
Ansible uses a combination of block, rescue, and always for this exact scenario:
  • block: Defines the main tasks you want to attempt to run. 
  • rescue: Tasks inside this section only run if a task inside the main block fails. This behaves like a catch block in programming and is ideal for rollbacks or error logging. 
  • always: Tasks inside this section run no matter what, regardless of whether the main block succeeded or failed. This behaves like a finally block and is ideal for cleanup activities (like closing connections or deleting temporary files). 
Example Syntax:
yaml
- name: Database Upgrade with Rollback Protection
  block:
    - name: Run database migration script
      ansible.builtin.command: /opt/app/upgrade.sh
  rescue:
    - name: Revert to backup if migration fails
      ansible.builtin.command: /opt/app/rollback.sh
  always:
    - name: Clear temporary installation cache
      ansible.builtin.file:
        path: /tmp/upgrade_cache
        state: absent
3. Key Differences Interviewers Might Ask You to Clarify
ConceptWhat it doesKey takeaway for interviews
when on a BlockEvaluates a condition before any tasks inside the block run.Used for conditional execution (skipping tasks) based on facts/variables.
failed_whenOverrides what Ansible considers a "failure" based on task output.It forces a task to pass or fail depending on custom string matching/return codes.
ignore_errors: yesForces the playbook to keep moving forward even if a specific task fails.Poor practice if used everywhere. A block/rescue structure is much safer for granular recovery.

4. Common Interview "Gotchas" (Pro-Tips)
  • Loops on Blocks: You cannot apply a loop or with_items directly to a block statement in Ansible. If an interviewer asks how you loop a block, clarify that loops must be applied to individual tasks inside the block, or packaged into an include_tasks file. 
  • Skipping vs Failing: A when condition that evaluates to false simply skips the block; it does not trigger the rescue section. The rescue section only triggers if a task executes and actively returns a failed state. 

Question: What is ansible language support in vs code

To get full Ansible language support in Visual Studio Code, you need the official Ansible VS Code Extension created by Red Hat. This extension uses the underlying ansible-language-server to transform VS Code into a robust development environment for automation. 

Key Features
  • Smart Auto-Completion: Context-aware IntelliSense that prioritizes required properties, module names, and variables. 
  • Syntax Highlighting: Clear, distinct color-coding for keywords, modules, and Jinja expressions. 
  • Real-Time Validation: Background linting using ansible-lint and yamllint to catch bugs before running code. 
  • Hover Documentation: Hovering your cursor over a module or keyword pulls up the official Ansible documentation directly inside the editor. 
  • Go to Definition: Jump directly to code definitions or related files with a click. 
  • Ansible Lightspeed: AI-assisted task and playbook generation embedded into the editor. 

Setup Guide
1. Install the Extension
  1. Open VS Code and open the Extensions view (Ctrl+Shift+X or Cmd+Shift+X).
  2. Search for "Ansible".
  3. Select the extension published by Red Hat and click Install.
  4. (Recommended) Also install the YAML extension by Red Hat, which assists with inventory and variable file structures. 
2. Install Local Prerequisites
For full diagnostics and linting to work properly, your underlying system (or your development environment) should have the following tools installed via pip3 or your package manager: 
bash
pip3 install ansible-core ansible-lint yamllint
3. Activate Ansible Language Mode
VS Code usually detects .yml and .yaml files as generic YAML. To get full Ansible support, tell VS Code to treat the file as Ansible: 
  1. Open your playbook or tasks file. 
  2. Look at the bottom right status bar of VS Code—it will likely say YAML. 
  3. Click YAML, type Ansible in the drop-down command palette, and select it. 
Tip: You can map your settings so all YAML files in an automation folder default to Ansible by adding file associations to your settings.json:
json
"files.associations": {
    "**/*playbook*.yml": "ansible",
    "**/roles/**/*.yml": "ansible"
}
Configuration & Advanced Workflows
The extension can adapt to how you run Ansible. You can view all adjustable configurations in the Ansible Language Server Settings documentation. 
  • Execution Environments (EE): If you develop using isolated containers, the extension natively supports containerized workflows via Podman or Docker, mapping your workspace seamlessly into the execution toolchain. 
  • Auto-Formatting on Save: To keep your playbooks flawlessly formatted for ansible-lint, toggle these settings in your VS Code configuration:
    • files.trimTrailingWhitespace: true
    • files.insertFinalNewline: true 


Question : interpretion for source /home/ansible/pyvenv/bin/activate

The command source /home/ansible/pyvenv/bin/activate activates a Python virtual environment located at /home/ansible/pyvenv/. Sourcing this script modifies your current shell's environment variables (specifically updating your PATH) so that any subsequent python or pip commands target this isolated environment instead of the system-wide Python installation. 
 Common Next Steps
Once the environment is active, you will see (pyvenv) prepended to your terminal prompt. You can then proceed with your Ansible or Python workflows: 
  • Upgrade Package Installer: Ensure you are using the latest pip version inside the environment: 
    bash
    python3 -m pip install --upgrade pip
    

  • Install Ansible or dependencies: Install packages directly into this isolated space: 
    bash
    pip install ansible
    

  • Verify the active path: Double-check that your binaries are running from the virtual environment: 
    bash
    which ansible
    # or
    which python
    

  • Exit the environment: When you are finished, return to your normal system shell: 
    bash
    deactivate
    
     Automation Pro-Tip
If you are trying to use this environment inside an automated Ansible playbook or cron job, running source will fail or lose scope because each task spawns a new sub-shell. Instead of activating it, call the binaries directly using their absolute paths: 
  • /home/ansible/pyvenv/bin/ansible-playbook site.yml
  • /home/ansible/pyvenv/bin/pip install -r requirements.txt 

Q1: What is Team Foundation Server (TFS), and how does it relate to Azure DevOps?
Answer: Team Foundation Server (TFS) is a Microsoft Application Lifecycle Management (ALM) platform providing version control, issue tracking, build automation, and project management capabilities.
  • Evolution: Microsoft rebranded TFS to Azure DevOps Server for on-premises deployments, while the cloud-hosted version is known as Azure DevOps Services.
Q2: What are the two types of version control systems supported by TFS/Azure Repos?
Answer: TFS supports Team Foundation Version Control (TFVC) and Git.
  • TFVC is a centralized version control system where developers check files out from a single server repository.
  • Git is a distributed version control system where every developer has a full copy of the repository locally.
Q3: Compare TFVC (Centralized) vs Git (Distributed) in TFS.
Answer:
FeatureTFVC (Centralized)Git (Distributed)
StorageEntire history lives on a central SQL server.Full history cloned locally to each machine.
BranchingPath-based. Creating a branch copies folders on the server.Pointer-based. Lightweight and fast local creation.
PermissionsHighly granular; permissions can be set down to individual files.Repository/Branch level permissions only.
Offline WorkLimited. Requires a server connection to check out/in files.Full offline capability. Commits and branches happen locally.

2. Workspace & File Management Questions
Q4: What is the difference between a Local Workspace and a Server Workspace in TFVC?
Answer:
  • Local Workspace: Files are not marked as read-only on your disk. TFS detects changes by scanning the file system. It allows offline modifications and works best for smaller repositories (under 100,000 files).
  • Server Workspace: TFS marks files as read-only on your disk until you explicitly check them out. The server tracks who has what checked out. It handles massive repositories better but requires a continuous server connection.
Q5: How can you see all items checked out by other users in TFS?
Answer: You can view these using the tf status command in the Visual Studio Command Prompt.
Run the following syntax in your workspace:
bash
tf status /user:* /recursive
This query returns a comprehensive list of all pending changes and checked-out files across all users in the collection.
Q6: How do you exclude specific files or file extensions from being tracked in TFS source control?
Answer:
  • In TFVC, you use a .tfignore text file placed in your local workspace folder.
  • In Git, you use a standard .gitignore file.
    Inside these files, you define wildcards or paths (e.g., *.user or /bin/) to tell the engine to ignore temporary or build-generated outputs.

3. Branching, Merging & Tracking Questions
Q7: What is a "Changeset" in TFS (TFVC)?
Answer: A Changeset is a logical grouping of file modifications, additions, or deletions committed to the TFS server in a single atomic check-in. Each changeset receives a unique incremental ID number, tracks the author, includes check-in comments, and logs associated Work Items (like bugs or tasks).
Q8: How can you roll back or revert a specific check-in/changeset in TFS?
Answer:
  • Using Visual Studio GUI: Open Source Control Explorer, right-click the file/folder, select View History, right-click the target changeset, and choose Rollback Entire Changeset.
  • Using Command Line: Run the tf rollback command:
    bash
    tf rollback /changeset:12345
    
    After executing the rollback, you must check in the pending changes to commit the reversal to the repository server.
Q9: What post-merge steps should be prioritized after merging a branch in TFS?
Answer: Following a branch merge, you should follow this stabilization workflow:
  1. Resolve Merge Conflicts: Use the TFS merge tool to settle file-level differences.
  2. Execute Local Build & Unit Tests: Ensure the merged code builds locally without failure.
  3. Trigger CI/CD Pipeline: Run automated builds and code analysis suites.
  4. Code Review: Have peers validate the structural integrity of the integration.

4. Advanced Operations & Administration
Q10: How do you move code and history from one TFS server to another?
Answer: The approach depends on what you want to preserve:
  • Full Fidelity Migration: Take a backup of the source TFS Collection Database (SQL Server), restore it on the new SQL target, and attach it via the TFS Administration Console. This retains all work items, build history, permissions, and raw source history.
  • History Consolidation (Git-TFS): If moving to Git or a clean slate, utilities like Git-TFS clone the TFVC repository directly into a local Git repo while accurately mapping changesets into Git commits.

Question : what is jinja template in ansible

Jinja2 templating in Ansible allows you to generate dynamic, reusable configuration files and control logic by embedding variables, expressions, loops, and conditionals. All template rendering happens entirely on the Ansible control node before the values are pushed to your managed hosts, reducing dependencies on your remote targets. 

1. Basic Jinja2 Syntax Rules
Jinja2 relies on three primary syntax markers to distinguish code from plain text: 
  • {{ ... }} (Expressions): Used for variable substitution or printing the result of an expression. [
  • {% ... %} (Statements): Used for logic control, such as loop iterations (for) and conditional blocks (if).
  • {# ... #} (Comments): Used for adding inline comments that will not appear in the final rendered file.

2. Core Functional Examples
Variable Substitution
Inserts variables defined in your playbooks, host files, or gathered system facts. 
nginx
# templates/nginx.conf.j2
server {
    listen {{ http_port }};
    server_name {{ server_name }};
}
Conditionals (if / else)
Renders blocks of code conditionally based on host facts or defined states. 
ini
# templates/motd.j2
Welcome to the server!
{% if ansible_facts['os_family'] == "RedHat" %}
This system runs on RHEL/CentOS.
{% else %}
This system runs on a non-RedHat OS.
{% endif %}
Loops (for)
Iterates over lists or dictionaries to output repetitive structural blocks. 
haproxy
# templates/haproxy.cfg.j2
backend web_servers
    balance roundrobin
{% for host in groups['webservers'] %}
    server {{ host }} {{ hostvars[host]['ansible_host'] }}:80 check
{% endfor %}
Filters
Modifies or formats variables on the fly by piping them through a filter. 
text
# Converts the string to uppercase
admin_user: {{ my_user | upper }}

# Provides a fallback value if the variable is undefined
fallback_port: {{ backend_port | default(8080) }}
3. Deploying Templates in a Playbook
To apply a Jinja2 template file (traditionally given a .j2 extension), you use Ansible's built-in template module. 
yaml
---
- name: Deploy dynamic configuration
  hosts: webservers
  vars:
    http_port: 80
    server_name: app.example.com

  tasks:
    - name: Render and copy NGINX configuration
      ansible.builtin.template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/sites-available/default
        mode: '0644'
4. Direct Inline Templating
You do not always need a dedicated .j2 file. Ansible parses Jinja2 syntax natively inside regular playbook blocks to dynamically evaluate arguments. 
yaml
- name: Create a dynamic directory path
  ansible.builtin.file:
    path: "/var/log/app_{{ ansible_facts['hostname'] }}"
    state: directory



Ansible Jinja2 Interview Questions & Answers
Q1: How do you use a Jinja2 template in an Ansible playbook?
  • Answer: You use the ansible.builtin.template module. It takes a source template file (usually ending in .j2) on the control node, processes it using the target host's facts and variables, and copies the rendered file to the destination on the managed node.
  • Example:
    yaml
    - name: Configure Nginx from template
      ansible.builtin.template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: '0644'
    
    Q2: What is the difference between the template module and the copy module?
  • template module: Parses the file dynamically through the Jinja2 engine. It replaces placeholders, executes loops, and evaluates conditionals before placing the file.
  • copy module: Moves a file exactly as-is. It does not look inside the file to change variables or evaluate code.
Q3: How do you handle a scenario where your configuration file needs to contain literal {{ and }} characters without Jinja processing them?
  • Answer: You can use the {% raw %} and {% endraw %} block tags. Anything placed inside these tags is ignored by the Jinja2 engine and printed as literal text.
  • Example:
    jinja2
    {% raw %}
    This is a Prometheus metric: metric_name{label="value"}
    {% endraw %}
    
    Q4: What are Jinja2 filters, and how do you use them in Ansible?
  • Answer: Filters are pipe operators (|) used to transform or manipulate variable data. Ansible includes standard Jinja2 filters and adds its own custom ones (like to_json, ipaddr, b64decode).
  • Example:
    • {{ my_variable | upper }} (Converts to uppercase)
    • {{ db_password | password_hash('sha512') }} (Hashes a string)

Real-World Project Context: Dynamic Multi-Environment Microservice Configuration
When interviewers ask for project details, use this structured scenario to demonstrate production-level experience.
Project Overview
  • Goal: Automate the deployment and configuration of an application stack (e.g., Nginx API Gateway + Spring Boot Microservices) across Dev, Staging, and Production environments using a single, reusable Ansible role.
  • How Jinja2 Was Used: Instead of maintaining three separate, static configuration files for each environment, we created one dynamic app_config.yml.j2 file. Jinja2 injected environment-specific database credentials, memory limits, and domain names at runtime based on inventory variables.
Example Template (app_config.yml.j2)
jinja2
# Generated automatically by Ansible - Do Not Edit Manually
environment: {{ env_name | default('development') }}
debug_mode: {{ 'true' if env_name == 'dev' else 'false' }}

database:
  host: "{{ db_host }}"
  port: {{ db_port }}
  pool_size: {% if env_name == 'prod' %}50{% else %}10{% endif %}

allowed_hosts:
{% for host in groups['webservers'] %}
  - {{ hostvars[host]['ansible_default_ipv4']['address'] }}
{% endfor %}
Production Challenges & Solutions
Interviewers love to hear about what went wrong and how you fixed it. Here are three common Jinja2 challenges in Ansible:
  • Challenge 1: Missing Variable Failures ("Undefined variable")
    • Problem: If a single variable in a massive .j2 template is missing from your group vars or host vars, the entire Ansible task crashes.
    • Solution: Use the | default() filter consistently to provide safe fallback values, or use ansible.builtin.assert tasks before the template block to validate required variables.
  • Challenge 2: Sloppy Formatting and Whitespace Control
    • Problem: Loops ({% for %}) and conditionals ({% if %}) inherently inject blank lines and extra spaces into the generated config file, breaking strict parsers like YAML or JSON.
    • Solution: Use whitespace control characters. Adding a minus sign {%- or -%} strips spaces and newlines from the start or end of the block.
  • Challenge 3: Silent Syntax Failures (Valid Jinja, Broken Config)
    • Problem: Ansible might successfully render a template without throwing an error, but the resulting file might have invalid syntax for the target application (e.g., an invalid Nginx config block), causing services to crash upon reload.
    • Solution: Use the validate parameter in the template module. For example, validate: '/usr/sbin/nginx -t -c %s' ensures Ansible tests the newly rendered config file before overwriting the live production file.

Question : how to clone and initialize on wsl2 ubuntu in vocode running from azure dev ops

To clone and initialize an Azure DevOps repository inside WSL2 (Ubuntu) while running Visual Studio Code connected to WSL, you must run the Git commands directly within the WSL terminal rather than cloning into a Windows directory. 
Step 1: Connect VS Code to WSL2 Ubuntu
  1. Open VS Code on Windows.
  2. Press Ctrl + Shift + P to open the Command Palette.
  3. Type and select WSL: Connect to WSL. A new VS Code window will launch connected to your Ubuntu environment. 
  4. Open the integrated terminal inside VS Code (Ctrl + or Terminal > New Terminal). Verify that the terminal prompt says ubuntu@... (or your Linux username) and not PowerShell or Command Prompt. 
Step 2: Get the Clone URL from Azure DevOps
  1. Go to your Azure DevOps project.
  2. Navigate to Repos > Files.
  3. Click the Clone button in the upper right.
  4. Copy the HTTPS (or SSH if configured) clone URL. 
Step 3: Clone the Repository inside WSL2
  1. In the VS Code terminal (which is running inside WSL Ubuntu), navigate to the directory where you want to store your project (e.g., your Linux home directory):
    bash
    cd ~/projects
    

  2. Clone the repository using git clone:
    bash
    git clone <YOUR_AZURE_DEVOPS_CLONE_URL>
    

  3. When prompted for credentials:
    • Username: Your Azure DevOps username or email address.
    • Password: Use an Azure DevOps Personal Access Token (PAT) with Code (Read & Write) permissions (your standard Microsoft/organization password will not work if MFA or basic auth restrictions are enabled).
Step 4: Initialize and Open in VS Code
  1. Move into the cloned repository folder:
    bash
    cd <repository-folder-name>
    

  2. If the repository was empty and you need to initialize it locally:
    .bash
    git init
    git branch -M main
    git remote add origin <YOUR_AZURE_DEVOPS_CLONE_URL>
    

  3. Open the folder in your active WSL VS Code window:
    bash
    code .

Question :  How to create feature branch in vscode

To create a feature branch in Visual Studio Code, click the Git branch name in the bottom-left Status Bar, select "Create new branch...", type your branch name (e.g., feature/login-page), and press Enter. 
You can accomplish this through three different methods depending on your preference:
Method 1: The Status Bar (Fastest UI Method)
  1. Look at the bottom-left corner of the VS Code window to find your current branch name (e.g., main or master). 
  2. Click the branch name to open the Command Palette dropdown menu at the top of the screen. 
  3. Select Create new branch... 
  4. Type your new feature branch name (e.g., feature/your-feature-name) and press Enter. VS Code will create the branch and automatically switch (checkout) to it. 
Method 2: The Source Control Panel
  1. Click the Source Control icon on the left Activity Bar (or press Ctrl+Shift+G). 
  2. Click the ... (Three Dots) icon at the top of the Source Control panel to open the menu. 
  3. Hover over Branch and click Create Branch...
  4. Enter your branch name and hit Enter. 
Method 3: The Integrated Terminal (CLI Method)
  1. Open the terminal by pressing `Ctrl + `` (backtick). 
  2. Run the checkout command with the -b flag to create and switch to your new branch: 
    bash
    git checkout -b feature/your-feature-name
    
 Publishing Your Branch
Your newly created branch only exists locally on your computer. To share it with your team or back it up to GitHub/GitLab: 
  • Click the Publish Branch button that appears in the Source Control panel or next to the branch name in the status bar


Question: What is wsl extension in vs code

The VS Code WSL extension lets you use the Windows Subsystem for Linux (WSL) as a full-time, native development environment right from your Windows desktop. 
It splits VS Code into a client-server architecture: the user interface runs smoothly on Windows, while the code, compilers, linters, and the integrated terminal run directly inside the Linux distribution. 

 Quick Start Guide
1. Install the Extension
  1. Open VS Code on Windows.
  2. Click the Extensions icon on the left sidebar (or press Ctrl + Shift + X).
  3. Search for "WSL" (published by Microsoft) and click Install. 
2. Open a Project in WSL
The fastest way to jump into WSL is straight from your command line:
  1. Open your WSL terminal (e.g., Ubuntu).
  2. Navigate to your project folder: cd ~/my-project
  3. Launch VS Code by typing:
    bash
    code .
    

  4. VS Code will automatically download the lightweight VS Code Server inside Linux and establish the connection. 
Alternative: Click the green remote indicator button in the bottom-left corner of VS Code and select WSL: Connect to WSL.

 How Extensions Change in WSL
When connected to WSL, your extensions sidebar splits into two categories: 
  • Local (Windows): UI-focused extensions like themes and keymaps only need to be installed once on Windows. 
  • WSL (Linux): Execution-focused extensions (like Python, C++, Go, or Docker) must be installed directly inside your WSL instance so they can access the Linux compilers and runtimes. Look for the green "Install in WSL" button next to your extensions. 

 Pro-Tips for Peak Performance
  •  Store files in the Linux filesystem: For maximum speed, keep your code inside the Linux file system (e.g., /home/username/projects). Do not open files located on the Windows side (/mnt/c/) as cross-OS file tracking will slow down your environment significantly. 
  •  Automatic Port Forwarding: If you run a local web server inside WSL (like a Node.js or Python backend), the extension automatically forwards the ports. You can access it in your Windows browser using standard localhost:XXXX URLs.