Remove incidental_inventory_foreman test.

pull/78012/head
Matt Clay 2 years ago
parent a4e4413cde
commit 5f5c4ef2ef

@ -183,8 +183,6 @@ stages:
test: ios/csr1000v/
- name: VyOS Python
test: vyos/1.1.8/
- name: Cloud Python
test: cloud/
- stage: Summary
condition: succeededOrFailed()
dependsOn:

@ -1,4 +0,0 @@
shippable/cloud/incidental
cloud/foreman
destructive
context/controller

@ -1,5 +0,0 @@
[defaults]
inventory = test-config.foreman.yaml
[inventory]
enable_plugins = foreman

@ -1,35 +0,0 @@
---
- hosts: localhost
vars:
foreman_stub_host: "{{ lookup('env', 'FOREMAN_HOST') }}"
foreman_stub_port: "{{ lookup('env', 'FOREMAN_PORT') }}"
foreman_stub_api_path: /api/v2
cached_hosts_key: "http://{{ foreman_stub_host }}:{{ foreman_stub_port }}{{ foreman_stub_api_path }}/hosts"
tasks:
- name: make sure jmespath is installed
pip:
name: jmespath
- name: verify a cache file was created
find:
path:
- ./foreman_cache
register: matching_files
- assert:
that:
- matching_files.matched == 1
- name: read the cached inventory
set_fact:
contents: "{{ lookup('file', matching_files.files.0.path) }}"
- name: extract all the host names
set_fact:
cached_hosts: "{{ contents[cached_hosts_key] | json_query('[*].name') }}"
- assert:
that:
"'{{ item }}' in cached_hosts"
loop:
- "v6.example-780.com"
- "c4.j1.y5.example-487.com"

@ -1,50 +0,0 @@
#!/usr/bin/env bash
[[ -n "$DEBUG" || -n "$ANSIBLE_DEBUG" ]] && set -x
set -euo pipefail
export ANSIBLE_INVENTORY
export ANSIBLE_PYTHON_INTERPRETER
unset ANSIBLE_INVENTORY
unset ANSIBLE_PYTHON_INTERPRETER
export ANSIBLE_CONFIG=ansible.cfg
export FOREMAN_HOST="${FOREMAN_HOST:-localhost}"
export FOREMAN_PORT="${FOREMAN_PORT:-8080}"
FOREMAN_CONFIG=test-config.foreman.yaml
# Set inventory caching environment variables to populate a jsonfile cache
export ANSIBLE_INVENTORY_CACHE=True
export ANSIBLE_INVENTORY_CACHE_PLUGIN=jsonfile
export ANSIBLE_INVENTORY_CACHE_CONNECTION=./foreman_cache
# flag for checking whether cleanup has already fired
_is_clean=
function _cleanup() {
[[ -n "$_is_clean" ]] && return # don't double-clean
echo Cleanup: removing $FOREMAN_CONFIG...
rm -vf "$FOREMAN_CONFIG"
unset ANSIBLE_CONFIG
unset FOREMAN_HOST
unset FOREMAN_PORT
unset FOREMAN_CONFIG
_is_clean=1
}
trap _cleanup INT TERM EXIT
cat > "$FOREMAN_CONFIG" <<FOREMAN_YAML
plugin: foreman
url: http://${FOREMAN_HOST}:${FOREMAN_PORT}
user: ansible-tester
password: secure
validate_certs: False
FOREMAN_YAML
ansible-playbook test_foreman_inventory.yml --connection=local -e 'ansible_python_interpreter={{ ansible_playbook_python }}' "$@"
ansible-playbook inspect_cache.yml --connection=local -e 'ansible_python_interpreter={{ ansible_playbook_python }}' "$@"
# remove inventory cache
rm -r ./foreman_cache

