summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSloane Hertel <shertel@redhat.com>2020-06-09 18:38:57 -0400
committerGitHub <noreply@github.com>2020-06-09 15:38:57 -0700
commit51f6d129cbb30f42c445f7e2fecba68fe02d6f85 (patch)
tree11ff79f7cc1ef9fa8ac1134ccdc65d0217b6f297
parenta862ff2d4324f871565ef5b749c6a96ad0ad767e (diff)
downloadansible-51f6d129cbb30f42c445f7e2fecba68fe02d6f85.tar.gz
support hard coded module_defaults.yml groups for collections (#69919)
* Only allow groups which were hardcoded in module_defaults.yml only load action groups from the collection if module_defaults contains a potential group for the action * Fix tests using modules that override those whitelisted in lib/ansible/config/module_defaults.yml Third party modules should not be using group/ - use the action name instead * add externalized module_defaults tests add the missing group and collections ci_complete Co-authored-by: Matt Davis <mrd@redhat.com> * changelog ci_complete * Fix import in tests ci_complete * Update with requested changes ci_complete * don't traceback since we don't validate the contents of module_defaults ci_complete Co-authored-by: Matt Davis <mrd@redhat.com>
-rw-r--r--changelogs/fragments/69919-module_defaults-groups-collections.yml3
-rw-r--r--lib/ansible/config/manager.py14
-rw-r--r--lib/ansible/config/module_defaults.yml1545
-rw-r--r--lib/ansible/executor/module_common.py43
-rw-r--r--lib/ansible/executor/task_executor.py4
-rw-r--r--lib/ansible/parsing/mod_args.py24
-rw-r--r--lib/ansible/playbook/task.py14
-rw-r--r--lib/ansible/plugins/action/gather_facts.py2
-rw-r--r--lib/ansible/plugins/action/package.py4
-rw-r--r--lib/ansible/plugins/action/service.py4
-rw-r--r--lib/ansible/plugins/loader.py4
-rw-r--r--lib/ansible/utils/collection_loader/_collection_finder.py9
-rw-r--r--test/integration/targets/incidental_aws_step_functions_state_machine/tasks/main.yml12
-rw-r--r--test/integration/targets/incidental_cloudformation/tasks/main.yml23
-rw-r--r--test/integration/targets/incidental_ec2_instance/main.yml2
-rw-r--r--test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/env_cleanup.yml18
-rw-r--r--test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/env_setup.yml16
-rw-r--r--test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/main.yml20
-rw-r--r--test/integration/targets/module_defaults/collections/ansible_collections/testns/othercoll/plugins/action/other_echoaction.py8
-rw-r--r--test/integration/targets/module_defaults/collections/ansible_collections/testns/othercoll/plugins/modules/other_echo1.py13
-rw-r--r--test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/meta/runtime.yml9
-rw-r--r--test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/echoaction.py19
-rw-r--r--test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/module_utils/echo_impl.py15
-rw-r--r--test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/modules/echo1.py13
-rw-r--r--test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/modules/echo2.py13
-rwxr-xr-xtest/integration/targets/module_defaults/runme.sh5
-rw-r--r--test/integration/targets/module_defaults/tasks/main.yml27
-rw-r--r--test/integration/targets/module_defaults/test_defaults.yml60
-rw-r--r--test/lib/ansible_test/_internal/cloud/vcenter.py2
-rw-r--r--test/sanity/ignore.txt1
-rw-r--r--test/units/plugins/action/test_gather_facts.py8
31 files changed, 341 insertions, 1613 deletions
diff --git a/changelogs/fragments/69919-module_defaults-groups-collections.yml b/changelogs/fragments/69919-module_defaults-groups-collections.yml
new file mode 100644
index 0000000000..e3feda80f8
--- /dev/null
+++ b/changelogs/fragments/69919-module_defaults-groups-collections.yml
@@ -0,0 +1,3 @@
+bugfixes:
+ - module_defaults - support short group names for content relocated to collections
+ - module_defaults - support candidate action names for relocated content
diff --git a/lib/ansible/config/manager.py b/lib/ansible/config/manager.py
index 18d2d11c95..3cbfb38d44 100644
--- a/lib/ansible/config/manager.py
+++ b/lib/ansible/config/manager.py
@@ -289,12 +289,6 @@ class ConfigManager(object):
# update constants
self.update_config_data()
- try:
- self.update_module_defaults_groups()
- except Exception as e:
- # Since this is a 2.7 preview feature, we want to have it fail as gracefully as possible when there are issues.
- sys.stderr.write('Could not load module_defaults_groups: %s: %s\n\n' % (type(e).__name__, e))
- self.module_defaults_groups = {}
def _read_config_yaml_file(self, yml_file):
# TODO: handle relative paths as relative to the directory containing the current playbook instead of CWD
@@ -525,14 +519,6 @@ class ConfigManager(object):
self._plugins[plugin_type][name] = defs
- def update_module_defaults_groups(self):
- defaults_config = self._read_config_yaml_file(
- '%s/module_defaults.yml' % os.path.join(os.path.dirname(__file__))
- )
- if defaults_config.get('version') not in ('1', '1.0', 1, 1.0):
- raise AnsibleError('module_defaults.yml has an invalid version "%s" for configuration. Could be a bad install.' % defaults_config.get('version'))
- self.module_defaults_groups = defaults_config.get('groupings', {})
-
def update_config_data(self, defs=None, configfile=None):
''' really: update constants '''
diff --git a/lib/ansible/config/module_defaults.yml b/lib/ansible/config/module_defaults.yml
deleted file mode 100644
index aff04a7668..0000000000
--- a/lib/ansible/config/module_defaults.yml
+++ /dev/null
@@ -1,1545 +0,0 @@
----
-version: '1.0'
-groupings:
- acme_account:
- - acme
- acme_account_info:
- - acme
- acme_account_facts:
- - acme
- acme_certificate:
- - acme
- acme_certificate_revoke:
- - acme
- acme_inspect:
- - acme
- aws_acm:
- - aws
- aws_acm_facts:
- - aws
- aws_acm_info:
- - aws
- aws_api_gateway:
- - aws
- aws_application_scaling_policy:
- - aws
- aws_az_facts:
- - aws
- aws_az_info:
- - aws
- aws_batch_compute_environment:
- - aws
- aws_batch_job_definition:
- - aws
- aws_batch_job_queue:
- - aws
- aws_caller_facts:
- - aws
- aws_caller_info:
- - aws
- aws_codebuild:
- - aws
- aws_codecommit:
- - aws
- aws_codepipeline:
- - aws
- aws_config_aggregation_authorization:
- - aws
- aws_config_aggregator:
- - aws
- aws_config_delivery_channel:
- - aws
- aws_config_recorder:
- - aws
- aws_config_rule:
- - aws
- aws_direct_connect_connection:
- - aws
- aws_direct_connect_gateway:
- - aws
- aws_direct_connect_link_aggregation_group:
- - aws
- aws_direct_connect_virtual_interface:
- - aws
- aws_eks_cluster:
- - aws
- aws_elasticbeanstalk_app:
- - aws
- aws_glue_connection:
- - aws
- aws_glue_job:
- - aws
- aws_inspector_target:
- - aws
- aws_kms:
- - aws
- aws_kms_facts:
- - aws
- aws_kms_info:
- - aws
- aws_region_facts:
- - aws
- aws_region_info:
- - aws
- aws_s3:
- - aws
- aws_s3_bucket_facts:
- - aws
- aws_s3_bucket_info:
- - aws
- aws_s3_cors:
- - aws
- aws_secret:
- - aws
- aws_ses_identity:
- - aws
- aws_ses_identity_policy:
- - aws
- aws_ses_rule_set:
- - aws
- aws_sgw_facts:
- - aws
- aws_sgw_info:
- - aws
- aws_ssm_parameter_store:
- - aws
- aws_step_functions_state_machine:
- - aws
- aws_step_functions_state_machine_execution:
- - aws
- aws_waf_condition:
- - aws
- aws_waf_facts:
- - aws
- aws_waf_info:
- - aws
- aws_waf_rule:
- - aws
- aws_waf_web_acl:
- - aws
- cloudformation:
- - aws
- cloudformation_exports_info:
- - aws
- cloudformation_facts:
- - aws
- cloudformation_info:
- - aws
- cloudformation_stack_set:
- - aws
- cloudfront_distribution:
- - aws
- cloudfront_facts:
- - aws
- cloudfront_info:
- - aws
- cloudfront_invalidation:
- - aws
- cloudfront_origin_access_identity:
- - aws
- cloudtrail:
- - aws
- cloudwatchevent_rule:
- - aws
- cloudwatchlogs_log_group:
- - aws
- cloudwatchlogs_log_group_facts:
- - aws
- cloudwatchlogs_log_group_info:
- - aws
- cloudwatchlogs_log_group_metric_filter:
- - aws
- cpm_plugconfig:
- - cpm
- cpm_plugcontrol:
- - cpm
- cpm_serial_port_config:
- - cpm
- cpm_serial_port_info:
- - cpm
- cpm_user:
- - cpm
- data_pipeline:
- - aws
- dms_endpoint:
- - aws
- dms_replication_subnet_group:
- - aws
- docker_compose:
- - docker
- docker_config:
- - docker
- docker_container_info:
- - docker
- docker_container:
- - docker
- docker_host_info:
- - docker
- docker_image_facts:
- - docker
- docker_image_info:
- - docker
- docker_image:
- - docker
- docker_login:
- - docker
- docker_network_info:
- - docker
- docker_network:
- - docker
- docker_node_info:
- - docker
- docker_node:
- - docker
- docker_prune:
- - docker
- docker_secret:
- - docker
- docker_service:
- - docker
- docker_swarm_info:
- - docker
- docker_swarm:
- - docker
- docker_swarm_service_info:
- - docker
- docker_swarm_service:
- - docker
- docker_volume_info:
- - docker
- docker_volume:
- - docker
- dynamodb_table:
- - aws
- dynamodb_ttl:
- - aws
- ec2:
- - aws
- ec2_ami:
- - aws
- ec2_ami_copy:
- - aws
- ec2_ami_facts:
- - aws
- ec2_ami_info:
- - aws
- ec2_asg:
- - aws
- ec2_asg_facts:
- - aws
- ec2_asg_info:
- - aws
- ec2_asg_lifecycle_hook:
- - aws
- ec2_customer_gateway:
- - aws
- ec2_customer_gateway_facts:
- - aws
- ec2_customer_gateway_info:
- - aws
- ec2_eip:
- - aws
- ec2_eip_facts:
- - aws
- ec2_eip_info:
- - aws
- ec2_elb:
- - aws
- ec2_elb_facts:
- - aws
- ec2_elb_info:
- - aws
- ec2_elb_lb:
- - aws
- ec2_eni:
- - aws
- ec2_eni_facts:
- - aws
- ec2_eni_info:
- - aws
- ec2_group:
- - aws
- ec2_group_facts:
- - aws
- ec2_group_info:
- - aws
- ec2_instance:
- - aws
- ec2_instance_facts:
- - aws
- ec2_instance_info:
- - aws
- ec2_key:
- - aws
- ec2_launch_template:
- - aws
- ec2_lc:
- - aws
- ec2_lc_facts:
- - aws
- ec2_lc_info:
- - aws
- ec2_lc_find:
- - aws
- ec2_metric_alarm:
- - aws
- ec2_placement_group:
- - aws
- ec2_placement_group_facts:
- - aws
- ec2_placement_group_info:
- - aws
- ec2_scaling_policy:
- - aws
- ec2_snapshot:
- - aws
- ec2_snapshot_copy:
- - aws
- ec2_snapshot_facts:
- - aws
- ec2_snapshot_info:
- - aws
- ec2_tag:
- - aws
- ec2_tag_info:
- - aws
- ec2_transit_gateway:
- - aws
- ec2_transit_gateway_info:
- - aws
- ec2_vol:
- - aws
- ec2_vol_facts:
- - aws
- ec2_vol_info:
- - aws
- ec2_vpc_dhcp_option:
- - aws
- ec2_vpc_dhcp_option_facts:
- - aws
- ec2_vpc_dhcp_option_info:
- - aws
- ec2_vpc_egress_igw:
- - aws
- ec2_vpc_endpoint:
- - aws
- ec2_vpc_endpoint_facts:
- - aws
- ec2_vpc_endpoint_info:
- - aws
- ec2_vpc_igw:
- - aws
- ec2_vpc_igw_facts:
- - aws
- ec2_vpc_igw_info:
- - aws
- ec2_vpc_nacl:
- - aws
- ec2_vpc_nacl_facts:
- - aws
- ec2_vpc_nacl_info:
- - aws
- ec2_vpc_nat_gateway:
- - aws
- ec2_vpc_nat_gateway_facts:
- - aws
- ec2_vpc_nat_gateway_info:
- - aws
- ec2_vpc_net:
- - aws
- ec2_vpc_net_facts:
- - aws
- ec2_vpc_net_info:
- - aws
- ec2_vpc_peer:
- - aws
- ec2_vpc_peering_facts:
- - aws
- ec2_vpc_peering_info:
- - aws
- ec2_vpc_route_table:
- - aws
- ec2_vpc_route_table_facts:
- - aws
- ec2_vpc_route_table_info:
- - aws
- ec2_vpc_subnet:
- - aws
- ec2_vpc_subnet_facts:
- - aws
- ec2_vpc_subnet_info:
- - aws
- ec2_vpc_vgw:
- - aws
- ec2_vpc_vgw_facts:
- - aws
- ec2_vpc_vgw_info:
- - aws
- ec2_vpc_vpn:
- - aws
- ec2_vpc_vpn_facts:
- - aws
- ec2_vpc_vpn_info:
- - aws
- ec2_win_password:
- - aws
- ecs_attribute:
- - aws
- ecs_cluster:
- - aws
- ecs_ecr:
- - aws
- ecs_service:
- - aws
- ecs_service_facts:
- - aws
- ecs_service_info:
- - aws
- ecs_tag:
- - aws
- ecs_task:
- - aws
- ecs_taskdefinition:
- - aws
- ecs_taskdefinition_facts:
- - aws
- ecs_taskdefinition_info:
- - aws
- efs:
- - aws
- efs_facts:
- - aws
- efs_info:
- - aws
- elasticache:
- - aws
- elasticache_facts:
- - aws
- elasticache_info:
- - aws
- elasticache_parameter_group:
- - aws
- elasticache_snapshot:
- - aws
- elasticache_subnet_group:
- - aws
- elb_application_lb:
- - aws
- elb_application_lb_facts:
- - aws
- elb_application_lb_info:
- - aws
- elb_classic_lb:
- - aws
- elb_classic_lb_facts:
- - aws
- elb_classic_lb_info:
- - aws
- elb_instance:
- - aws
- elb_network_lb:
- - aws
- elb_target:
- - aws
- elb_target_facts:
- - aws
- elb_target_group:
- - aws
- elb_target_group_facts:
- - aws
- elb_target_group_info:
- - aws
- elb_target_info:
- - aws
- execute_lambda:
- - aws
- iam:
- - aws
- iam_cert:
- - aws
- iam_group:
- - aws
- iam_managed_policy:
- - aws
- iam_mfa_device_facts:
- - aws
- iam_mfa_device_info:
- - aws
- iam_password_policy:
- - aws
- iam_policy:
- - aws
- iam_policy_info:
- - aws
- iam_role:
- - aws
- iam_role_facts:
- - aws
- iam_role_info:
- - aws
- iam_server_certificate_facts:
- - aws
- iam_saml_federation:
- - aws
- iam_server_certificate_info:
- - aws
- iam_user:
- - aws
- iam_user_info:
- - aws
- kinesis_stream:
- - aws
- lambda:
- - aws
- lambda_alias:
- - aws
- lambda_event:
- - aws
- lambda_facts:
- - aws
- lambda_info:
- - aws
- lambda_policy:
- - aws
- lightsail:
- - aws
- lightsail_keypair:
- - aws
- rds:
- - aws
- rds_instance:
- - aws
- rds_instance_facts:
- - aws
- rds_instance_info:
- - aws
- rds_param_group:
- - aws
- rds_snapshot_facts:
- - aws
- rds_snapshot_info:
- - aws
- rds_subnet_group:
- - aws
- redshift:
- - aws
- redshift_cross_region_snapshots:
- - aws
- redshift_facts:
- - aws
- redshift_info:
- - aws
- redshift_subnet_group:
- - aws
- route53:
- - aws
- route53_facts:
- - aws
- route53_info:
- - aws
- route53_health_check:
- - aws
- route53_zone:
- - aws
- s3_bucket:
- - aws
- s3_bucket_notification:
- - aws
- s3_lifecycle:
- - aws
- s3_logging:
- - aws
- s3_sync:
- - aws
- s3_website:
- - aws
- sns:
- - aws
- sns_topic:
- - aws
- sqs_queue:
- - aws
- sts_assume_role:
- - aws
- sts_session_token:
- - aws
- gcp_appengine_firewall_rule:
- - gcp
- gcp_appengine_firewall_rule_info:
- - gcp
- gcp_bigquery_dataset:
- - gcp
- gcp_bigquery_dataset_info:
- - gcp
- gcp_bigquery_table:
- - gcp
- gcp_bigquery_table_info:
- - gcp
- gcp_cloudbuild_trigger:
- - gcp
- gcp_cloudbuild_trigger_info:
- - gcp
- gcp_cloudfunctions_cloud_function:
- - gcp
- gcp_cloudfunctions_cloud_function_info:
- - gcp
- gcp_cloudscheduler_job:
- - gcp
- gcp_cloudscheduler_job_info:
- - gcp
- gcp_cloudtasks_queue:
- - gcp
- gcp_cloudtasks_queue_info:
- - gcp
- gcp_compute_address:
- - gcp
- gcp_compute_address_info:
- - gcp
- gcp_compute_autoscaler:
- - gcp
- gcp_compute_autoscaler_info:
- - gcp
- gcp_compute_backend_bucket:
- - gcp
- gcp_compute_backend_bucket_info:
- - gcp
- gcp_compute_backend_service:
- - gcp
- gcp_compute_backend_service_info:
- - gcp
- gcp_compute_disk:
- - gcp
- gcp_compute_disk_info:
- - gcp
- gcp_compute_firewall:
- - gcp
- gcp_compute_firewall_info:
- - gcp
- gcp_compute_forwarding_rule:
- - gcp
- gcp_compute_forwarding_rule_info:
- - gcp
- gcp_compute_global_address:
- - gcp
- gcp_compute_global_address_info:
- - gcp
- gcp_compute_global_forwarding_rule:
- - gcp
- gcp_compute_global_forwarding_rule_info:
- - gcp
- gcp_compute_health_check:
- - gcp
- gcp_compute_health_check_info:
- - gcp
- gcp_compute_http_health_check:
- - gcp
- gcp_compute_http_health_check_info:
- - gcp
- gcp_compute_https_health_check:
- - gcp
- gcp_compute_https_health_check_info:
- - gcp
- gcp_compute_image:
- - gcp
- gcp_compute_image_info:
- - gcp
- gcp_compute_instance:
- - gcp
- gcp_compute_instance_info:
- - gcp
- gcp_compute_instance_group:
- - gcp
- gcp_compute_instance_group_info:
- - gcp
- gcp_compute_instance_group_manager:
- - gcp
- gcp_compute_instance_group_manager_info:
- - gcp
- gcp_compute_instance_template:
- - gcp
- gcp_compute_instance_template_info:
- - gcp
- gcp_compute_interconnect_attachment:
- - gcp
- gcp_compute_interconnect_attachment_info:
- - gcp
- gcp_compute_network:
- - gcp
- gcp_compute_network_info:
- - gcp
- gcp_compute_network_endpoint_group:
- - gcp
- gcp_compute_network_endpoint_group_info:
- - gcp
- gcp_compute_node_group:
- - gcp
- gcp_compute_node_group_info:
- - gcp
- gcp_compute_node_template:
- - gcp
- gcp_compute_node_template_info:
- - gcp
- gcp_compute_region_backend_service:
- - gcp
- gcp_compute_region_backend_service_info:
- - gcp
- gcp_compute_region_disk:
- - gcp
- gcp_compute_region_disk_info:
- - gcp
- gcp_compute_reservation:
- - gcp
- gcp_compute_reservation_info:
- - gcp
- gcp_compute_route:
- - gcp
- gcp_compute_route_info:
- - gcp
- gcp_compute_router:
- - gcp
- gcp_compute_router_info:
- - gcp
- gcp_compute_snapshot:
- - gcp
- gcp_compute_snapshot_info:
- - gcp
- gcp_compute_ssl_certificate:
- - gcp
- gcp_compute_ssl_certificate_info:
- - gcp
- gcp_compute_ssl_policy:
- - gcp
- gcp_compute_ssl_policy_info:
- - gcp
- gcp_compute_subnetwork:
- - gcp
- gcp_compute_subnetwork_info:
- - gcp
- gcp_compute_target_http_proxy:
- - gcp
- gcp_compute_target_http_proxy_info:
- - gcp
- gcp_compute_target_https_proxy:
- - gcp
- gcp_compute_target_https_proxy_info:
- - gcp
- gcp_compute_target_instance:
- - gcp
- gcp_compute_target_instance_info:
- - gcp
- gcp_compute_target_pool:
- - gcp
- gcp_compute_target_pool_info:
- - gcp
- gcp_compute_target_ssl_proxy:
- - gcp
- gcp_compute_target_ssl_proxy_info:
- - gcp
- gcp_compute_target_tcp_proxy:
- - gcp
- gcp_compute_target_tcp_proxy_info:
- - gcp
- gcp_compute_target_vpn_gateway:
- - gcp
- gcp_compute_target_vpn_gateway_info:
- - gcp
- gcp_compute_url_map:
- - gcp
- gcp_compute_url_map_info:
- - gcp
- gcp_compute_vpn_tunnel:
- - gcp
- gcp_compute_vpn_tunnel_info:
- - gcp
- gcp_container_cluster:
- - gcp
- gcp_container_cluster_info:
- - gcp
- gcp_container_node_pool:
- - gcp
- gcp_container_node_pool_info:
- - gcp
- gcp_dns_managed_zone:
- - gcp
- gcp_dns_managed_zone_info:
- - gcp
- gcp_dns_resource_record_set:
- - gcp
- gcp_dns_resource_record_set_info:
- - gcp
- gcp_filestore_instance:
- - gcp
- gcp_filestore_instance_info:
- - gcp
- gcp_iam_role:
- - gcp
- gcp_iam_role_info:
- - gcp
- gcp_iam_service_account:
- - gcp
- gcp_iam_service_account_info:
- - gcp
- gcp_iam_service_account_key:
- - gcp
- gcp_kms_crypto_key:
- - gcp
- gcp_kms_crypto_key_info:
- - gcp
- gcp_kms_key_ring:
- - gcp
- gcp_kms_key_ring_info:
- - gcp
- gcp_logging_metric:
- - gcp
- gcp_logging_metric_info:
- - gcp
- gcp_mlengine_model:
- - gcp
- gcp_mlengine_model_info:
- - gcp
- gcp_mlengine_version:
- - gcp
- gcp_mlengine_version_info:
- - gcp
- gcp_pubsub_subscription:
- - gcp
- gcp_pubsub_subscription_info:
- - gcp
- gcp_pubsub_topic:
- - gcp
- gcp_pubsub_topic_info:
- - gcp
- gcp_redis_instance:
- - gcp
- gcp_redis_instance_info:
- - gcp
- gcp_resourcemanager_project:
- - gcp
- gcp_resourcemanager_project_info:
- - gcp
- gcp_runtimeconfig_config:
- - gcp
- gcp_runtimeconfig_config_info:
- - gcp
- gcp_runtimeconfig_variable:
- - gcp
- gcp_runtimeconfig_variable_info:
- - gcp
- gcp_serviceusage_service:
- - gcp
- gcp_serviceusage_service_info:
- - gcp
- gcp_sourcerepo_repository:
- - gcp
- gcp_sourcerepo_repository_info:
- - gcp
- gcp_spanner_database:
- - gcp
- gcp_spanner_database_info:
- - gcp
- gcp_spanner_instance:
- - gcp
- gcp_spanner_instance_info:
- - gcp
- gcp_sql_database:
- - gcp
- gcp_sql_database_info:
- - gcp
- gcp_sql_instance:
- - gcp
- gcp_sql_instance_info:
- - gcp
- gcp_sql_user:
- - gcp
- gcp_sql_user_info:
- - gcp
- gcp_storage_bucket:
- - gcp
- gcp_storage_bucket_access_control:
- - gcp
- gcp_storage_object:
- - gcp
- gcp_tpu_node:
- - gcp
- gcp_tpu_node_info:
- - gcp
- azure_rm_acs:
- - azure
- azure_rm_aks:
- - azure
- azure_rm_aks_facts:
- - azure
- azure_rm_appserviceplan:
- - azure
- azure_rm_appserviceplan_facts:
- - azure
- azure_rm_availabilityset:
- - azure
- azure_rm_availabilityset_facts:
- - azure
- azure_rm_containerinstance:
- - azure
- azure_rm_containerregistry:
- - azure
- azure_rm_deployment:
- - azure
- azure_rm_dnsrecordset:
- - azure
- azure_rm_dnsrecordset_facts:
- - azure
- azure_rm_dnszone:
- - azure
- azure_rm_dnszone_facts:
- - azure
- azure_rm_functionapp:
- - azure
- azure_rm_functionapp_facts:
- - azure
- azure_rm_image:
- - azure
- azure_rm_keyvault:
- - azure
- azure_rm_keyvaultkey:
- - azure
- azure_rm_keyvaultsecret:
- - azure
- azure_rm_loadbalancer:
- - azure
- azure_rm_loadbalancer_facts:
- - azure
- azure_rm_managed_disk:
- - azure
- azure_rm_manageddisk:
- - azure
- azure_rm_managed_disk_facts:
- - azure
- azure_rm_manageddisk_facts:
- - azure
- azure_rm_mysqldatabase:
- - azure
- azure_rm_mysqldatabase_facts:
- - azure
- azure_rm_mysqlserver:
- - azure
- azure_rm_mysqlserver_facts:
- - azure
- azure_rm_networkinterface:
- - azure
- azure_rm_networkinterface_facts:
- - azure
- azure_rm_postgresqldatabase:
- - azure
- azure_rm_postgresqldatabase_facts:
- - azure
- azure_rm_postgresqlserver:
- - azure
- azure_rm_publicipaddress:
- - azure
- azure_rm_publicipaddress_facts:
- - azure
- azure_rm_resource:
- - azure
- azure_rm_resource_facts:
- - azure
- azure_rm_resourcegroup:
- - azure
- azure_rm_resourcegroup_facts:
- - azure
- azure_rm_resourcegroup_info:
- - azure
- azure_rm_securitygroup:
- - azure
- azure_rm_securitygroup_facts:
- - azure
- azure_rm_sqldatabase:
- - azure
- azure_rm_sqlserver:
- - azure
- azure_rm_sqlserver_facts:
- - azure
- azure_rm_storageaccount:
- - azure
- azure_rm_storageaccount_facts:
- - azure
- azure_rm_storageblob:
- - azure
- azure_rm_subnet:
- - azure
- azure_rm_virtualmachine:
- - azure
- azure_rm_virtualmachine_extension:
- - azure
- azure_rm_virtualmachine_facts:
- - azure
- azure_rm_virtualmachineimage_facts:
- - azure
- azure_rm_virtualmachine_scaleset:
- - azure
- azure_rm_virtualmachine_scaleset_facts:
- - azure
- azure_rm_virtualnetwork:
- - azure
- azure_rm_virtualnetwork_facts:
- - azure
- azure_rm_webapp:
- - azure
- k8s:
- - k8s
- k8s_auth:
- - k8s
- k8s_facts:
- - k8s
- k8s_info:
- - k8s
- k8s_service:
- - k8s
- k8s_scale:
- - k8s
- kubevirt_cdi_upload:
- - k8s
- kubevirt_preset:
- - k8s
- kubevirt_pvc:
- - k8s
- kubevirt_rs:
- - k8s
- kubevirt_template:
- - k8s
- kubevirt_vm:
- - k8s
- os_auth:
- - os
- os_client_config:
- - os
- os_coe_cluster:
- - os
- os_coe_cluster_template:
- - os
- os_flavor_facts:
- - os
- os_flavor_info:
- - os
- os_floating_ip:
- - os
- os_group:
- - os
- os_image:
- - os
- os_image_facts:
- - os
- os_image_info:
- - os
- os_ironic:
- - os
- os_ironic_inspect:
- - os
- os_ironic_node:
- - os
- os_keypair:
- - os
- os_keystone_domain:
- - os
- os_keystone_domain_facts:
- - os
- os_keystone_domain_info:
- - os
- os_keystone_endpoint:
- - os
- os_keystone_role:
- - os
- os_keystone_service:
- - os
- os_listener:
- - os
- os_loadbalancer:
- - os
- os_member:
- - os
- os_network:
- - os
- os_networks_facts:
- - os
- os_networks_info:
- - os
- os_nova_flavor:
- - os
- os_nova_host_aggregate:
- - os
- os_object:
- - os
- os_pool:
- - os
- os_port:
- - os
- os_port_facts:
- - os
- os_port_info:
- - os
- os_project:
- - os
- os_project_access:
- - os
- os_project_facts:
- - os
- os_project_info:
- - os
- os_quota:
- - os
- os_recordset:
- - os
- os_router:
- - os
- os_security_group:
- - os
- os_security_group_rule:
- - os
- os_server:
- - os
- os_server_action:
- - os
- os_server_facts:
- - os
- os_server_info:
- - os
- os_server_group:
- - os
- os_server_metadata:
- - os
- os_server_volume:
- - os
- os_stack:
- - os
- os_subnet:
- - os
- os_subnets_facts:
- - os
- os_subnets_info:
- - os
- os_user:
- - os
- os_user_facts:
- - os
- os_user_info:
- - os
- os_user_group:
- - os
- os_user_role:
- - os
- os_volume:
- - os
- os_volume_snapshot:
- - os
- os_zone:
- - os
- ovirt_affinity_group:
- - ovirt
- ovirt_affinity_label_facts:
- - ovirt
- ovirt_affinity_label_info:
- - ovirt
- ovirt_affinity_label:
- - ovirt
- ovirt_api_facts:
- - ovirt
- ovirt_api_info:
- - ovirt
- ovirt_auth:
- - ovirt
- ovirt_cluster_facts:
- - ovirt
- ovirt_cluster_info:
- - ovirt
- ovirt_cluster:
- - ovirt
- ovirt_datacenter_facts:
- - ovirt
- ovirt_datacenter_info:
- - ovirt
- ovirt_datacenter:
- - ovirt
- ovirt_disk_facts:
- - ovirt
- ovirt_disk_info:
- - ovirt
- ovirt_disk:
- - ovirt
- ovirt_event_facts:
- - ovirt
- ovirt_event_info:
- - ovirt
- ovirt_event:
- - ovirt
- ovirt_external_provider_facts:
- - ovirt
- ovirt_external_provider_info:
- - ovirt
- ovirt_external_provider:
- - ovirt
- ovirt_group_facts:
- - ovirt
- ovirt_group_info:
- - ovirt
- ovirt_group:
- - ovirt
- ovirt_host_facts:
- - ovirt
- ovirt_host_info:
- - ovirt
- ovirt_host_network:
- - ovirt
- ovirt_host_pm:
- - ovirt
- ovirt_host:
- - ovirt
- ovirt_host_storage_facts:
- - ovirt
- ovirt_host_storage_info:
- - ovirt
- ovirt_instance_type:
- - ovirt
- ovirt_job:
- - ovirt
- ovirt_mac_pool:
- - ovirt
- ovirt_network_facts:
- - ovirt
- ovirt_network_info:
- - ovirt
- ovirt_network:
- - ovirt
- ovirt_nic_facts:
- - ovirt
- ovirt_nic_info:
- - ovirt
- ovirt_nic:
- - ovirt
- ovirt_permission_facts:
- - ovirt
- ovirt_permission_info:
- - ovirt
- ovirt_permission:
- - ovirt
- ovirt_quota_facts:
- - ovirt
- ovirt_quota_info:
- - ovirt
- ovirt_quota:
- - ovirt
- ovirt_role:
- - ovirt
- ovirt_scheduling_policy_facts:
- - ovirt
- ovirt_scheduling_policy_info:
- - ovirt
- ovirt_snapshot_facts:
- - ovirt
- ovirt_snapshot_info:
- - ovirt
- ovirt_snapshot:
- - ovirt
- ovirt_storage_connection:
- - ovirt
- ovirt_storage_domain_facts:
- - ovirt
- ovirt_storage_domain_info:
- - ovirt
- ovirt_storage_domain:
- - ovirt
- ovirt_storage_template_facts:
- - ovirt
- ovirt_storage_template_info:
- - ovirt
- ovirt_storage_vm_facts:
- - ovirt
- ovirt_storage_vm_info:
- - ovirt
- ovirt_tag_facts:
- - ovirt
- ovirt_tag_info:
- - ovirt
- ovirt_tag:
- - ovirt
- ovirt_template_facts:
- - ovirt
- ovirt_template_info:
- - ovirt
- ovirt_template:
- - ovirt
- ovirt_user_facts:
- - ovirt
- ovirt_user_info:
- - ovirt
- ovirt_user:
- - ovirt
- ovirt_vm_facts:
- - ovirt
- ovirt_vm_info:
- - ovirt
- ovirt_vmpool_facts:
- - ovirt
- ovirt_vmpool_info:
- - ovirt
- ovirt_vmpool:
- - ovirt
- ovirt_vm:
- - ovirt
- ovirt_vnic_profile_info:
- - ovirt
- ovirt_vnic_profile:
- - ovirt
- test_module_defaults:
- - test
- vcenter_extension:
- - vmware
- vcenter_extension_info:
- - vmware
- vcenter_folder:
- - vmware
- vcenter_license:
- - vmware
- vmware_about_info:
- - vmware
- vmware_category:
- - vmware
- vmware_category_info:
- - vmware
- vmware_cfg_backup:
- - vmware
- vmware_cluster:
- - vmware
- vmware_cluster_drs:
- - vmware
- vmware_cluster_ha:
- - vmware
- vmware_cluster_info:
- - vmware
- vmware_cluster_vsan:
- - vmware
- vmware_content_deploy_template:
- - vmware
- vmware_content_library_info:
- - vmware
- vmware_content_library_manager:
- - vmware
- vmware_datacenter:
- - vmware
- vmware_datastore_cluster:
- - vmware
- vmware_datastore_info:
- - vmware
- vmware_datastore_maintenancemode:
- - vmware
- vmware_deploy_ovf:
- - vmware
- vmware_dns_config:
- - vmware
- vmware_drs_group:
- - vmware
- vmware_drs_group_info:
- - vmware
- vmware_drs_rule_info:
- - vmware
- vmware_dvs_host:
- - vmware
- vmware_dvs_portgroup:
- - vmware
- vmware_dvs_portgroup_find:
- - vmware
- vmware_dvs_portgroup_info:
- - vmware
- vmware_dvswitch:
- - vmware
- vmware_dvswitch_lacp:
- - vmware
- vmware_dvswitch_nioc:
- - vmware
- vmware_dvswitch_pvlans:
- - vmware
- vmware_dvswitch_uplink_pg:
- - vmware
- vmware_evc_mode:
- - vmware
- vmware_export_ovf:
- - vmware
- vmware_folder_info:
- - vmware
- vmware_guest:
- - vmware
- vmware_guest_boot_info:
- - vmware
- vmware_guest_boot_manager:
- - vmware
- vmware_guest_controller:
- - vmware
- vmware_guest_custom_attribute_defs:
- - vmware
- vmware_guest_custom_attributes:
- - vmware
- vmware_guest_customization_info:
- - vmware
- vmware_guest_disk:
- - vmware
- vmware_guest_disk_info:
- - vmware
- vmware_guest_file_operation:
- - vmware
- vmware_guest_find:
- - vmware
- vmware_guest_info:
- - vmware
- vmware_guest_move:
- - vmware
- vmware_guest_network:
- - vmware
- vmware_guest_powerstate:
- - vmware
- vmware_guest_register_operation:
- - vmware
- vmware_guest_screenshot:
- - vmware
- vmware_guest_sendkey:
- - vmware
- vmware_guest_serial_port:
- - vmware
- vmware_guest_snapshot:
- - vmware
- vmware_guest_snapshot_info:
- - vmware
- vmware_guest_tools_info:
- - vmware
- vmware_guest_tools_upgrade:
- - vmware
- vmware_guest_tools_wait:
- - vmware
- vmware_guest_video:
- - vmware
- vmware_guest_vnc:
- - vmware
- vmware_host:
- - vmware
- vmware_host_acceptance:
- - vmware
- vmware_host_active_directory:
- - vmware
- vmware_host_auto_start:
- - vmware
- vmware_host_capability_info:
- - vmware
- vmware_host_config_info:
- - vmware
- vmware_host_config_manager:
- - vmware
- vmware_host_datastore:
- - vmware
- vmware_host_dns:
- - vmware
- vmware_host_dns_info:
- - vmware
- vmware_host_facts:
- - vmware
- vmware_host_feature_info:
- - vmware
- vmware_host_firewall_info:
- - vmware
- vmware_host_firewall_manager:
- - vmware
- vmware_host_hyperthreading:
- - vmware
- vmware_host_ipv6:
- - vmware
- vmware_host_kernel_manager:
- - vmware
- vmware_host_lockdown:
- - vmware
- vmware_host_ntp:
- - vmware
- vmware_host_ntp_info:
- - vmware
- vmware_host_package_info:
- - vmware
- vmware_host_powermgmt_policy:
- - vmware
- vmware_host_powerstate:
- - vmware
- vmware_host_scanhba:
- - vmware
- vmware_host_service_info:
- - vmware
- vmware_host_service_manager:
- - vmware
- vmware_host_snmp:
- - vmware
- vmware_host_ssl_info:
- - vmware
- vmware_host_vmhba_info:
- - vmware
- vmware_host_vmnic_info:
- - vmware
- vmware_local_role_info:
- - vmware
- vmware_local_role_manager:
- - vmware
- vmware_local_user_info:
- - vmware
- vmware_local_user_manager:
- - vmware
- vmware_maintenancemode:
- - vmware
- vmware_migrate_vmk:
- - vmware
- vmware_object_role_permission:
- - vmware
- vmware_portgroup:
- - vmware
- vmware_portgroup_info:
- - vmware
- vmware_resource_pool:
- - vmware
- vmware_resource_pool_info:
- - vmware
- vmware_tag:
- - vmware
- vmware_tag_info:
- - vmware
- vmware_tag_manager:
- - vmware
- vmware_target_canonical_info:
- - vmware
- vmware_vcenter_settings:
- - vmware
- vmware_vcenter_statistics:
- - vmware
- vmware_vm_host_drs_rule:
- - vmware
- vmware_vm_info:
- - vmware
- vmware_vm_shell:
- - vmware
- vmware_vm_storage_policy_info:
- - vmware
- vmware_vm_vm_drs_rule:
- - vmware
- vmware_vm_vss_dvs_migrate:
- - vmware
- vmware_vmkernel:
- - vmware
- vmware_vmkernel_info:
- - vmware
- vmware_vmkernel_ip_config:
- - vmware
- vmware_vmotion:
- - vmware
- vmware_vsan_cluster:
- - vmware
- vmware_vsan_health_info:
- - vmware
- vmware_vspan_session:
- - vmware
- vmware_vswitch:
- - vmware
- vmware_vswitch_info:
- - vmware
- vsphere_copy:
- - vmware
- vsphere_file:
- - vmware
diff --git a/lib/ansible/executor/module_common.py b/lib/ansible/executor/module_common.py
index 05b1e8ab2f..429bfbb10e 100644
--- a/lib/ansible/executor/module_common.py
+++ b/lib/ansible/executor/module_common.py
@@ -38,7 +38,7 @@ from ansible.executor.interpreter_discovery import InterpreterDiscoveryRequiredE
from ansible.executor.powershell import module_manifest as ps_manifest
from ansible.module_utils.common.text.converters import to_bytes, to_text, to_native
from ansible.plugins.loader import module_utils_loader
-from ansible.utils.collection_loader._collection_finder import _get_collection_metadata
+from ansible.utils.collection_loader._collection_finder import _get_collection_metadata, AnsibleCollectionRef
# Must import strategy and use write_locks from there
# If we import write_locks directly then we end up binding a
@@ -1319,7 +1319,23 @@ def modify_module(module_name, module_path, module_args, templar, task_vars=None
return (b_module_data, module_style, shebang)
-def get_action_args_with_defaults(action, args, defaults, templar):
+def get_action_args_with_defaults(action, args, defaults, templar, redirected_names=None):
+ group_collection_map = {
+ 'acme': ['community.crypto'],
+ 'aws': ['amazon.aws', 'community.aws'],
+ 'azure': ['azure.azcollection'],
+ 'cpm': ['wti.remote'],
+ 'docker': ['community.general'],
+ 'gcp': ['google.cloud'],
+ 'k8s': ['community.kubernetes', 'community.general'],
+ 'os': ['openstack.cloud'],
+ 'ovirt': ['ovirt.ovirt', 'community.general'],
+ 'vmware': ['community.vmware'],
+ 'testgroup': ['testns.testcoll', 'testns.othercoll', 'testns.boguscoll']
+ }
+
+ if not redirected_names:
+ redirected_names = [action]
tmp_args = {}
module_defaults = {}
@@ -1334,13 +1350,26 @@ def get_action_args_with_defaults(action, args, defaults, templar):
module_defaults = templar.template(module_defaults)
# deal with configured group defaults first
- if action in C.config.module_defaults_groups:
- for group in C.config.module_defaults_groups.get(action, []):
- tmp_args.update((module_defaults.get('group/{0}'.format(group)) or {}).copy())
+ for default in module_defaults:
+ if not default.startswith('group/'):
+ continue
+
+ group_name = default.split('group/')[-1]
+
+ for collection_name in group_collection_map.get(group_name, []):
+ try:
+ action_group = _get_collection_metadata(collection_name).get('action_groups', {})
+ except ValueError:
+ # The collection may not be installed
+ continue
+
+ if any(name for name in redirected_names if name in action_group):
+ tmp_args.update((module_defaults.get('group/%s' % group_name) or {}).copy())
# handle specific action defaults
- if action in module_defaults:
- tmp_args.update(module_defaults[action].copy())
+ for action in redirected_names:
+ if action in module_defaults:
+ tmp_args.update(module_defaults[action].copy())
# direct args override all
tmp_args.update(args)
diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py
index 22f758e9ce..4bb9ea3141 100644
--- a/lib/ansible/executor/task_executor.py
+++ b/lib/ansible/executor/task_executor.py
@@ -631,7 +631,9 @@ class TaskExecutor:
self._handler = self._get_action_handler(connection=self._connection, templar=templar)
# Apply default params for action/module, if present
- self._task.args = get_action_args_with_defaults(self._task.action, self._task.args, self._task.module_defaults, templar)
+ self._task.args = get_action_args_with_defaults(
+ self._task.action, self._task.args, self._task.module_defaults, templar, self._task._ansible_internal_redirect_list
+ )
# And filter out any fields which were set to default(omit), and got the omit token value
omit_token = variables.get('omit')
diff --git a/lib/ansible/parsing/mod_args.py b/lib/ansible/parsing/mod_args.py
index 929d1add9e..a6906b909c 100644
--- a/lib/ansible/parsing/mod_args.py
+++ b/lib/ansible/parsing/mod_args.py
@@ -119,6 +119,8 @@ class ModuleArgsParser:
self._task_attrs.update(['local_action', 'static'])
self._task_attrs = frozenset(self._task_attrs)
+ self.internal_redirect_list = []
+
def _split_module_string(self, module_string):
'''
when module names are expressed like:
@@ -266,6 +268,8 @@ class ModuleArgsParser:
delegate_to = self._task_ds.get('delegate_to', Sentinel)
args = dict()
+ self.internal_redirect_list = []
+
# This is the standard YAML form for command-type modules. We grab
# the args and pass them in as additional arguments, which can/will
# be overwritten via dict updates from the other arg sources below
@@ -294,8 +298,24 @@ class ModuleArgsParser:
# walk the filtered input dictionary to see if we recognize a module name
for item, value in iteritems(non_task_ds):
- if item in BUILTIN_TASKS or skip_action_validation or action_loader.has_plugin(item, collection_list=self._collection_list) or \
- module_loader.has_plugin(item, collection_list=self._collection_list):
+ is_action_candidate = False
+ if item in BUILTIN_TASKS:
+ is_action_candidate = True
+ elif skip_action_validation:
+ is_action_candidate = True
+ else:
+ # If the plugin is resolved and redirected smuggle the list of candidate names via the task attribute 'internal_redirect_list'
+ context = action_loader.find_plugin_with_context(item, collection_list=self._collection_list)
+ if not context.resolved:
+ context = module_loader.find_plugin_with_context(item, collection_list=self._collection_list)
+ if context.resolved and context.redirect_list:
+ self.internal_redirect_list = context.redirect_list
+ elif context.redirect_list:
+ self.internal_redirect_list = context.redirect_list
+
+ is_action_candidate = bool(self.internal_redirect_list)
+
+ if is_action_candidate:
# finding more than one module name is a problem
if action is not None:
raise AnsibleParserError("conflicting action statements: %s, %s" % (action, item), obj=self._task_ds)
diff --git a/lib/ansible/playbook/task.py b/lib/ansible/playbook/task.py
index 405316d3f8..80b7fd353f 100644
--- a/lib/ansible/playbook/task.py
+++ b/lib/ansible/playbook/task.py
@@ -91,6 +91,10 @@ class Task(Base, Conditional, Taggable, CollectionSearch):
def __init__(self, block=None, role=None, task_include=None):
''' constructors a task, without the Task.load classmethod, it will be pretty blank '''
+ # This is a reference of all the candidate action names for transparent execution of module_defaults with redirected content
+ # This isn't a FieldAttribute to prevent it from being set via the playbook
+ self._ansible_internal_redirect_list = []
+
self._role = role
self._parent = None
@@ -220,6 +224,8 @@ class Task(Base, Conditional, Taggable, CollectionSearch):
raise
# But if it wasn't, we can add the yaml object now to get more detail
raise AnsibleParserError(to_native(e), obj=ds, orig_exc=e)
+ else:
+ self._ansible_internal_redirect_list = args_parser.internal_redirect_list[:]
# the command/shell/script modules used to support the `cmd` arg,
# which corresponds to what we now call _raw_params, so move that
@@ -394,6 +400,9 @@ class Task(Base, Conditional, Taggable, CollectionSearch):
def copy(self, exclude_parent=False, exclude_tasks=False):
new_me = super(Task, self).copy()
+ # if the task has an associated list of candidate names, copy it to the new object too
+ new_me._ansible_internal_redirect_list = self._ansible_internal_redirect_list[:]
+
new_me._parent = None
if self._parent and not exclude_parent:
new_me._parent = self._parent.copy(exclude_tasks=exclude_tasks)
@@ -415,6 +424,9 @@ class Task(Base, Conditional, Taggable, CollectionSearch):
if self._role:
data['role'] = self._role.serialize()
+ if self._ansible_internal_redirect_list:
+ data['_ansible_internal_redirect_list'] = self._ansible_internal_redirect_list[:]
+
return data
def deserialize(self, data):
@@ -443,6 +455,8 @@ class Task(Base, Conditional, Taggable, CollectionSearch):
self._role = r
del data['role']
+ self._ansible_internal_redirect_list = data.get('_ansible_internal_redirect_list', [])
+
super(Task, self).deserialize(data)
def set_loader(self, loader):
diff --git a/lib/ansible/plugins/action/gather_facts.py b/lib/ansible/plugins/action/gather_facts.py
index d58e9dd6bc..cd181203b5 100644
--- a/lib/ansible/plugins/action/gather_facts.py
+++ b/lib/ansible/plugins/action/gather_facts.py
@@ -42,7 +42,7 @@ class ActionModule(ActionBase):
mod_args = dict((k, v) for k, v in mod_args.items() if v is not None)
# handle module defaults
- mod_args = get_action_args_with_defaults(fact_module, mod_args, self._task.module_defaults, self._templar)
+ mod_args = get_action_args_with_defaults(fact_module, mod_args, self._task.module_defaults, self._templar, self._task._ansible_internal_redirect_list)
return mod_args
diff --git a/lib/ansible/plugins/action/package.py b/lib/ansible/plugins/action/package.py
index 932acccb04..c4349ca4d7 100644
--- a/lib/ansible/plugins/action/package.py
+++ b/lib/ansible/plugins/action/package.py
@@ -66,7 +66,9 @@ class ActionModule(ActionBase):
del new_module_args['use']
# get defaults for specific module
- new_module_args = get_action_args_with_defaults(module, new_module_args, self._task.module_defaults, self._templar)
+ new_module_args = get_action_args_with_defaults(
+ module, new_module_args, self._task.module_defaults, self._templar, self._task._ansible_internal_redirect_list
+ )
display.vvvv("Running %s" % module)
result.update(self._execute_module(module_name=module, module_args=new_module_args, task_vars=task_vars, wrap_async=self._task.async_val))
diff --git a/lib/ansible/plugins/action/service.py b/lib/ansible/plugins/action/service.py
index 3ebd0ae17d..c6af6248e6 100644
--- a/lib/ansible/plugins/action/service.py
+++ b/lib/ansible/plugins/action/service.py
@@ -73,7 +73,9 @@ class ActionModule(ActionBase):
self._display.warning('Ignoring "%s" as it is not used in "%s"' % (unused, module))
# get defaults for specific module
- new_module_args = get_action_args_with_defaults(module, new_module_args, self._task.module_defaults, self._templar)
+ new_module_args = get_action_args_with_defaults(
+ module, new_module_args, self._task.module_defaults, self._templar, self._task._ansible_internal_redirect_list
+ )
self._display.vvvv("Running %s" % module)
result.update(self._execute_module(module_name=module, module_args=new_module_args, task_vars=task_vars, wrap_async=self._task.async_val))
diff --git a/lib/ansible/plugins/loader.py b/lib/ansible/plugins/loader.py
index 466dac066f..249aebd7dd 100644
--- a/lib/ansible/plugins/loader.py
+++ b/lib/ansible/plugins/loader.py
@@ -587,6 +587,10 @@ class PluginLoader:
else:
# 'ansible.builtin' should be handled here. This means only internal, or builtin, paths are searched.
plugin_load_context = self._find_fq_plugin(candidate_name, suffix, plugin_load_context=plugin_load_context)
+
+ if candidate_name != plugin_load_context.original_name and candidate_name not in plugin_load_context.redirect_list:
+ plugin_load_context.redirect_list.append(candidate_name)
+
if plugin_load_context.resolved or plugin_load_context.pending_redirect: # if we got an answer or need to chase down a redirect, return
return plugin_load_context
except (AnsiblePluginRemovedError, AnsiblePluginCircularRedirect, AnsibleCollectionUnsupportedVersionError):
diff --git a/lib/ansible/utils/collection_loader/_collection_finder.py b/lib/ansible/utils/collection_loader/_collection_finder.py
index 47b5782997..6aa3ca5ab4 100644
--- a/lib/ansible/utils/collection_loader/_collection_finder.py
+++ b/lib/ansible/utils/collection_loader/_collection_finder.py
@@ -531,6 +531,15 @@ class _AnsibleCollectionPkgLoader(_AnsibleCollectionPkgLoaderBase):
# if redirect.startswith('..'):
# redirect = redirect[2:]
+ action_groups = meta_dict.pop('action_groups', {})
+ meta_dict['action_groups'] = {}
+ for group_name in action_groups:
+ for action_name in action_groups[group_name]:
+ if action_name in meta_dict['action_groups']:
+ meta_dict['action_groups'][action_name].append(group_name)
+ else:
+ meta_dict['action_groups'][action_name] = [group_name]
+
return meta_dict
diff --git a/test/integration/targets/incidental_aws_step_functions_state_machine/tasks/main.yml b/test/integration/targets/incidental_aws_step_functions_state_machine/tasks/main.yml
index 1eb63de130..23e71dcebf 100644
--- a/test/integration/targets/incidental_aws_step_functions_state_machine/tasks/main.yml
+++ b/test/integration/targets/incidental_aws_step_functions_state_machine/tasks/main.yml
@@ -2,7 +2,17 @@
- name: Integration test for AWS Step Function state machine module
module_defaults:
- group/aws:
+ iam_role:
+ aws_access_key: "{{ aws_access_key }}"
+ aws_secret_key: "{{ aws_secret_key }}"
+ security_token: "{{ security_token | default(omit) }}"
+ region: "{{ aws_region }}"
+ aws_step_functions_state_machine:
+ aws_access_key: "{{ aws_access_key }}"
+ aws_secret_key: "{{ aws_secret_key }}"
+ security_token: "{{ security_token | default(omit) }}"
+ region: "{{ aws_region }}"
+ aws_step_functions_state_machine_execution:
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
security_token: "{{ security_token | default(omit) }}"
diff --git a/test/integration/targets/incidental_cloudformation/tasks/main.yml b/test/integration/targets/incidental_cloudformation/tasks/main.yml
index 9b89722b20..10924bcd53 100644
--- a/test/integration/targets/incidental_cloudformation/tasks/main.yml
+++ b/test/integration/targets/incidental_cloudformation/tasks/main.yml
@@ -1,17 +1,25 @@
---
+- name: set up aws connection info
+ set_fact:
+ aws_connection_info: &aws_connection_info
+ aws_access_key: "{{ aws_access_key | default(omit) }}"
+ aws_secret_key: "{{ aws_secret_key | default(omit) }}"
+ security_token: "{{ security_token | default(omit) }}"
+ region: "{{ aws_region | default(omit) }}"
+ no_log: yes
- module_defaults:
- group/aws:
- aws_access_key: '{{ aws_access_key | default(omit) }}'
- aws_secret_key: '{{ aws_secret_key | default(omit) }}'
- security_token: '{{ security_token | default(omit) }}'
- region: '{{ aws_region | default(omit) }}'
+ cloudformation:
+ <<: *aws_connection_info
+ cloudformation_info:
+ <<: *aws_connection_info
block:
# ==== Env setup ==========================================================
- name: list available AZs
aws_az_info:
+ <<: *aws_connection_info
register: region_azs
- name: pick an AZ for testing
@@ -24,6 +32,7 @@
cidr_block: "{{ vpc_cidr }}"
tags:
Name: Cloudformation testing
+ <<: *aws_connection_info
register: testing_vpc
- name: Create a test subnet
@@ -31,6 +40,7 @@
vpc_id: "{{ testing_vpc.vpc.id }}"
cidr: "{{ subnet_cidr }}"
az: "{{ availability_zone }}"
+ <<: *aws_connection_info
register: testing_subnet
- name: Find AMI to use
@@ -38,6 +48,7 @@
owners: 'amazon'
filters:
name: '{{ ec2_ami_name }}'
+ <<: *aws_connection_info
register: ec2_amis
- name: Set fact with latest AMI
@@ -453,6 +464,7 @@
vpc_id: "{{ testing_vpc.vpc.id }}"
cidr: "{{ subnet_cidr }}"
state: absent
+ <<: *aws_connection_info
ignore_errors: yes
- name: Delete test VPC
@@ -460,4 +472,5 @@
name: "{{ vpc_name }}"
cidr_block: "{{ vpc_cidr }}"
state: absent
+ <<: *aws_connection_info
ignore_errors: yes
diff --git a/test/integration/targets/incidental_ec2_instance/main.yml b/test/integration/targets/incidental_ec2_instance/main.yml
index 7695f7bcb9..788c2243a0 100644
--- a/test/integration/targets/incidental_ec2_instance/main.yml
+++ b/test/integration/targets/incidental_ec2_instance/main.yml
@@ -9,7 +9,7 @@
gather_facts: no
tasks:
- module_defaults:
- group/aws:
+ ec2_ami_info:
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
security_token: "{{ security_token | default(omit) }}"
diff --git a/test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/env_cleanup.yml b/test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/env_cleanup.yml
index 1b6c79e0d9..7ab668de17 100644
--- a/test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/env_cleanup.yml
+++ b/test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/env_cleanup.yml
@@ -1,9 +1,19 @@
+- name: set up aws connection info
+ set_fact:
+ aws_connection_info: &aws_connection_info
+ aws_access_key: "{{ aws_access_key }}"
+ aws_secret_key: "{{ aws_secret_key }}"
+ security_token: "{{ security_token | default(omit) }}"
+ region: "{{ aws_region }}"
+ no_log: yes
+
- name: "remove Instances"
ec2_instance:
state: absent
filters:
vpc-id: "{{ testing_vpc.vpc.id }}"
wait: yes
+ <<: *aws_connection_info
ignore_errors: yes
retries: 10
@@ -11,12 +21,14 @@
ec2_eni_info:
filters:
vpc-id: "{{ testing_vpc.vpc.id }}"
+ <<: *aws_connection_info
register: enis
- name: "delete all ENIs"
ec2_eni:
state: absent
eni_id: "{{ item.id }}"
+ <<: *aws_connection_info
until: removed is not failed
with_items: "{{ enis.network_interfaces }}"
ignore_errors: yes
@@ -28,6 +40,7 @@
name: "{{ resource_prefix }}-sg"
description: a security group for ansible tests
vpc_id: "{{ testing_vpc.vpc.id }}"
+ <<: *aws_connection_info
register: removed
until: removed is not failed
ignore_errors: yes
@@ -45,6 +58,7 @@
subnets:
- "{{ testing_subnet_a.subnet.id }}"
- "{{ testing_subnet_b.subnet.id }}"
+ <<: *aws_connection_info
register: removed
until: removed is not failed
ignore_errors: yes
@@ -54,6 +68,7 @@
ec2_vpc_igw:
state: absent
vpc_id: "{{ testing_vpc.vpc.id }}"
+ <<: *aws_connection_info
register: removed
until: removed is not failed
ignore_errors: yes
@@ -64,6 +79,7 @@
state: absent
vpc_id: "{{ testing_vpc.vpc.id }}"
cidr: "{{ subnet_a_cidr }}"
+ <<: *aws_connection_info
register: removed
until: removed is not failed
ignore_errors: yes
@@ -74,6 +90,7 @@
state: absent
vpc_id: "{{ testing_vpc.vpc.id }}"
cidr: "{{ subnet_b_cidr }}"
+ <<: *aws_connection_info
register: removed
until: removed is not failed
ignore_errors: yes
@@ -87,6 +104,7 @@
tags:
Name: Ansible Testing VPC
tenancy: default
+ <<: *aws_connection_info
register: removed
until: removed is not failed
ignore_errors: yes
diff --git a/test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/env_setup.yml b/test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/env_setup.yml
index 6c76b7bf79..1f2f3f0ada 100644
--- a/test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/env_setup.yml
+++ b/test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/env_setup.yml
@@ -1,7 +1,17 @@
+- name: set up aws connection info
+ set_fact:
+ aws_connection_info: &aws_connection_info
+ aws_access_key: "{{ aws_access_key }}"
+ aws_secret_key: "{{ aws_secret_key }}"
+ security_token: "{{ security_token | default(omit) }}"
+ region: "{{ aws_region }}"
+ no_log: yes
+
- run_once: '{{ setup_run_once | default("no") | bool }}'
block:
- name: "fetch AZ availability"
aws_az_info:
+ <<: *aws_connection_info
register: az_info
- name: "Assert that we have multiple AZs available to us"
assert:
@@ -20,12 +30,14 @@
tags:
Name: Ansible ec2_instance Testing VPC
tenancy: default
+ <<: *aws_connection_info
register: testing_vpc
- name: "Create internet gateway for use in testing"
ec2_vpc_igw:
state: present
vpc_id: "{{ testing_vpc.vpc.id }}"
+ <<: *aws_connection_info
register: igw
- name: "Create default subnet in zone A"
@@ -36,6 +48,7 @@
az: "{{ subnet_a_az }}"
resource_tags:
Name: "{{ resource_prefix }}-subnet-a"
+ <<: *aws_connection_info
register: testing_subnet_a
- name: "Create secondary subnet in zone B"
@@ -46,6 +59,7 @@
az: "{{ subnet_b_az }}"
resource_tags:
Name: "{{ resource_prefix }}-subnet-b"
+ <<: *aws_connection_info
register: testing_subnet_b
- name: "create routing rules"
@@ -60,6 +74,7 @@
subnets:
- "{{ testing_subnet_a.subnet.id }}"
- "{{ testing_subnet_b.subnet.id }}"
+ <<: *aws_connection_info
- name: "create a security group with the vpc"
ec2_group:
@@ -76,4 +91,5 @@
from_port: 80
to_port: 80
cidr_ip: 0.0.0.0/0
+ <<: *aws_connection_info
register: sg
diff --git a/test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/main.yml b/test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/main.yml
index e10aebcefe..c67f81b4e1 100644
--- a/test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/main.yml
+++ b/test/integration/targets/incidental_ec2_instance/roles/ec2_instance/tasks/main.yml
@@ -17,13 +17,27 @@
# - EC2_REGION -> AWS_REGION
#
-- name: "Wrap up all tests and setup AWS credentials"
- module_defaults:
- group/aws:
+- name: set up aws connection info
+ set_fact:
+ aws_connection_info: &aws_connection_info
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
security_token: "{{ security_token | default(omit) }}"
region: "{{ aws_region }}"
+ no_log: yes
+
+- name: "Wrap up all tests and setup AWS credentials"
+ module_defaults:
+ ec2_instance:
+ <<: *aws_connection_info
+ ec2_instance_info:
+ <<: *aws_connection_info
+ ec2_key:
+ <<: *aws_connection_info
+ ec2_eni:
+ <<: *aws_connection_info
+ iam_role:
+ <<: *aws_connection_info
block:
- debug:
msg: "{{ inventory_hostname }} start: {{ lookup('pipe','date') }}"
diff --git a/test/integration/targets/module_defaults/collections/ansible_collections/testns/othercoll/plugins/action/other_echoaction.py b/test/integration/targets/module_defaults/collections/ansible_collections/testns/othercoll/plugins/action/other_echoaction.py
new file mode 100644
index 0000000000..f7777b8ae2
--- /dev/null
+++ b/test/integration/targets/module_defaults/collections/ansible_collections/testns/othercoll/plugins/action/other_echoaction.py
@@ -0,0 +1,8 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible_collections.testns.testcoll.plugins.action.echoaction import ActionModule as BaseAM
+
+
+class ActionModule(BaseAM):
+ pass
diff --git a/test/integration/targets/module_defaults/collections/ansible_collections/testns/othercoll/plugins/modules/other_echo1.py b/test/integration/targets/module_defaults/collections/ansible_collections/testns/othercoll/plugins/modules/other_echo1.py
new file mode 100644
index 0000000000..771395f232
--- /dev/null
+++ b/test/integration/targets/module_defaults/collections/ansible_collections/testns/othercoll/plugins/modules/other_echo1.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible_collections.testns.testcoll.plugins.module_utils.echo_impl import do_echo
+
+
+def main():
+ do_echo()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/meta/runtime.yml b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/meta/runtime.yml
new file mode 100644
index 0000000000..62695fbc95
--- /dev/null
+++ b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/meta/runtime.yml
@@ -0,0 +1,9 @@
+action_groups:
+ testgroup:
+ - testns.testcoll.echo1
+ - testns.testcoll.echo2
+# note we can define defaults for an action
+ - testns.testcoll.echoaction
+# note we can define defaults in this group for actions/modules in another collection
+ - testns.othercoll.other_echoaction
+ - testns.othercoll.other_echo1
diff --git a/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/echoaction.py b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/echoaction.py
new file mode 100644
index 0000000000..2fa097b29f
--- /dev/null
+++ b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/action/echoaction.py
@@ -0,0 +1,19 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible.plugins.action import ActionBase
+
+
+class ActionModule(ActionBase):
+ TRANSFERS_FILES = False
+ _VALID_ARGS = frozenset()
+
+ def run(self, tmp=None, task_vars=None):
+ if task_vars is None:
+ task_vars = dict()
+
+ result = super(ActionModule, self).run(None, task_vars)
+
+ result = dict(changed=False, args_in=self._task.args)
+
+ return result
diff --git a/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/module_utils/echo_impl.py b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/module_utils/echo_impl.py
new file mode 100644
index 0000000000..f5c5d737be
--- /dev/null
+++ b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/module_utils/echo_impl.py
@@ -0,0 +1,15 @@
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import json
+from ansible.module_utils import basic
+from ansible.module_utils.basic import _load_params, AnsibleModule
+
+
+def do_echo():
+ p = _load_params()
+ d = json.loads(basic._ANSIBLE_ARGS)
+ d['ANSIBLE_MODULE_ARGS'] = {}
+ basic._ANSIBLE_ARGS = json.dumps(d).encode('utf-8')
+ module = AnsibleModule(argument_spec={})
+ module.exit_json(args_in=p)
diff --git a/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/modules/echo1.py b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/modules/echo1.py
new file mode 100644
index 0000000000..771395f232
--- /dev/null
+++ b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/modules/echo1.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible_collections.testns.testcoll.plugins.module_utils.echo_impl import do_echo
+
+
+def main():
+ do_echo()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/modules/echo2.py b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/modules/echo2.py
new file mode 100644
index 0000000000..771395f232
--- /dev/null
+++ b/test/integration/targets/module_defaults/collections/ansible_collections/testns/testcoll/plugins/modules/echo2.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+from ansible_collections.testns.testcoll.plugins.module_utils.echo_impl import do_echo
+
+
+def main():
+ do_echo()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/test/integration/targets/module_defaults/runme.sh b/test/integration/targets/module_defaults/runme.sh
new file mode 100755
index 0000000000..c19e607bbb
--- /dev/null
+++ b/test/integration/targets/module_defaults/runme.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -eux
+
+ansible-playbook test_defaults.yml "$@"
diff --git a/test/integration/targets/module_defaults/tasks/main.yml b/test/integration/targets/module_defaults/tasks/main.yml
index b84e33f430..3ed960d3b5 100644
--- a/test/integration/targets/module_defaults/tasks/main.yml
+++ b/test/integration/targets/module_defaults/tasks/main.yml
@@ -87,30 +87,3 @@
- assert:
that:
foo.msg == "Hello world!"
-- name: Module group defaults block
- module_defaults:
- group/test:
- arg1: "test1"
- arg2: "test2"
- block:
- - test_module_defaults:
- register: result
- - assert:
- that:
- - "result.test_module_defaults.arg1 == 'test1'"
- - "result.test_module_defaults.arg2 == 'test2'"
- - "result.test_module_defaults.arg3 == 'default3'"
-- name: Module group defaults block
- module_defaults:
- group/test:
- arg1: "test1"
- arg2: "test2"
- arg3: "test3"
- block:
- - test_module_defaults:
- register: result
- - assert:
- that:
- - "result.test_module_defaults.arg1 == 'test1'"
- - "result.test_module_defaults.arg2 == 'test2'"
- - "result.test_module_defaults.arg3 == 'test3'"
diff --git a/test/integration/targets/module_defaults/test_defaults.yml b/test/integration/targets/module_defaults/test_defaults.yml
new file mode 100644
index 0000000000..15b66362b2
--- /dev/null
+++ b/test/integration/targets/module_defaults/test_defaults.yml
@@ -0,0 +1,60 @@
+- hosts: localhost
+ gather_facts: no
+ collections:
+ - testns.testcoll
+ - testns.othercoll
+ module_defaults:
+ testns.testcoll.echoaction:
+ explicit_module_default: from playbook
+ testns.testcoll.echo1:
+ explicit_module_default: from playbook
+ group/testgroup:
+ group_module_default: from playbook
+ tasks:
+ - testns.testcoll.echoaction:
+ task_arg: from task
+ register: echoaction_fq
+ - echoaction:
+ task_arg: from task
+ register: echoaction_unq
+ - testns.testcoll.echo1:
+ task_arg: from task
+ register: echo1_fq
+ - echo1:
+ task_arg: from task
+ register: echo1_unq
+ - testns.testcoll.echo2:
+ task_arg: from task
+ register: echo2_fq
+ - echo2:
+ task_arg: from task
+ register: echo2_unq
+ - testns.othercoll.other_echoaction:
+ task_arg: from task
+ register: other_echoaction_fq
+ - other_echoaction:
+ task_arg: from task
+ register: other_echoaction_unq
+ - testns.othercoll.other_echo1:
+ task_arg: from task
+ register: other_echo1_fq
+ - other_echo1:
+ task_arg: from task
+ register: other_echo1_unq
+
+ - debug: var=echo1_fq
+
+ - assert:
+ that:
+ - "echoaction_fq.args_in == {'task_arg': 'from task', 'explicit_module_default': 'from playbook', 'group_module_default': 'from playbook' }"
+ - "echoaction_unq.args_in == {'task_arg': 'from task', 'explicit_module_default': 'from playbook', 'group_module_default': 'from playbook' }"
+ - "echo1_fq.args_in == {'task_arg': 'from task', 'explicit_module_default': 'from playbook', 'group_module_default': 'from playbook' }"
+ - "echo1_unq.args_in == {'task_arg': 'from task', 'explicit_module_default': 'from playbook', 'group_module_default': 'from playbook' }"
+ - "echo2_fq.args_in == {'task_arg': 'from task', 'group_module_default': 'from playbook' }"
+ - "echo2_unq.args_in == {'task_arg': 'from task', 'group_module_default': 'from playbook' }"
+ - "other_echoaction_fq.args_in == {'task_arg': 'from task', 'group_module_default': 'from playbook' }"
+ - "other_echoaction_unq.args_in == {'task_arg': 'from task', 'group_module_default': 'from playbook' }"
+ - "other_echo1_fq.args_in == {'task_arg': 'from task', 'group_module_default': 'from playbook' }"
+ - "other_echo1_unq.args_in == {'task_arg': 'from task', 'group_module_default': 'from playbook' }"
+
+ - include_tasks: tasks/main.yml
diff --git a/test/lib/ansible_test/_internal/cloud/vcenter.py b/test/lib/ansible_test/_internal/cloud/vcenter.py
index 37cfa6d5e6..59b9fe05bf 100644
--- a/test/lib/ansible_test/_internal/cloud/vcenter.py
+++ b/test/lib/ansible_test/_internal/cloud/vcenter.py
@@ -220,7 +220,7 @@ class VcenterEnvironment(CloudEnvironment):
env_vars=env_vars,
ansible_vars=ansible_vars,
module_defaults={
- 'group/vmware': {
+ 'vmware_guest': {
'hostname': ansible_vars['vcenter_hostname'],
'username': ansible_vars['vcenter_username'],
'password': ansible_vars['vcenter_password'],
diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt
index 33560007c5..51cc725660 100644
--- a/test/sanity/ignore.txt
+++ b/test/sanity/ignore.txt
@@ -57,7 +57,6 @@ lib/ansible/cli/console.py pylint:blacklisted-name
lib/ansible/cli/scripts/ansible_cli_stub.py shebang
lib/ansible/cli/scripts/ansible_connection_cli_stub.py shebang
lib/ansible/config/base.yml no-unwanted-files
-lib/ansible/config/module_defaults.yml no-unwanted-files
lib/ansible/executor/playbook_executor.py pylint:blacklisted-name
lib/ansible/executor/powershell/async_watchdog.ps1 pslint:PSCustomUseLiteralPath
lib/ansible/executor/powershell/async_wrapper.ps1 pslint:PSCustomUseLiteralPath
diff --git a/test/units/plugins/action/test_gather_facts.py b/test/units/plugins/action/test_gather_facts.py
index b550917e4a..6d81200014 100644
--- a/test/units/plugins/action/test_gather_facts.py
+++ b/test/units/plugins/action/test_gather_facts.py
@@ -19,12 +19,13 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from units.compat import unittest
-from units.compat.mock import MagicMock
+from units.compat.mock import MagicMock, patch
from ansible import constants as C
from ansible.plugins.action.gather_facts import ActionModule
from ansible.playbook.task import Task
from ansible.template import Templar
+import ansible.executor.module_common as module_common
from units.mock.loader import DictDataLoader
@@ -48,6 +49,7 @@ class TestNetworkFacts(unittest.TestCase):
self.task_vars = {'ansible_network_os': 'ios'}
self.task.action = 'gather_facts'
self.task.async_val = False
+ self.task._ansible_internal_redirect_list = []
self.task.args = {'gather_subset': 'min'}
self.task.module_defaults = [{'ios_facts': {'gather_subset': 'min'}}]
@@ -63,9 +65,11 @@ class TestNetworkFacts(unittest.TestCase):
facts_modules = C.config.get_config_value('FACTS_MODULES', variables=self.task_vars)
self.assertEqual(facts_modules, ['ios_facts'])
- def test_network_gather_facts_fqcn(self):
+ @patch.object(module_common, '_get_collection_metadata', return_value={})
+ def test_network_gather_facts_fqcn(self, mock_collection_metadata):
self.fqcn_task_vars = {'ansible_network_os': 'cisco.ios.ios'}
self.task.action = 'gather_facts'
+ self.task._ansible_internal_redirect_list = ['cisco.ios.ios_facts']
self.task.async_val = False
self.task.args = {'gather_subset': 'min'}
self.task.module_defaults = [{'cisco.ios.ios_facts': {'gather_subset': 'min'}}]