|
4 | 4 | import os
|
5 | 5 | import re
|
6 | 6 | import subprocess
|
| 7 | +import sys |
7 | 8 | from collections import UserDict
|
8 | 9 | from functools import lru_cache
|
9 |
| -from typing import TYPE_CHECKING, Dict, List, Optional, Tuple |
| 10 | +from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union |
10 | 11 |
|
11 | 12 | from packaging.version import Version
|
12 | 13 |
|
13 | 14 | from ansible_compat.errors import MissingAnsibleError
|
14 | 15 |
|
| 16 | +# mypy/pylint idiom for py36-py38 compatibility |
| 17 | +# https://github.com/python/typeshed/issues/3500#issuecomment-560958608 |
| 18 | +if sys.version_info >= (3, 8): |
| 19 | + from typing import Literal # pylint: disable=no-name-in-module |
| 20 | +else: |
| 21 | + from typing_extensions import Literal |
| 22 | + |
| 23 | + |
15 | 24 | if TYPE_CHECKING:
|
16 | 25 | # https://github.com/PyCQA/pylint/issues/3285
|
17 | 26 | _UserDict = UserDict[str, object] # pylint: disable=unsubscriptable-object
|
@@ -92,7 +101,322 @@ class AnsibleConfig(_UserDict): # pylint: disable=too-many-ancestors
|
92 | 101 | 'COLLECTIONS_PATHS': 'COLLECTIONS_PATH', # 2.9 -> 2.10+
|
93 | 102 | 'COLLECTIONS_PATH': 'COLLECTIONS_PATHS', # 2.10+ -> 2.9
|
94 | 103 | }
|
95 |
| - collections_path: List[str] |
| 104 | + # Expose some attributes to enable auto-complete in editors, based on |
| 105 | + # https://docs.ansible.com/ansible/latest/reference_appendices/config.html |
| 106 | + action_warnings: bool = True |
| 107 | + agnostic_become_prompt: bool = True |
| 108 | + allow_world_readable_tmpfiles: bool = False |
| 109 | + ansible_connection_path: Optional[str] = None |
| 110 | + ansible_cow_acceptlist: List[str] |
| 111 | + ansible_cow_path: Optional[str] = None |
| 112 | + ansible_cow_selection: str = 'default' |
| 113 | + ansible_force_color: bool = False |
| 114 | + ansible_nocolor: bool = False |
| 115 | + ansible_nocows: bool = False |
| 116 | + ansible_pipelining: bool = False |
| 117 | + any_errors_fatal: bool = False |
| 118 | + become_allow_same_user: bool = False |
| 119 | + become_plugin_path: List[str] = [ |
| 120 | + "~/.ansible/plugins/become", |
| 121 | + "/usr/share/ansible/plugins/become", |
| 122 | + ] |
| 123 | + cache_plugin: str = "memory" |
| 124 | + cache_plugin_connection: Optional[str] = None |
| 125 | + cache_plugin_prefix: str = "ansible_facts" |
| 126 | + cache_plugin_timeout: int = 86400 |
| 127 | + callable_accept_list: List[str] = [] |
| 128 | + callbacks_enabled: List[str] = [] |
| 129 | + collections_on_ansible_version_mismatch: Union[ |
| 130 | + Literal["warning"], Literal["warning"], Literal["ignore"] |
| 131 | + ] = "warning" |
| 132 | + collections_paths: List[str] = [ |
| 133 | + "~/.ansible/collections", |
| 134 | + "/usr/share/ansible/collections", |
| 135 | + ] |
| 136 | + collections_scan_sys_path: bool = True |
| 137 | + color_changed: str = "yellow" |
| 138 | + color_console_prompt: str = "white" |
| 139 | + color_debug: str = "dark gray" |
| 140 | + color_deprecate: str = "purple" |
| 141 | + color_diff_add: str = "green" |
| 142 | + color_diff_lines: str = "cyan" |
| 143 | + color_diff_remove: str = "red" |
| 144 | + color_error: str = "red" |
| 145 | + color_highlight: str = "white" |
| 146 | + color_ok: str = "green" |
| 147 | + color_skip: str = "cyan" |
| 148 | + color_unreachable: str = "bright red" |
| 149 | + color_verbose: str = "blue" |
| 150 | + color_warn: str = "bright purple" |
| 151 | + command_warnings: bool = False |
| 152 | + conditional_bare_vars: bool = False |
| 153 | + connection_facts_modules: Dict[str, str] |
| 154 | + controller_python_warning: bool = True |
| 155 | + coverage_remote_output: Optional[str] |
| 156 | + coverage_remote_paths: List[str] |
| 157 | + default_action_plugin_path: List[str] = [ |
| 158 | + "~/.ansible/plugins/action", |
| 159 | + "/usr/share/ansible/plugins/action", |
| 160 | + ] |
| 161 | + default_allow_unsafe_lookups: bool = False |
| 162 | + default_ask_pass: bool = False |
| 163 | + default_ask_vault_pass: bool = False |
| 164 | + default_become: bool = False |
| 165 | + default_become_ask_pass: bool = False |
| 166 | + default_become_exe: Optional[str] = None |
| 167 | + default_become_flags: str |
| 168 | + default_become_method: str = "sudo" |
| 169 | + default_become_user: str = "root" |
| 170 | + default_cache_plugin_path: List[str] = [ |
| 171 | + "~/.ansible/plugins/cache", |
| 172 | + "/usr/share/ansible/plugins/cache", |
| 173 | + ] |
| 174 | + default_callback_plugin_path: List[str] = [ |
| 175 | + "~/.ansible/plugins/callback", |
| 176 | + "/usr/share/ansible/plugins/callback", |
| 177 | + ] |
| 178 | + default_cliconf_plugin_path: List[str] = [ |
| 179 | + "~/.ansible/plugins/cliconf", |
| 180 | + "/usr/share/ansible/plugins/cliconf", |
| 181 | + ] |
| 182 | + default_connection_plugin_path: List[str] = [ |
| 183 | + "~/.ansible/plugins/connection", |
| 184 | + "/usr/share/ansible/plugins/connection", |
| 185 | + ] |
| 186 | + default_debug: bool = False |
| 187 | + default_executable: str = "/bin/sh" |
| 188 | + default_fact_path: Optional[str] = None |
| 189 | + default_filter_plugin_path: List[str] = [ |
| 190 | + "~/.ansible/plugins/filter", |
| 191 | + "/usr/share/ansible/plugins/filter", |
| 192 | + ] |
| 193 | + default_force_handlers: bool = False |
| 194 | + default_forks: int = 5 |
| 195 | + default_gathering: Union[ |
| 196 | + Literal["smart"], Literal["explicit"], Literal["implicit"] |
| 197 | + ] = "smart" |
| 198 | + default_gather_subset: List[str] = ['all'] |
| 199 | + default_gather_timeout: int = 10 |
| 200 | + default_handler_includes_static: bool = False |
| 201 | + default_hash_behaviour: str = "replace" |
| 202 | + default_host_list: List[str] = ["/etc/ansible/hosts"] |
| 203 | + default_httpapi_plugin_path: List[str] = [ |
| 204 | + "~/.ansible/plugins/httpapi", |
| 205 | + "/usr/share/ansible/plugins/httpapi", |
| 206 | + ] |
| 207 | + default_internal_poll_interval: float = 0.001 |
| 208 | + default_inventory_plugin_path: List[str] = [ |
| 209 | + "~/.ansible/plugins/inventory", |
| 210 | + "/usr/share/ansible/plugins/inventory", |
| 211 | + ] |
| 212 | + default_jinja2_extensions: List[str] = [] |
| 213 | + default_jinja2_native: bool = False |
| 214 | + default_keep_remote_files: bool = False |
| 215 | + default_libvirt_lxc_noseclabel: bool = False |
| 216 | + default_load_callback_plugins: bool = False |
| 217 | + default_local_tmp: str = "~/.ansible/tmp" |
| 218 | + default_log_filter: List[str] = [] |
| 219 | + default_log_path: Optional[str] = None |
| 220 | + default_lookup_lugin_path: List[str] = [ |
| 221 | + "~/.ansible/plugins/lookup", |
| 222 | + "/usr/share/ansible/plugins/lookup", |
| 223 | + ] |
| 224 | + default_managed_str: str = "Ansible managed" |
| 225 | + default_module_args: str |
| 226 | + default_module_compression: str = "ZIP_DEFLATED" |
| 227 | + default_module_name: str = "command" |
| 228 | + default_module_path: List[str] = [ |
| 229 | + "~/.ansible/plugins/modules", |
| 230 | + "/usr/share/ansible/plugins/modules", |
| 231 | + ] |
| 232 | + default_module_utils_path: List[str] = [ |
| 233 | + "~/.ansible/plugins/module_utils", |
| 234 | + "/usr/share/ansible/plugins/module_utils", |
| 235 | + ] |
| 236 | + default_netconf_plugin_path: List[str] = [ |
| 237 | + "~/.ansible/plugins/netconf", |
| 238 | + "/usr/share/ansible/plugins/netconf", |
| 239 | + ] |
| 240 | + default_no_log: bool = False |
| 241 | + default_no_target_syslog: bool = False |
| 242 | + default_null_representation: Optional[str] = None |
| 243 | + default_poll_interval: int = 15 |
| 244 | + default_private_key_file: Optional[str] = None |
| 245 | + default_private_role_vars: bool = False |
| 246 | + default_remote_port: Optional[str] = None |
| 247 | + default_remote_user: Optional[str] = None |
| 248 | + default_roles_path: List[str] = [ |
| 249 | + "~/.ansible/roles", |
| 250 | + "/usr/share/ansible/roles:/etc/ansible/roles", |
| 251 | + ] |
| 252 | + default_selinux_special_fs: List[str] = [ |
| 253 | + "fuse", |
| 254 | + "nfs", |
| 255 | + "vboxsf", |
| 256 | + "ramfs", |
| 257 | + "9p", |
| 258 | + "vfat", |
| 259 | + ] |
| 260 | + default_stdout_callback: str = "default" |
| 261 | + default_strategy: str = "linear" |
| 262 | + default_strategy_plugin_path: List[str] = [ |
| 263 | + "~/.ansible/plugins/strategy", |
| 264 | + "/usr/share/ansible/plugins/strategy", |
| 265 | + ] |
| 266 | + default_su: bool = False |
| 267 | + default_syslog_facility: str = "LOG_USER" |
| 268 | + default_task_includes_static: bool = False |
| 269 | + default_terminal_plugin_path: List[str] = [ |
| 270 | + "~/.ansible/plugins/terminal", |
| 271 | + "/usr/share/ansible/plugins/terminal", |
| 272 | + ] |
| 273 | + default_test_plugin_path: List[str] = [ |
| 274 | + "~/.ansible/plugins/test", |
| 275 | + "/usr/share/ansible/plugins/test", |
| 276 | + ] |
| 277 | + default_timeout: int = 10 |
| 278 | + default_transport: str = "smart" |
| 279 | + default_undefined_var_behavior: bool = True |
| 280 | + default_vars_plugin_path: List[str] = [ |
| 281 | + "~/.ansible/plugins/vars", |
| 282 | + "/usr/share/ansible/plugins/vars", |
| 283 | + ] |
| 284 | + default_vault_encrypt_identity: Optional[str] = None |
| 285 | + default_vault_identity: str = "default" |
| 286 | + default_vault_identity_list: List[str] = [] |
| 287 | + default_vault_id_match: bool = False |
| 288 | + default_vault_password_file: Optional[str] = None |
| 289 | + default_verbosity: int = 0 |
| 290 | + deprecation_warnings: bool = False |
| 291 | + devel_warning: bool = True |
| 292 | + diff_always: bool = False |
| 293 | + diff_context: int = 3 |
| 294 | + display_args_to_stdout: bool = False |
| 295 | + display_skipped_hosts: bool = True |
| 296 | + docsite_root_url: str = "https://docs.ansible.com/ansible/" |
| 297 | + doc_fragment_plugin_path: List[str] = [ |
| 298 | + "~/.ansible/plugins/doc_fragments", |
| 299 | + "/usr/share/ansible/plugins/doc_fragments", |
| 300 | + ] |
| 301 | + duplicate_yaml_dict_key: Union[ |
| 302 | + Literal["warn"], Literal["error"], Literal["ignore"] |
| 303 | + ] = "warn" |
| 304 | + enable_task_debugger: bool = False |
| 305 | + error_on_missing_handler: bool = True |
| 306 | + facts_modules: List[str] = ["smart"] |
| 307 | + galaxy_cache_dir: str = "~/.ansible/galaxy_cache" |
| 308 | + galaxy_display_progress: Optional[str] = None |
| 309 | + galaxy_ignore_certs: bool = False |
| 310 | + galaxy_role_skeleton: Optional[str] = None |
| 311 | + galaxy_role_skeleton_ignore: List[str] = ['^.git$', '^.*/.git_keep$'] |
| 312 | + galaxy_server: str = "https://galaxy.ansible.com" |
| 313 | + galaxy_server_list: Optional[str] = None |
| 314 | + galaxy_token_path: str = "~/.ansible/galaxy_token" |
| 315 | + host_key_checking: bool = True |
| 316 | + host_pattern_mismatch: Union[ |
| 317 | + Literal["warning"], Literal["error"], Literal["ignore"] |
| 318 | + ] = "warning" |
| 319 | + inject_facts_as_vars: bool = True |
| 320 | + interpreter_python: str = "auto_legacy" |
| 321 | + interpreter_python_distro_map: Dict[str, str] |
| 322 | + interpreter_python_fallback: List[str] |
| 323 | + invalid_task_attribute_failed: bool = True |
| 324 | + inventory_any_unparsed_is_failed: bool = False |
| 325 | + inventory_cache_enabled: bool = False |
| 326 | + inventory_cache_plugin: Optional[str] = None |
| 327 | + inventory_cache_plugin_connection: Optional[str] = None |
| 328 | + inventory_cache_plugin_prefix: str = "ansible_facts" |
| 329 | + inventory_cache_timeout: int = 3600 |
| 330 | + inventory_enabled: List[str] = [ |
| 331 | + 'host_list', |
| 332 | + 'script', |
| 333 | + 'auto', |
| 334 | + 'yaml', |
| 335 | + 'ini', |
| 336 | + 'toml', |
| 337 | + ] |
| 338 | + inventory_export: bool = False |
| 339 | + inventory_ignore_exts: str |
| 340 | + inventory_ignore_patterns: List[str] = [] |
| 341 | + inventory_unparsed_is_failed: bool = False |
| 342 | + localhost_warning: bool = True |
| 343 | + max_file_size_for_diff: int = 104448 |
| 344 | + module_ignore_exts: str |
| 345 | + netconf_ssh_config: Optional[str] = None |
| 346 | + network_group_modules: List[str] = [ |
| 347 | + 'eos', |
| 348 | + 'nxos', |
| 349 | + 'ios', |
| 350 | + 'iosxr', |
| 351 | + 'junos', |
| 352 | + 'enos', |
| 353 | + 'ce', |
| 354 | + 'vyos', |
| 355 | + 'sros', |
| 356 | + 'dellos9', |
| 357 | + 'dellos10', |
| 358 | + 'dellos6', |
| 359 | + 'asa', |
| 360 | + 'aruba', |
| 361 | + 'aireos', |
| 362 | + 'bigip', |
| 363 | + 'ironware', |
| 364 | + 'onyx', |
| 365 | + 'netconf', |
| 366 | + 'exos', |
| 367 | + 'voss', |
| 368 | + 'slxos', |
| 369 | + ] |
| 370 | + old_plugin_cache_clearing: bool = False |
| 371 | + paramiko_host_key_auto_add: bool = False |
| 372 | + paramiko_look_for_keys: bool = True |
| 373 | + persistent_command_timeout: int = 30 |
| 374 | + persistent_connect_retry_timeout: int = 15 |
| 375 | + persistent_connect_timeout: int = 30 |
| 376 | + persistent_control_path_dir: str = "~/.ansible/pc" |
| 377 | + playbook_dir: Optional[str] |
| 378 | + playbook_vars_root: Union[Literal["top"], Literal["bottom"], Literal["all"]] = "top" |
| 379 | + plugin_filters_cfg: Optional[str] = None |
| 380 | + python_module_rlimit_nofile: int = 0 |
| 381 | + retry_files_enabled: bool = False |
| 382 | + retry_files_save_path: Optional[str] = None |
| 383 | + run_vars_plugins: str = "demand" |
| 384 | + show_custom_stats: bool = False |
| 385 | + string_conversion_action: Union[ |
| 386 | + Literal["warn"], Literal["error"], Literal["ignore"] |
| 387 | + ] = "warn" |
| 388 | + string_type_filters: List[str] = [ |
| 389 | + 'string', |
| 390 | + 'to_json', |
| 391 | + 'to_nice_json', |
| 392 | + 'to_yaml', |
| 393 | + 'to_nice_yaml', |
| 394 | + 'ppretty', |
| 395 | + 'json', |
| 396 | + ] |
| 397 | + system_warnings: bool = True |
| 398 | + tags_run: List[str] = [] |
| 399 | + tags_skip: List[str] = [] |
| 400 | + task_debugger_ignore_errors: bool = True |
| 401 | + task_timeout: int = 0 |
| 402 | + transform_invalid_group_chars: Union[ |
| 403 | + Literal["always"], Literal["never"], Literal["ignore"], Literal["silently"] |
| 404 | + ] = "never" |
| 405 | + use_persistent_connections: bool = False |
| 406 | + variable_plugins_enabled: List[str] = ['host_group_vars'] |
| 407 | + variable_precedence: List[str] = [ |
| 408 | + 'all_inventory', |
| 409 | + 'groups_inventory', |
| 410 | + 'all_plugins_inventory', |
| 411 | + 'all_plugins_play', |
| 412 | + 'groups_plugins_inventory', |
| 413 | + 'groups_plugins_play', |
| 414 | + ] |
| 415 | + verbose_to_stderr: bool = False |
| 416 | + win_async_startup_timeout: int = 5 |
| 417 | + worker_shutdown_poll_count: int = 0 |
| 418 | + worker_shutdown_poll_delay: float = 0.1 |
| 419 | + yaml_filename_extensions: List[str] = ['.yml', '.yaml', '.json'] |
96 | 420 |
|
97 | 421 | def __init__(
|
98 | 422 | self,
|
@@ -144,3 +468,10 @@ def __copy__(self) -> "AnsibleConfig":
|
144 | 468 | def __deepcopy__(self, memo: object) -> "AnsibleConfig":
|
145 | 469 | """Allow users to run deeepcopy on Config."""
|
146 | 470 | return AnsibleConfig(data=self.data)
|
| 471 | + |
| 472 | + def _dump_config_attrs(self) -> None: # pragma: no cover |
| 473 | + """Dump config attributes using pytest typed format.""" |
| 474 | + for item in sorted(self.data): |
| 475 | + name = item.lower() |
| 476 | + kind = self.data[item].__class__.__name__ |
| 477 | + print(f"{name}: {kind}") |
0 commit comments