fix tests for new inv plugin behavior

* Enforce plugin:
This commit is contained in:
Chris Meyers
2020-07-28 13:14:43 -04:00
committed by Ryan Petrello
parent a8a47f314e
commit 34adbe6028
15 changed files with 111 additions and 417 deletions

View File

@@ -7,6 +7,7 @@ import time
import logging import logging
import re import re
import copy import copy
import json
import os.path import os.path
from urllib.parse import urljoin from urllib.parse import urljoin
import yaml import yaml
@@ -1157,6 +1158,20 @@ class InventorySource(UnifiedJobTemplate, InventorySourceOptions, CustomVirtualE
raise ValidationError(_("Cannot set source_path if not SCM type.")) raise ValidationError(_("Cannot set source_path if not SCM type."))
return self.source_path return self.source_path
def clean_source_vars(self):
injector = self.injectors.get(self.source)
source_vars = dict(self.source_vars_dict) # make a copy
if injector and self.source_vars_dict.get('plugin', '') != injector.get_proper_name():
source_vars['plugin'] = injector.get_proper_name()
elif not injector:
source_vars = dict(self.source_vars_dict) # make a copy
collection_pattern = re.compile("^(.+)\.(.+)\.(.+)$") # noqa
if 'plugin' not in source_vars:
raise ValidationError(_("plugin: must be present and of the form namespace.collection.inv_plugin"))
elif not bool(collection_pattern.match(source_vars['plugin'])):
raise ValidationError(_("plugin: must be of the form namespace.collection.inv_plugin"))
return json.dumps(source_vars)
''' '''
RelatedJobsMixin RelatedJobsMixin
''' '''
@@ -1344,6 +1359,12 @@ class PluginFileInjector(object):
# This is InventoryOptions instance, could be source or inventory update # This is InventoryOptions instance, could be source or inventory update
self.ansible_version = ansible_version self.ansible_version = ansible_version
@classmethod
def get_proper_name(cls):
if cls.plugin_name is None:
return None
return f'{cls.namespace}.{cls.collection}.{cls.plugin_name}'
@property @property
def filename(self): def filename(self):
"""Inventory filename for using the inventory plugin """Inventory filename for using the inventory plugin

View File

@@ -1,43 +0,0 @@
conditional_groups:
azure: true
default_host_filters: []
exclude_host_filters:
- resource_group not in ['foo_resources', 'bar_resources']
- '"Creator" not in tags.keys()'
- tags["Creator"] != "jmarshall"
- '"peanutbutter" not in tags.keys()'
- tags["peanutbutter"] != "jelly"
- location not in ['southcentralus', 'westus']
fail_on_template_errors: false
hostvar_expressions:
ansible_host: private_ipv4_addresses[0]
computer_name: name
private_ip: private_ipv4_addresses[0] if private_ipv4_addresses else None
provisioning_state: provisioning_state | title
public_ip: public_ipv4_addresses[0] if public_ipv4_addresses else None
public_ip_id: public_ip_id if public_ip_id is defined else None
public_ip_name: public_ip_name if public_ip_name is defined else None
tags: tags if tags else None
type: resource_type
keyed_groups:
- key: location
prefix: ''
separator: ''
- key: tags.keys() | list if tags else []
prefix: ''
separator: ''
- key: security_group
prefix: ''
separator: ''
- key: resource_group
prefix: ''
separator: ''
- key: os_disk.operating_system_type
prefix: ''
separator: ''
- key: dict(tags.keys() | map("regex_replace", "^(.*)$", "\1_") | list | zip(tags.values() | list)) if tags else []
prefix: ''
separator: ''
plain_host_names: true
plugin: azure.azcollection.azure_rm
use_contrib_script_compatible_sanitization: true

View File

@@ -1,81 +0,0 @@
boto_profile: /tmp/my_boto_stuff
compose:
ansible_host: public_dns_name
ec2_account_id: owner_id
ec2_ami_launch_index: ami_launch_index | string
ec2_architecture: architecture
ec2_block_devices: dict(block_device_mappings | map(attribute='device_name') | list | zip(block_device_mappings | map(attribute='ebs.volume_id') | list))
ec2_client_token: client_token
ec2_dns_name: public_dns_name
ec2_ebs_optimized: ebs_optimized
ec2_eventsSet: events | default("")
ec2_group_name: placement.group_name
ec2_hypervisor: hypervisor
ec2_id: instance_id
ec2_image_id: image_id
ec2_instance_profile: iam_instance_profile | default("")
ec2_instance_type: instance_type
ec2_ip_address: public_ip_address
ec2_kernel: kernel_id | default("")
ec2_key_name: key_name
ec2_launch_time: launch_time | regex_replace(" ", "T") | regex_replace("(\+)(\d\d):(\d)(\d)$", ".\g<2>\g<3>Z")
ec2_monitored: monitoring.state in ['enabled', 'pending']
ec2_monitoring_state: monitoring.state
ec2_persistent: persistent | default(false)
ec2_placement: placement.availability_zone
ec2_platform: platform | default("")
ec2_private_dns_name: private_dns_name
ec2_private_ip_address: private_ip_address
ec2_public_dns_name: public_dns_name
ec2_ramdisk: ramdisk_id | default("")
ec2_reason: state_transition_reason
ec2_region: placement.region
ec2_requester_id: requester_id | default("")
ec2_root_device_name: root_device_name
ec2_root_device_type: root_device_type
ec2_security_group_ids: security_groups | map(attribute='group_id') | list | join(',')
ec2_security_group_names: security_groups | map(attribute='group_name') | list | join(',')
ec2_sourceDestCheck: source_dest_check | default(false) | lower | string
ec2_spot_instance_request_id: spot_instance_request_id | default("")
ec2_state: state.name
ec2_state_code: state.code
ec2_state_reason: state_reason.message if state_reason is defined else ""
ec2_subnet_id: subnet_id | default("")
ec2_tag_Name: tags.Name
ec2_virtualization_type: virtualization_type
ec2_vpc_id: vpc_id | default("")
filters:
instance-state-name:
- running
groups:
ec2: true
hostnames:
- dns-name
iam_role_arn: arn:aws:iam::123456789012:role/test-role
keyed_groups:
- key: placement.availability_zone
parent_group: zones
prefix: ''
separator: ''
- key: instance_type | regex_replace("[^A-Za-z0-9\_]", "_")
parent_group: types
prefix: type
- key: placement.region
parent_group: regions
prefix: ''
separator: ''
- key: dict(tags.keys() | map("regex_replace", "[^A-Za-z0-9\_]", "_") | list | zip(tags.values() | map("regex_replace", "[^A-Za-z0-9\_]", "_") | list))
parent_group: tags
prefix: tag
- key: tags.keys() | map("regex_replace", "[^A-Za-z0-9\_]", "_") | list
parent_group: tags
prefix: tag
- key: placement.availability_zone
parent_group: '{{ placement.region }}'
prefix: ''
separator: ''
plugin: amazon.aws.aws_ec2
regions:
- us-east-2
- ap-south-1
use_contrib_script_compatible_sanitization: true

View File

@@ -1,50 +0,0 @@
auth_kind: serviceaccount
compose:
ansible_ssh_host: networkInterfaces[0].accessConfigs[0].natIP | default(networkInterfaces[0].networkIP)
gce_description: description if description else None
gce_id: id
gce_image: image
gce_machine_type: machineType
gce_metadata: metadata.get("items", []) | items2dict(key_name="key", value_name="value")
gce_name: name
gce_network: networkInterfaces[0].network.name
gce_private_ip: networkInterfaces[0].networkIP
gce_public_ip: networkInterfaces[0].accessConfigs[0].natIP | default(None)
gce_status: status
gce_subnetwork: networkInterfaces[0].subnetwork.name
gce_tags: tags.get("items", [])
gce_zone: zone
hostnames:
- name
- public_ip
- private_ip
keyed_groups:
- key: gce_subnetwork
prefix: network
- key: gce_private_ip
prefix: ''
separator: ''
- key: gce_public_ip
prefix: ''
separator: ''
- key: machineType
prefix: ''
separator: ''
- key: zone
prefix: ''
separator: ''
- key: gce_tags
prefix: tag
- key: status | lower
prefix: status
- key: image
prefix: ''
separator: ''
plugin: google.cloud.gcp_compute
projects:
- fooo
retrieve_image_info: true
use_contrib_script_compatible_sanitization: true
zones:
- us-east4-a
- us-west1-b

View File

@@ -1,7 +1,3 @@
ansible:
expand_hostvars: true
fail_on_errors: true
use_hostnames: false
clouds: clouds:
devstack: devstack:
auth: auth:
@@ -11,5 +7,5 @@ clouds:
project_domain_name: fooo project_domain_name: fooo
project_name: fooo project_name: fooo
username: fooo username: fooo
private: false private: true
verify: false verify: false

View File

@@ -1,4 +0,0 @@
expand_hostvars: true
fail_on_errors: true
inventory_hostname: uuid
plugin: openstack.cloud.openstack

View File

@@ -1,20 +0,0 @@
base_source_var: value_of_var
compose:
ansible_host: (devices.values() | list)[0][0] if devices else None
groups:
dev: '"dev" in tags'
keyed_groups:
- key: cluster
prefix: cluster
separator: _
- key: status
prefix: status
separator: _
- key: tags
prefix: tag
separator: _
ovirt_hostname_preference:
- name
- fqdn
ovirt_insecure: false
plugin: ovirt.ovirt.ovirt

View File

@@ -1,30 +0,0 @@
base_source_var: value_of_var
compose:
ansible_ssh_host: foreman['ip6'] | default(foreman['ip'], true)
group_prefix: foo_group_prefix
keyed_groups:
- key: foreman['environment_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_') | regex_replace('none', '')
prefix: foo_group_prefixenvironment_
separator: ''
- key: foreman['location_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_')
prefix: foo_group_prefixlocation_
separator: ''
- key: foreman['organization_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_')
prefix: foo_group_prefixorganization_
separator: ''
- key: foreman['content_facet_attributes']['lifecycle_environment_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_')
prefix: foo_group_prefixlifecycle_environment_
separator: ''
- key: foreman['content_facet_attributes']['content_view_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9_]', '_')
prefix: foo_group_prefixcontent_view_
separator: ''
- key: '"%s-%s-%s" | format(app, tier, color)'
separator: ''
- key: '"%s-%s" | format(app, color)'
separator: ''
legacy_hostvars: true
plugin: theforeman.foreman.foreman
validate_certs: false
want_facts: true
want_hostcollections: true
want_params: true

View File

@@ -1,3 +0,0 @@
include_metadata: true
inventory_id: 42
plugin: awx.awx.tower

View File

@@ -1,55 +0,0 @@
compose:
ansible_host: guest.ipAddress
ansible_ssh_host: guest.ipAddress
ansible_uuid: 99999999 | random | to_uuid
availablefield: availableField
configissue: configIssue
configstatus: configStatus
customvalue: customValue
effectiverole: effectiveRole
guestheartbeatstatus: guestHeartbeatStatus
layoutex: layoutEx
overallstatus: overallStatus
parentvapp: parentVApp
recenttask: recentTask
resourcepool: resourcePool
rootsnapshot: rootSnapshot
triggeredalarmstate: triggeredAlarmState
filters:
- config.zoo == "DC0_H0_VM0"
hostnames:
- config.foo
keyed_groups:
- key: config.asdf
prefix: ''
separator: ''
plugin: community.vmware.vmware_vm_inventory
properties:
- availableField
- configIssue
- configStatus
- customValue
- datastore
- effectiveRole
- guestHeartbeatStatus
- layout
- layoutEx
- name
- network
- overallStatus
- parentVApp
- permission
- recentTask
- resourcePool
- rootSnapshot
- snapshot
- triggeredAlarmState
- value
- capability
- config
- guest
- runtime
- storage
- summary
strict: false
with_nested_properties: true

View File

@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import pytest import pytest
import json
from unittest import mock from unittest import mock
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
@@ -8,8 +9,6 @@ from awx.api.versioning import reverse
from awx.main.models import InventorySource, Inventory, ActivityStream from awx.main.models import InventorySource, Inventory, ActivityStream
import json
@pytest.fixture @pytest.fixture
def scm_inventory(inventory, project): def scm_inventory(inventory, project):
@@ -457,6 +456,56 @@ def test_inventory_source_vars_prohibition(post, inventory, admin_user):
assert 'FOOBAR' in r.data['source_vars'][0] assert 'FOOBAR' in r.data['source_vars'][0]
@pytest.mark.django_db
@pytest.mark.parametrize('source,source_var_actual,source_var_expected,description', [
('ec2', {'plugin': 'blah'}, {'plugin': 'amazon.aws.aws_ec2'}, 'source plugin mismatch'),
('ec2', {'plugin': 'amazon.aws.aws_ec2'}, {'plugin': 'amazon.aws.aws_ec2'}, 'valid plugin'),
])
def test_inventory_source_vars_source_plugin_ok(post, inventory, admin_user, source, source_var_actual, source_var_expected, description):
r = post(reverse('api:inventory_source_list'),
{'name': 'new inv src', 'source_vars': json.dumps(source_var_actual), 'inventory': inventory.pk, 'source': source},
admin_user, expect=201)
assert r.data['source_vars'] == json.dumps(source_var_expected)
@pytest.mark.django_db
@pytest.mark.parametrize('source_var_actual,description', [
({'plugin': 'namespace.collection.script'}, 'valid scm user plugin'),
])
def test_inventory_source_vars_source_plugin_scm_ok(post, inventory, admin_user, project, source_var_actual, description):
r = post(reverse('api:inventory_source_list'),
{'name': 'new inv src',
'source_vars': json.dumps(source_var_actual),
'inventory': inventory.pk,
'source': 'scm',
'source_project': project.id,},
admin_user, expect=201)
assert r.data['source_vars'] == json.dumps(source_var_actual)
@pytest.mark.django_db
@pytest.mark.parametrize('source_var_actual,err_msg,description', [
({'foo': 'bar'}, 'plugin: must be present and of the form namespace.collection.inv_plugin', 'no plugin line'),
({'plugin': ''}, 'plugin: must be of the form namespace.collection.inv_plugin', 'blank plugin line'),
({'plugin': '.'}, 'plugin: must be of the form namespace.collection.inv_plugin', 'missing namespace, collection name, and inventory plugin'),
({'plugin': 'a.'}, 'plugin: must be of the form namespace.collection.inv_plugin', 'missing collection name and inventory plugin'),
({'plugin': 'a.b'}, 'plugin: must be of the form namespace.collection.inv_plugin', 'missing inventory plugin'),
({'plugin': 'a.b.'}, 'plugin: must be of the form namespace.collection.inv_plugin', 'missing inventory plugin'),
])
def test_inventory_source_vars_source_plugin_scm_invalid(post, inventory, admin_user, project, source_var_actual, err_msg, description):
r = post(reverse('api:inventory_source_list'),
{'name': 'new inv src',
'source_vars': json.dumps(source_var_actual),
'inventory': inventory.pk,
'source': 'scm',
'source_project': project.id,},
admin_user, expect=400)
assert err_msg in r.data['source_vars'][0]
@pytest.mark.django_db @pytest.mark.django_db
@pytest.mark.parametrize('role,expect', [ @pytest.mark.parametrize('role,expect', [
('admin_role', 200), ('admin_role', 200),
@@ -522,7 +571,8 @@ class TestInventorySourceCredential:
data={ data={
'inventory': inventory.pk, 'name': 'fobar', 'source': 'scm', 'inventory': inventory.pk, 'name': 'fobar', 'source': 'scm',
'source_project': project.pk, 'source_path': '', 'source_project': project.pk, 'source_path': '',
'credential': vault_credential.pk 'credential': vault_credential.pk,
'source_vars': 'plugin: a.b.c',
}, },
expect=400, expect=400,
user=admin_user user=admin_user
@@ -561,7 +611,7 @@ class TestInventorySourceCredential:
data={ data={
'inventory': inventory.pk, 'name': 'fobar', 'source': 'scm', 'inventory': inventory.pk, 'name': 'fobar', 'source': 'scm',
'source_project': project.pk, 'source_path': '', 'source_project': project.pk, 'source_path': '',
'credential': os_cred.pk 'credential': os_cred.pk, 'source_vars': 'plugin: a.b.c',
}, },
expect=201, expect=201,
user=admin_user user=admin_user
@@ -636,8 +686,14 @@ class TestControlledBySCM:
assert scm_inventory.inventory_sources.count() == 0 assert scm_inventory.inventory_sources.count() == 0
def test_adding_inv_src_ok(self, post, scm_inventory, project, admin_user): def test_adding_inv_src_ok(self, post, scm_inventory, project, admin_user):
post(reverse('api:inventory_inventory_sources_list', kwargs={'pk': scm_inventory.id}), post(reverse('api:inventory_inventory_sources_list',
{'name': 'new inv src', 'source_project': project.pk, 'update_on_project_update': False, 'source': 'scm', 'overwrite_vars': True}, kwargs={'pk': scm_inventory.id}),
{'name': 'new inv src',
'source_project': project.pk,
'update_on_project_update': False,
'source': 'scm',
'overwrite_vars': True,
'source_vars': 'plugin: a.b.c'},
admin_user, expect=201) admin_user, expect=201)
def test_adding_inv_src_prohibited(self, post, scm_inventory, project, admin_user): def test_adding_inv_src_prohibited(self, post, scm_inventory, project, admin_user):
@@ -657,7 +713,7 @@ class TestControlledBySCM:
def test_adding_inv_src_without_proj_access_prohibited(self, post, project, inventory, rando): def test_adding_inv_src_without_proj_access_prohibited(self, post, project, inventory, rando):
inventory.admin_role.members.add(rando) inventory.admin_role.members.add(rando)
post(reverse('api:inventory_inventory_sources_list', kwargs={'pk': inventory.id}), post(reverse('api:inventory_inventory_sources_list', kwargs={'pk': inventory.id}),
{'name': 'new inv src', 'source_project': project.pk, 'source': 'scm', 'overwrite_vars': True}, {'name': 'new inv src', 'source_project': project.pk, 'source': 'scm', 'overwrite_vars': True, 'source_vars': 'plugin: a.b.c'},
rando, expect=403) rando, expect=403)

View File

@@ -2,7 +2,6 @@
import pytest import pytest
from unittest import mock from unittest import mock
import json
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
@@ -259,30 +258,19 @@ class TestInventorySourceInjectors:
injector = InventorySource.injectors[source]('2.7.7') injector = InventorySource.injectors[source]('2.7.7')
assert injector.filename == filename assert injector.filename == filename
def test_group_by_azure(self): @pytest.mark.parametrize('source,proper_name', [
injector = InventorySource.injectors['azure_rm']('2.9') ('ec2', 'amazon.aws.aws_ec2'),
inv_src = InventorySource( ('openstack', 'openstack.cloud.openstack'),
name='azure source', source='azure_rm', ('gce', 'google.cloud.gcp_compute'),
source_vars={'group_by_os_family': True} ('azure_rm', 'azure.azcollection.azure_rm'),
) ('vmware', 'community.vmware.vmware_vm_inventory'),
group_by_on = injector.inventory_as_dict(inv_src, '/tmp/foo') ('rhv', 'ovirt.ovirt.ovirt'),
# suspicious, yes, that is just what the script did ('satellite6', 'theforeman.foreman.foreman'),
expected_groups = 6 ('tower', 'awx.awx.tower'),
assert len(group_by_on['keyed_groups']) == expected_groups ])
inv_src.source_vars = json.dumps({'group_by_os_family': False}) def test_plugin_proper_names(self, source, proper_name):
group_by_off = injector.inventory_as_dict(inv_src, '/tmp/foo') injector = InventorySource.injectors[source]('2.9')
# much better, everyone should turn off the flag and live in the future assert injector.get_proper_name() == proper_name
assert len(group_by_off['keyed_groups']) == expected_groups - 1
def test_tower_plugin_named_url(self):
injector = InventorySource.injectors['tower']('2.9')
inv_src = InventorySource(
name='my tower source', source='tower',
# named URL pattern "inventory++organization"
instance_filters='Designer hair 읰++Cosmetic_products䵆'
)
result = injector.inventory_as_dict(inv_src, '/tmp/foo')
assert result['inventory_id'] == 'Designer%20hair%20%EC%9D%B0++Cosmetic_products%E4%B5%86'
@pytest.mark.django_db @pytest.mark.django_db

View File

@@ -14,69 +14,6 @@ from django.conf import settings
DATA = os.path.join(os.path.dirname(data.__file__), 'inventory') DATA = os.path.join(os.path.dirname(data.__file__), 'inventory')
TEST_SOURCE_FIELDS = {
'vmware': {
'instance_filters': '{{ config.name == "only_my_server" }},{{ somevar == "bar"}}',
'group_by': 'fouo'
},
'ec2': {
'instance_filters': 'foobaa',
# group_by selected to capture some non-trivial cross-interactions
'group_by': 'availability_zone,instance_type,tag_keys,region',
'source_regions': 'us-east-2,ap-south-1'
},
'gce': {
'source_regions': 'us-east4-a,us-west1-b' # surfaced as env var
},
'azure_rm': {
'source_regions': 'southcentralus,westus'
},
'tower': {
'instance_filters': '42'
}
}
INI_TEST_VARS = {
'ec2': {
'boto_profile': '/tmp/my_boto_stuff',
'iam_role_arn': 'arn:aws:iam::123456789012:role/test-role',
'hostname_variable': 'public_dns_name',
'destination_variable': 'public_dns_name'
},
'gce': {},
'openstack': {
'private': False,
'use_hostnames': False,
'expand_hostvars': True,
'fail_on_errors': True
},
'tower': {}, # there are none
'vmware': {
'alias_pattern': "{{ config.foo }}",
'host_filters': '{{ config.zoo == "DC0_H0_VM0" }}',
'groupby_patterns': "{{ config.asdf }}",
# setting VMWARE_VALIDATE_CERTS is duplicated with env var
},
'azure_rm': {
'use_private_ip': True,
'resource_groups': 'foo_resources,bar_resources',
'tags': 'Creator:jmarshall, peanutbutter:jelly'
},
'satellite6': {
'satellite6_group_patterns': '["{app}-{tier}-{color}", "{app}-{color}"]',
'satellite6_group_prefix': 'foo_group_prefix',
'satellite6_want_hostcollections': True,
'satellite6_want_ansible_ssh_host': True,
'satellite6_want_facts': True
},
'rhv': { # options specific to the plugin
'ovirt_insecure': False,
'groups': {
'dev': '"dev" in tags'
}
}
}
def generate_fake_var(element): def generate_fake_var(element):
"""Given a credential type field element, makes up something acceptable. """Given a credential type field element, makes up something acceptable.
@@ -245,25 +182,21 @@ def create_reference_data(source_dir, env, content):
@pytest.mark.django_db @pytest.mark.django_db
@pytest.mark.parametrize('this_kind', CLOUD_PROVIDERS) @pytest.mark.parametrize('this_kind', CLOUD_PROVIDERS)
def test_inventory_update_injected_content(this_kind, inventory, fake_credential_factory): def test_inventory_update_injected_content(this_kind, inventory, fake_credential_factory):
injector = InventorySource.injectors[this_kind]
if injector.plugin_name is None:
pytest.skip('Use of inventory plugin is not enabled for this source')
src_vars = dict(base_source_var='value_of_var') src_vars = dict(base_source_var='value_of_var')
if this_kind in INI_TEST_VARS: src_vars['plugin'] = injector.get_proper_name()
src_vars.update(INI_TEST_VARS[this_kind])
extra_kwargs = {}
if this_kind in TEST_SOURCE_FIELDS:
extra_kwargs.update(TEST_SOURCE_FIELDS[this_kind])
inventory_source = InventorySource.objects.create( inventory_source = InventorySource.objects.create(
inventory=inventory, inventory=inventory,
source=this_kind, source=this_kind,
source_vars=src_vars, source_vars=src_vars,
**extra_kwargs
) )
inventory_source.credentials.add(fake_credential_factory(this_kind)) inventory_source.credentials.add(fake_credential_factory(this_kind))
inventory_update = inventory_source.create_unified_job() inventory_update = inventory_source.create_unified_job()
task = RunInventoryUpdate() task = RunInventoryUpdate()
if InventorySource.injectors[this_kind].plugin_name is None:
pytest.skip('Use of inventory plugin is not enabled for this source')
def substitute_run(envvars=None, **_kw): def substitute_run(envvars=None, **_kw):
"""This method will replace run_pexpect """This method will replace run_pexpect
instead of running, it will read the private data directory contents instead of running, it will read the private data directory contents
@@ -274,6 +207,12 @@ def test_inventory_update_injected_content(this_kind, inventory, fake_credential
assert envvars.pop('ANSIBLE_INVENTORY_ENABLED') == 'auto' assert envvars.pop('ANSIBLE_INVENTORY_ENABLED') == 'auto'
set_files = bool(os.getenv("MAKE_INVENTORY_REFERENCE_FILES", 'false').lower()[0] not in ['f', '0']) set_files = bool(os.getenv("MAKE_INVENTORY_REFERENCE_FILES", 'false').lower()[0] not in ['f', '0'])
env, content = read_content(private_data_dir, envvars, inventory_update) env, content = read_content(private_data_dir, envvars, inventory_update)
# Assert inventory plugin inventory file is in private_data_dir
inventory_filename = InventorySource.injectors[inventory_update.source]('2.9').filename
assert len([True for k in content.keys() if k.endswith(inventory_filename)]) > 0, \
f"'{inventory_filename}' file not found in inventory update runtime files {content.keys()}"
env.pop('ANSIBLE_COLLECTIONS_PATHS', None) # collection paths not relevant to this test env.pop('ANSIBLE_COLLECTIONS_PATHS', None) # collection paths not relevant to this test
base_dir = os.path.join(DATA, 'plugins') base_dir = os.path.join(DATA, 'plugins')
if not os.path.exists(base_dir): if not os.path.exists(base_dir):
@@ -283,6 +222,8 @@ def test_inventory_update_injected_content(this_kind, inventory, fake_credential
create_reference_data(source_dir, env, content) create_reference_data(source_dir, env, content)
pytest.skip('You set MAKE_INVENTORY_REFERENCE_FILES, so this created files, unset to run actual test.') pytest.skip('You set MAKE_INVENTORY_REFERENCE_FILES, so this created files, unset to run actual test.')
else: else:
source_dir = os.path.join(base_dir, this_kind) # this_kind is a global
if not os.path.exists(source_dir): if not os.path.exists(source_dir):
raise FileNotFoundError( raise FileNotFoundError(
'Maybe you never made reference files? ' 'Maybe you never made reference files? '
@@ -292,9 +233,6 @@ def test_inventory_update_injected_content(this_kind, inventory, fake_credential
expected_file_list = os.listdir(files_dir) expected_file_list = os.listdir(files_dir)
except FileNotFoundError: except FileNotFoundError:
expected_file_list = [] expected_file_list = []
assert set(expected_file_list) == set(content.keys()), (
'Inventory update runtime environment does not have expected files'
)
for f_name in expected_file_list: for f_name in expected_file_list:
with open(os.path.join(files_dir, f_name), 'r') as f: with open(os.path.join(files_dir, f_name), 'r') as f:
ref_content = f.read() ref_content = f.read()

View File

@@ -72,23 +72,6 @@ def test_invalid_kind_clean_insights_credential():
assert json.dumps(str(e.value)) == json.dumps(str([u'Assignment not allowed for Smart Inventory'])) assert json.dumps(str(e.value)) == json.dumps(str([u'Assignment not allowed for Smart Inventory']))
@pytest.mark.parametrize('source_vars,validate_certs', [
({'ssl_verify': True}, True),
({'ssl_verify': False}, False),
({'validate_certs': True}, True),
({'validate_certs': False}, False)])
def test_satellite_plugin_backwards_support_for_ssl_verify(source_vars, validate_certs):
injector = InventorySource.injectors['satellite6']('2.9')
inv_src = InventorySource(
name='satellite source', source='satellite6',
source_vars=source_vars
)
ret = injector.inventory_as_dict(inv_src, '/tmp/foo')
assert 'validate_certs' in ret
assert ret['validate_certs'] in (validate_certs, str(validate_certs))
class TestControlledBySCM(): class TestControlledBySCM():
def test_clean_source_path_valid(self): def test_clean_source_path_valid(self):
inv_src = InventorySource(source_path='/not_real/', inv_src = InventorySource(source_path='/not_real/',

View File

@@ -8,8 +8,6 @@ from datetime import timedelta
# global settings # global settings
from django.conf import global_settings from django.conf import global_settings
# ugettext lazy
from django.utils.translation import ugettext_lazy as _
# Update this module's local settings from the global settings module. # Update this module's local settings from the global settings module.
this_module = sys.modules[__name__] this_module = sys.modules[__name__]