This directory contains a dynamic Ansible inventory plugin designed to generate an inventory for various Oracle deployment topologies on Google Cloud.
The plugin (gcp_oracle_inventory.py) does not use a static inventory file. Instead, it dynamically constructs an in-memory inventory by parsing a YAML configuration file. The install-oracle.sh script automatically generates this YAML file (e.g., gcp_oracle.yml.XXXXXX) based on the command-line arguments provided.
The plugin is automatically activated by Ansible when the inventory source (-i) is a file whose name begins with gcp_oracle.yml.
This plugin relies on the PyYAML library for parsing YAML configuration files. When installing ansible-core via pip install ansible-core PyYAML is typically included as a dependency, so no separate installation should be required in most Ansible environments.
A critical aspect of this system is the merging of variables. The dynamic inventory plugin sets host-specific variables based on the generated YAML file (e.g., IP addresses, database name).
However, a large number of default values, complex Jinja2 templates, and derived variables are defined in group_vars/all.yml. Ansible automatically loads these variables and merges them with the host variables from the dynamic inventory. This creates the final, complete set of variables that the playbooks use during execution.
To inspect the final, merged inventory, you can run a command similar to this (assuming gcp_oracle.yml.yJ5W0I is a generated inventory file):
ansible-inventory -i gcp_oracle.yml.yJ5W0I --listThe structure of the generated inventory depends on the --cluster-type argument passed to install-oracle.sh.
This is the most straightforward topology, used for standalone Oracle databases.
- Generated Groups: A single group named
dbasm. - Hosts: The
dbasmgroup contains a single host. The name of the host is taken from theinstance_hostnamevariable. - Variables: All variables from the generated YAML file and
group_vars/all.ymlare applied to this single host.
This topology is for multi-node, active-active Oracle database clusters.
- Generated Groups: A single group named
dbasm. - Hosts: The
dbasmgroup contains multiple hosts, one for each node defined in thecluster_config_jsonvariable provided to theinstall-oracle.shscript. - Variables:
- Node-specific variables from the JSON configuration (e.g.,
vip_name,vip_ip) are set as host variables for each respective node. - Cluster-wide parameters from the JSON configuration, including network details like
public_netandscan_ips, are set as group variables for thedbasmgroup for compatibility with the existing playbooks as they reference these variables by group name. - Variables from
group_vars/all.ymlare merged for all hosts.
- Node-specific variables from the JSON configuration (e.g.,
This topology provides a primary database and a standby database for disaster recovery. The deployment is a two-step process:
- Primary Node Setup: First,
install-oracle.shis run with--cluster-type NONEon the primary machine to install a standalone database. - Standby Node Setup: Second,
install-oracle.shis run with--cluster-type DG --primary-ip-addr <ip_address_of_primary_node>. The inventory described below is generated during this second step.
- Generated Groups:
dbasm: Contains the standby node.primary: Contains the primary node.
- Rationale for Structure: During the standby setup, the primary database is already fully configured. The inventory's purpose is not to re-configure the primary, but to include it as a remote target for specific tasks (e.g., enabling force logging, configuring the Data Guard broker).
- Variable Assignment:
- The standby host in the
dbasmgroup receives the full set of configuration variables from the YAML file andgroup_vars/all.yml. - The primary host in the
primarygroup is intentionally assigned only the necessary SSH connection parameters (ansible_ssh_host,ansible_ssh_user, etc.). This is to prevent bugs where a standby-specific variable could be accidentally used during a task delegated to the primary host.
- The standby host in the
ora_cluster_type: DG
# Standby's IP and Hostname
instance_ip_addr: 10.0.0.2
instance_hostname: standby-1
# Primary's IP
primary_ip_addr: 10.0.0.1
# Common SSH credentials
instance_ssh_user: ansible
instance_ssh_key: /home/ansible/.ssh/id_rsa
# Other Oracle configuration parameters...
ora_swlib_bucket: gs://my-swlib-bucket
db_password_secret: projects/my-project/secrets/db-password/versions/1
ora_version: 19
db_name: ORCLUnit tests for the gcp_oracle_inventory.py plugin are located in test_gcp_oracle_inventory.py within this directory. These tests ensure the plugin correctly parses configuration files and generates the expected Ansible inventory structure for various deployment types.
- The tests compare the dynamically generated inventory against pre-defined JSON snapshot files (located in
testdata/snapshots). These snapshots capture the expected inventory structure, including host groups, hosts, and the key variables explicitly assigned by the plugin.
To run all unit tests, navigate to the project root directory and execute the following command:
pytest inventory_plugins/
It is also possible to manually inspect how Ansible renders the inventory for the input test YAML files. Since the plugin expects its configuration file to begin with gcp_oracle.yml, you can copy one of the test input files to a temporary name and then run ansible-inventory:
cp inventory_plugins/testdata/inputs/data_guard.yml gcp_oracle.yml.tmp
ansible-inventory -i gcp_oracle.yml.tmp --listNote that the output inventory will contain a large set of variables, including those explicitly defined in the input gcp_oracle.yml.tmp file and those merged from group_vars/all.yml (which provides internal variables and default values). The input files in testdata/inputs/ contain only a small subset of these variables.
The install-oracle.sh script provides a --inventory-file flag that allows you to bypass the dynamic inventory plugin and use your own static inventory file. When this flag is used, you become responsible for defining the entire inventory structure, including host groups and all necessary variables.
This is particularly critical for Data Guard deployments, which rely on a specific structure and a special variable (is_standby_node) to function correctly.
To successfully deploy a Data Guard standby node using a custom inventory, your file must adhere to the following structure:
- Groups: You must define two groups:
dbasm(for the standby node) andprimary(for the primary node). - Primary hostname: The primary host in your inventory must be named
primary1, as playbooks rely on this hardcoded hostname for delegation and targeting. - Hosts: The standby machine must be placed in the
dbasmgroup, and the primary machine must be in theprimarygroup. is_standby_nodevariable: You must set the variableis_standby_node=truefor the standby host. This is the flag that tells theconfig-db.ymlplaybook to run the standby creation tasks (db-copy) instead of the primary creation tasks.- Host-specific variables: You must define variables that are unique to each host, such as
ansible_ssh_host, directly in the inventory. Most other configuration variables will be automatically applied fromgroup_vars/all.yml.
Example inventory.ini for Data Guard:
# Custom static inventory for a Data Guard deployment
[dbasm]
# The host in this group is the STANDBY node.
# 'is_standby_node=true' is mandatory.
standby-1 ansible_ssh_host=10.0.0.2 is_standby_node=true primary_ip_addr=10.0.0.1 instance_ip_addr=10.0.0.2
[primary]
# The host in this group is the PRIMARY node.
primary1 ansible_ssh_host=10.0.0.1
[all:vars]
# Common variables can be defined here
ansible_ssh_user=ansible
ansible_ssh_private_key_file=/home/ansible/.ssh/id_rsa