@ -1,59 +0,0 @@
---
- hosts: localhost
vars:
foreman_stub_host: "{{ lookup('env', 'FOREMAN_HOST') }}"
foreman_stub_port: "{{ lookup('env', 'FOREMAN_PORT') }}"
foreman_stub_api_path: /api/v2
foreman_stub_host_uri: "http://{{ foreman_stub_host }}:{{ foreman_stub_port }}"
foreman_stub_api_uri: "{{ foreman_stub_host_uri }}{{ foreman_stub_api_path }}"
foreman_stub_heartbeat_uri: "{{ foreman_stub_host_uri }}/ping"
tasks:
- debug:
msg: >-
Foreman host: {{ foreman_stub_host }} |
Foreman port: {{ foreman_stub_port }} |
API path: {{ foreman_stub_api_path }} |
Foreman API URL: {{ foreman_stub_api_uri }}
- name: Wait for Foreman API stub to come up online
wait_for:
host: "{{ foreman_stub_host }}"
port: "{{ foreman_stub_port }}"
state: started
# smoke test that flask app is serving
- name: Smoke test HTTP response from Foreman stub
uri:
url: "{{ foreman_stub_heartbeat_uri }}"
return_content: yes
register: heartbeat_resp
failed_when: >
heartbeat_resp.json.status != 'ok' or heartbeat_resp.json.response != 'pong'
#### Testing start
- name: >
Check that there are 'foreman_pgagne_sats' and 'foreman_base'
groups present in inventory
assert:
that: >
'{{ item }}' in groups
with_items:
- foreman_pgagne_sats
- foreman_base
- name: Check that host are in appropriate groups
assert:
that: >
'{{ item.key }}' in groups['{{ item.value }}']
with_dict:
v6.example-780.com: foreman_base
c4.j1.y5.example-487.com: ungrouped
- name: Check host UUIDs
assert:
that: >
hostvars['{{ item.key }}']['foreman_subscription_facet_attributes']['uuid'] == '{{ item.value }}'
with_dict:
v6.example-780.com: 2c72fa49-995a-4bbf-bda0-684c7048ad9f
c4.j1.y5.example-487.com: 0a494b6e-7e90-4ed2-8edc-43a41436a242
#### Testing end

