Note:

Build Custom Execution Environments with Oracle Linux Automation Manager Builder Utility

Introduction

The Builder utility is a tool based on the upstream ansible-builder project, which generates custom execution environments for Oracle Linux Automation Manager.

This tutorial shows how to install the Builder utility and then create and verify a custom execution environment.

Objectives

In this tutorial, you’ll learn how to:

Prerequisites

Deploy Oracle Linux

Note: If running in your own tenancy, read the linux-virt-labs GitHub project README.md and complete the prerequisites before deploying the lab environment.

  1. Open a terminal on the Luna Desktop.

  2. Clone the linux-virt-labs GitHub project.

    git clone https://github.com/oracle-devrel/linux-virt-labs.git
    
  3. Change into the working directory.

    cd linux-virt-labs/olam
    
  4. Install the required collections.

    ansible-galaxy collection install -r requirements.yml
    
  5. Update the Oracle Linux instance configuration.

    cat << EOF | tee instances.yml > /dev/null
    compute_instances:
      1:
        instance_name: "devops-node"
        type: "server"
    olam_type: none
    EOF
    
  6. Create an inventory file.

    cat << EOF | tee hosts > /dev/null
    localhost ansible_connection=local ansible_connection=local ansible_python_interpreter=/usr/bin/python3.6
    EOF
    
  7. Deploy the lab environment.

    ansible-playbook create_instance.yml -i hosts -e "@instances.yml"
    

    The free lab environment requires the extra variable ansible_python_interpreter for localhost because it installs the RPM package for the Oracle Cloud Infrastructure SDK for Python. The location for installing this package is under the system’s default Python modules based on your version of Oracle Linux. Using an inventory variable avoids impacting the plays running on hosts other than localhost.

    The default deployment shape uses the AMD CPU. You can change the shape of the instances by passing a new shape variable definition on the command line.

    For example: -e instance_shape="VM.Standard3.Flex"

    Similarly, the default version of the Oracle Linux image uses the variable os_version defined in the `default_vars.yml file. You can modify this value by passing the Oracle Linux major version on the command line.

    For example: -e os_version="9"

    Important: Wait for the playbook to run successfully and reach the pause task. At this stage of the playbook, the installation of Oracle Linux is complete, and the instances are ready. Note the previous play, which prints the public and private IP addresses of the nodes it deploys.

Install Builder Utility

  1. Open a terminal and connect via SSH to the devops-node instance.

    ssh oracle@<ip_address_of_instance>
    
  2. Install the Oracle Linux Automation Manager repository.

    Oracle Linux 8:

    sudo dnf install -y oraclelinux-automation-manager-release-el8
    

    Oracle Linux 9:

    sudo dnf install -y oraclelinux-automation-manager-release-el9
    
  3. Install the Builder utility package.

    sudo dnf install -y python3.11-ansible-builder
    

    The Builder utility installs python3.11, podman, and other package dependencies.

Create the Custom Execution Environment Definition

When building your execution environment, you define the content in a YAML file. The Builder utility provided as part of Oracle Linux Automation Manager allows users to use either version 1, version 2, or version 3 schemas. For this tutorial, we’ll focus on version 3.

  1. Create a project directory.

    mkdir ~/my_custom_ee
    
  2. Create the default file.

    The execution_enviroment.yml file tells the Builder utility how to construct the instruction file, a Containerfile for Podman, and any additional build context for our container image.

    Oracle Linux 8:

    tee ~/my_custom_ee/execution-environment.yml > /dev/null <<EOF
    ---
    version: 3
    
    build_arg_defaults:
     ANSIBLE_GALAXY_CLI_COLLECTION_OPTS: '--pre --ignore-certs'
    
    dependencies:
     ansible_runner:
       package_pip: ansible-runner
     galaxy: requirements.yml
     python: requirements.txt
     system: bindep.txt
    
    images:
     base_image:
      name: container-registry.oracle.com/oracle_linux_automation_manager/olam-ee:2.3-ol8
    
    additional_build_files:
        - src: ansible.cfg
          dest: configs 
    
    additional_build_steps:
      prepend_galaxy:
        - COPY _build/configs/ansible.cfg /etc/ansible/ansible.cfg
      prepend_final: |
        RUN whoami
        RUN cat /etc/os-release
      append_final:
        - RUN echo This is a post-install command!
        - RUN ls -la /etc
    EOF
    

    Oracle Linux 9:

    tee ~/my_custom_ee/execution-environment.yml > /dev/null <<EOF
    ---
    version: 3
    
    build_arg_defaults:
     ANSIBLE_GALAXY_CLI_COLLECTION_OPTS: '--pre --ignore-certs'
    
    dependencies:
     ansible_runner:
       package_pip: ansible-runner
     galaxy: requirements.yml
     python: requirements.txt
     system: bindep.txt
    
    images:
     base_image:
      name: container-registry.oracle.com/oracle_linux_automation_manager/olam-ee:2.3-ol9
    
    additional_build_files:
        - src: ansible.cfg
          dest: configs 
    
    additional_build_steps:
      prepend_galaxy:
        - COPY _build/configs/ansible.cfg /etc/ansible/ansible.cfg
      prepend_final: |
        RUN whoami
        RUN cat /etc/os-release
      append_final:
        - RUN echo This is a post-install command!
        - RUN ls -la /etc
    EOF
    

    Details on constructing this file exist in the Oracle Linux Automation Manager or the upstream documentation.

  3. Add additional Ansible Collections.

    These are a list of dependencies that the Builder utility installs using the ansible-galaxy collection install -r requirements.yml command.

    tee ~/my_custom_ee/requirements.yml > /dev/null <<EOF
    ---
    collections:
    - name: oracle.oci
      version: ">=5.5.0,<6.0.0"
      type: galaxy
    - name: ovirt.ovirt
    EOF
    

    This requirements.yml pulls two collections:

    • The Oracle OCI collection to enable a playbook to interact with your OCI tenancy
    • The oVirt collection for managing libvirt environments such as KVM and Oracle Linux Virtualization Manager.
  4. Include Python dependencies.

    This file instructs the Builder utility to install the list of Python dependencies using the pip3 install -r requirements.txt command. The pip3 command installs these dependencies under the /usr/local/lib/python3.11/site-packages directory, as the Builder utility uses the 3.11 version of Python.

    tee ~/my_custom_ee/requirements.txt > /dev/null <<EOF
    requests>=2.4.2
    ovirt-engine-sdk-python>=4.6.2
    oci>=2.155.0
    EOF
    

    This file pulls the latest Python packages for requests, Python SDK for oVirt, and the Oracle OCI SDK for Python.

  5. Define additional system packages.

    The Builder utility includes binary packages using the [bindep](https://docs.opendev.org/opendev/bindep/latest/readme.html) tool, which runs dnf within the container.

    Oracle Linux 8:

    tee ~/my_custom_ee/bindep.txt > /dev/null <<EOF
    gcc
    libcurl-devel
    libxml2-devel
    python3.11-devel
    openssl-devel
    EOF
    

    Oracle Linux 9:

    tee ~/my_custom_ee/bindep.txt > /dev/null <<EOF
    gcc
    libcurl-devel
    libxml2-devel
    python3-devel
    openssl-devel
    EOF
    

    The libxml2-devel package provides the necessary libraries, includes, and other components to develop XML and HTML applications. The OCI Ansible Collection or OCI SDK for Python does not require this package and is just an example of using the bindep.txt file. However, the oVirt collection requires the Python development packages, and the required version differs depending on the version of Oracle Linux used within the image.

  6. Create an Ansible configuration settings file.

    We will not be using this file in this lab, so please create it and leave it empty.

    touch ~/my_custom_ee/ansible.cfg
    

Build the Custom Execution Environment

The ansible-builder build command takes our execution environment definition, generates the build instructions for our custom image, and then builds it.

  1. Change into our project directory.

    cd ~/my_custom_ee
    
  2. Build the image.

    ansible-builder build --tag my_custom_ee -v 3
    

    The --tag customizes the tagged name applied to the image, while the -v sets the verbosity of the command’s output.

  3. Monitor the output as the build steps complete.

  4. Verify the image exists.

    podman images
    

    As the Builder utility runs as a non-root user, podman creates and then stores the container image localhost/my_custom_ee under the user’s home directory in $HOME/.local/share/containers/storage as a default. You’ll also see other images for this user, including the base and builder images we define in the custom execution environment definition file.

Test the Custom Execution Environment Image

Before loading our custom execution environment image into Oracle Linux Automation Manager, we should test it and ensure it behaves as expected. To accomplish this task, we’ll introduce the upstream project Ansible Navigator. Oracle does not provide this utility, so it is not supported.

Navigator requires Python version 3.8 or greater; so we’ll use Python 3.11, which matches the version used by the Builder utility.

  1. Install the Python 3.11 pip module.

    sudo dnf install -y python3.11-pip
    
  2. Install Ansible Navigator.

    python3.11 -m pip install ansible-navigator
    
  3. Verify the success of the Ansible Navigator installation.

    ansible-navigator -h
    
  4. Make a project directory for our test playbook.

    mkdir -p /tmp/private/project
    
  5. Write the playbook.

    tee /tmp/private/project/playbook.yml > /dev/null <<'EOF'
    ---
    - name: get namespace name
      hosts: localhost
      collections:
        - oracle.oci
      tasks:
        - name: get namespace
          oracle.oci.oci_object_storage_namespace_facts:
          register: output
        - name: print namespace
          debug:
            msg: ""
    EOF
    

    This playbook prints the namespace for the associated tenancy, which we define in a local OCI SDK and CLI configuration file.

  6. Create the SDK and CLI default configuration file.

    The free lab environment provides a pre-generated SDK and CLI configuration file, which we can copy from the Luna Desktop to our devops-node instance. If running in your environment and tenancy, see the instructions provided within the SDK and CLI Configuration File and Required Keys and OCIDs sections of the OCI Documentation.

    1. Make the default configuration directory on the devops-node instance.

      mkdir ~/.oci
      
    2. Open a new terminal from the Luna Desktop environment.

      Note: Do not connect to the devops-node.

    3. Copy all of the configuration files to the devops-node instance.

      scp ~/.oci/* oracle@<ip_address_of_devops-node_instance>:~/.oci/.
      
    4. Exit the current terminal.

      exit
      
    5. Switch to the open terminal window connected to the devops-node instance.

    6. Review the SDK and CLI configuration file.

      cat ~/.oci/config
      
  7. Update the location of the key_file in the SDK configuration file.

    Since we plan to test the playbook within our custom execution environment image, we must set this value to the container’s root user’s home directory, denoted by $HOME.

    Information: When mounting the SDK configuration directory to the container, Podman maps the local user’s UID (User ID) into the container as root. Since we’ll be in the root user namespace, the $HOME directory within the container will be /root.

    sed -i 's|/home/luna.user|/root|g' ~/.oci/config
    

    If you modify the file manually with your favorite editor of choice, you can replace /home/luna.user with the shorthand syntax of ~.

  8. Run the playbook with Ansible Navigator.

    ansible-navigator run /tmp/private/project/playbook.yml --mode stdout --execution-environment-image my_custom_ee --container-options="--volume=/home/oracle/.oci/:/root/.oci/:Z" --pull-policy never
    
    • run: is the command mode for the Ansible Navigator
    • /tmp/private/project/playbook.yml: playbook to run within the custom execution environment
    • --node stdout: allows passing most ansible-playbook commands and extensions
    • --execution-environment-image: name of the custom execution environment
    • --container-options: accepts most podman command line options. This example mounts the local SDK and CLI configuration file to the root user’s $HOME directory within the container. The :Z creates a private, unshared SELinux label of container_file_t
    • --pull-policy: sets the image pull policy

Next Steps

The output of the tenancy namespace confirms you have a working execution environment for running playbooks within Oracle Linux Automation Manager. Explore our other tutorials, which cover Oracle Linux Automation Manager and Oracle Linux technologies.

More Learning Resources

Explore other labs on docs.oracle.com/learn or access more free learning content on the Oracle Learning YouTube channel. Additionally, visit education.oracle.com/learning-explorer to become an Oracle Learning Explorer.

For product documentation, visit Oracle Help Center.