@ -1,296 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2016 Guido Günther <agx@sigxcpu.org>, Daniel Lobato Garcia <dlobatog@redhat.com>
# Copyright (c) 2018 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: foreman
plugin_type: inventory
short_description: foreman inventory source
version_added: "2.6"
requirements:
- requests >= 1.1
description:
- Get inventory hosts from the foreman service.
- "Uses a configuration file as an inventory source, it must end in ``.foreman.yml`` or ``.foreman.yaml`` and has a ``plugin: foreman`` entry."
extends_documentation_fragment:
- inventory_cache
- constructed
options:
plugin:
description: the name of this plugin, it should always be set to 'foreman' for this plugin to recognize it as it's own.
required: True
choices: ['foreman']
url:
description: url to foreman
default: 'http://localhost:3000'
env:
- name: FOREMAN_SERVER
version_added: "2.8"
user:
description: foreman authentication user
required: True
env:
- name: FOREMAN_USER
version_added: "2.8"
password:
description: foreman authentication password
required: True
env:
- name: FOREMAN_PASSWORD
version_added: "2.8"
validate_certs:
description: verify SSL certificate if using https
type: boolean
default: False
group_prefix:
description: prefix to apply to foreman groups
default: foreman_
vars_prefix:
description: prefix to apply to host variables, does not include facts nor params
default: foreman_
want_facts:
description: Toggle, if True the plugin will retrieve host facts from the server
type: boolean
default: False
want_params:
description: Toggle, if true the inventory will retrieve 'all_parameters' information as host vars
type: boolean
default: False
want_hostcollections:
description: Toggle, if true the plugin will create Ansible groups for host collections
type: boolean
default: False
version_added: '2.10'
want_ansible_ssh_host:
description: Toggle, if true the plugin will populate the ansible_ssh_host variable to explicitly specify the connection target
type: boolean
default: False
version_added: '2.10'
'''
EXAMPLES = '''
# my.foreman.yml
plugin: foreman
url: http://localhost:2222
user: ansible-tester
password: secure
validate_certs: False
'''
from collections.abc import MutableMapping
from ansible.module_utils.compat.version import LooseVersion
from ansible.errors import AnsibleError
from ansible.module_utils._text import to_bytes, to_native, to_text
from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable, to_safe_group_name, Constructable
# 3rd party imports
try:
import requests
if LooseVersion(requests.__version__) < LooseVersion('1.1.0'):
raise ImportError
except ImportError:
raise AnsibleError('This script requires python-requests 1.1 as a minimum version')
from requests.auth import HTTPBasicAuth
class InventoryModule(BaseInventoryPlugin, Cacheable, Constructable):
''' Host inventory parser for ansible using foreman as source. '''
NAME = 'foreman'
def __init__(self):
super(InventoryModule, self).__init__()
# from config
self.foreman_url = None
self.session = None
self.cache_key = None
self.use_cache = None
def verify_file(self, path):
valid = False
if super(InventoryModule, self).verify_file(path):
if path.endswith(('foreman.yaml', 'foreman.yml')):
valid = True
else:
self.display.vvv('Skipping due to inventory source not ending in "foreman.yaml" nor "foreman.yml"')
return valid
def _get_session(self):
if not self.session:
self.session = requests.session()
self.session.auth = HTTPBasicAuth(self.get_option('user'), to_bytes(self.get_option('password')))
self.session.verify = self.get_option('validate_certs')
return self.session
def _get_json(self, url, ignore_errors=None):
if not self.use_cache or url not in self._cache.get(self.cache_key, {}):
if self.cache_key not in self._cache:
self._cache[self.cache_key] = {url: ''}
results = []
s = self._get_session()
params = {'page': 1, 'per_page': 250}
while True:
ret = s.get(url, params=params)
if ignore_errors and ret.status_code in ignore_errors:
break
ret.raise_for_status()
json = ret.json()
# process results
# FIXME: This assumes 'return type' matches a specific query,
# it will break if we expand the queries and they dont have different types
if 'results' not in json:
# /hosts/:id dos not have a 'results' key
results = json
break
elif isinstance(json['results'], MutableMapping):
# /facts are returned as dict in 'results'
results = json['results']
break
else:
# /hosts 's 'results' is a list of all hosts, returned is paginated
results = results + json['results']
# check for end of paging
if len(results) >= json['subtotal']:
break
if len(json['results']) == 0:
self.display.warning("Did not make any progress during loop. expected %d got %d" % (json['subtotal'], len(results)))
break
# get next page
params['page'] += 1
self._cache[self.cache_key][url] = results
return self._cache[self.cache_key][url]
def _get_hosts(self):
return self._get_json("%s/api/v2/hosts" % self.foreman_url)
def _get_all_params_by_id(self, hid):
url = "%s/api/v2/hosts/%s" % (self.foreman_url, hid)
ret = self._get_json(url, [404])
if not ret or not isinstance(ret, MutableMapping) or not ret.get('all_parameters', False):
return {}
return ret.get('all_parameters')
def _get_facts_by_id(self, hid):
url = "%s/api/v2/hosts/%s/facts" % (self.foreman_url, hid)
return self._get_json(url)
def _get_host_data_by_id(self, hid):
url = "%s/api/v2/hosts/%s" % (self.foreman_url, hid)
return self._get_json(url)
def _get_facts(self, host):
"""Fetch all host facts of the host"""
ret = self._get_facts_by_id(host['id'])
if len(ret.values()) == 0:
facts = {}
elif len(ret.values()) == 1:
facts = list(ret.values())[0]
else:
raise ValueError("More than one set of facts returned for '%s'" % host)
return facts
def _populate(self):
for host in self._get_hosts():
if host.get('name'):
host_name = self.inventory.add_host(host['name'])
# create directly mapped groups
group_name = host.get('hostgroup_title', host.get('hostgroup_name'))
if group_name:
group_name = to_safe_group_name('%s%s' % (self.get_option('group_prefix'), group_name.lower().replace(" ", "")))
group_name = self.inventory.add_group(group_name)
self.inventory.add_child(group_name, host_name)
# set host vars from host info
try:
for k, v in host.items():
if k not in ('name', 'hostgroup_title', 'hostgroup_name'):
try:
self.inventory.set_variable(host_name, self.get_option('vars_prefix') + k, v)
except ValueError as e:
self.display.warning("Could not set host info hostvar for %s, skipping %s: %s" % (host, k, to_text(e)))
except ValueError as e:
self.display.warning("Could not get host info for %s, skipping: %s" % (host_name, to_text(e)))
# set host vars from params
if self.get_option('want_params'):
for p in self._get_all_params_by_id(host['id']):
try:
self.inventory.set_variable(host_name, p['name'], p['value'])
except ValueError as e:
self.display.warning("Could not set hostvar %s to '%s' for the '%s' host, skipping: %s" %
(p['name'], to_native(p['value']), host, to_native(e)))
# set host vars from facts
if self.get_option('want_facts'):
self.inventory.set_variable(host_name, 'foreman_facts', self._get_facts(host))
# create group for host collections
if self.get_option('want_hostcollections'):
host_data = self._get_host_data_by_id(host['id'])
hostcollections = host_data.get('host_collections')
if hostcollections:
# Create Ansible groups for host collections
for hostcollection in hostcollections:
try:
hostcollection_group = to_safe_group_name('%shostcollection_%s' % (self.get_option('group_prefix'),
hostcollection['name'].lower().replace(" ", "")))
hostcollection_group = self.inventory.add_group(hostcollection_group)
self.inventory.add_child(hostcollection_group, host_name)
except ValueError as e:
self.display.warning("Could not create groups for host collections for %s, skipping: %s" % (host_name, to_text(e)))
# put ansible_ssh_host as hostvar
if self.get_option('want_ansible_ssh_host'):
for key in ('ip', 'ipv4', 'ipv6'):
if host.get(key):
try:
self.inventory.set_variable(host_name, 'ansible_ssh_host', host[key])
break
except ValueError as e:
self.display.warning("Could not set hostvar ansible_ssh_host to '%s' for the '%s' host, skipping: %s" %
(host[key], host_name, to_text(e)))
strict = self.get_option('strict')
hostvars = self.inventory.get_host(host_name).get_vars()
self._set_composite_vars(self.get_option('compose'), hostvars, host_name, strict)
self._add_host_to_composed_groups(self.get_option('groups'), hostvars, host_name, strict)
self._add_host_to_keyed_groups(self.get_option('keyed_groups'), hostvars, host_name, strict)
def parse(self, inventory, loader, path, cache=True):
super(InventoryModule, self).parse(inventory, loader, path)
# read config from file, this sets 'options'
self._read_config_data(path)
# get connection host
self.foreman_url = self.get_option('url')
self.cache_key = self.get_cache_key(path)
self.use_cache = cache and self.get_option('cache')
# actually populate inventory
self._populate()

@ -1,40 +0,0 @@
#!/usr/bin/env bash
set -o pipefail -eux
declare -a args
IFS='/:' read -ra args <<< "$1"
cloud="${args[0]}"
python_version="${args[1]}"
target="shippable/${cloud}/incidental/"
stage="${S:-prod}"
# python versions to test in order
# all versions run full tests
python_versions=(
2.7
3.6
)
if [ "${python_version}" ]; then
# limit tests to a single python version
python_versions=("${python_version}")
fi
for python_version in "${python_versions[@]}"; do
# terminate remote instances on the final python version tested
if [ "${python_version}" = "${python_versions[-1]}" ]; then
terminate="always"
else
terminate="never"
fi
# shellcheck disable=SC2086
ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
--remote-terminate "${terminate}" \
--remote-stage "${stage}" \
--docker --python "${python_version}"
done
Loading…
Cancel
Save