diff options
38 files changed, 645 insertions, 314 deletions
diff --git a/.ansible-lint b/.ansible-lint index 2e1a9d6f9..9790df05b 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -1,13 +1,13 @@ --- exclude_paths: - releasenotes - - roles - tests - zuul.d +rulesdir: + - .ansible-lint-rules/ # NOTE(mnasiadka): Switched to false due to rules skipped via .ansible-lint-ignore causing # failures strict: false -use_default_rules: true skip_list: # disable experimental rules - experimental @@ -16,5 +16,9 @@ skip_list: - fqcn-builtins # FQCNs again, now for module actions - fqcn[action] + # Role names + - role-name - var-naming[no-role-prefix] - yaml[line-length] + +use_default_rules: true diff --git a/.ansible-lint-rules/container_exec_become.py b/.ansible-lint-rules/container_exec_become.py new file mode 100644 index 000000000..00d420250 --- /dev/null +++ b/.ansible-lint-rules/container_exec_become.py @@ -0,0 +1,271 @@ +# Copyright 2026 Michal Nasiadka +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Custom ansible-lint rule to enforce become on container exec commands.""" + +from typing import Any + +from ansiblelint.errors import MatchError +from ansiblelint.file_utils import Lintable +from ansiblelint.rules import AnsibleLintRule + + +class ContainerExecBecomeRule(AnsibleLintRule): + + id = "container-exec-become" + description = """shell/command tasks starting with 'docker exec' or + 'podman exec' should have become set to True""" + severity = "MEDIUM" + tags = ["security", "container"] + version_added = "v6.0.0" + version_changed = "v6.0.0" + + def matchyaml(self, file: Lintable) -> list[MatchError]: + """Check if container exec commands have become set to True. + + Args: + file: The file being linted + + Returns: + List of MatchError objects if violations found + """ + errors = [] + + # Get the parsed YAML data + data = file.data + if not data: + return errors + + # Process plays or task files + if isinstance(data, list): + # Check if this is a playbook (contains plays) or + # a task file (just tasks) + if data and isinstance(data[0], dict): + # If first item has 'hosts' or 'import_playbook', + # it's a playbook + first_item = data[0] + if 'hosts' in first_item or 'import_playbook' in first_item: + # Process as playbook + for play_idx, play in enumerate(data): + if not isinstance(play, dict): + continue + + # Check tasks at play level + self._check_tasks(play.get('tasks', []), None, errors, + file, f".[{play_idx}].tasks") + + # Check pre_tasks + self._check_tasks(play.get('pre_tasks', []), None, + errors, file, + f".[{play_idx}].pre_tasks") + + # Check post_tasks + self._check_tasks(play.get('post_tasks', []), None, + errors, file, + f".[{play_idx}].post_tasks") + + # Check handlers + self._check_tasks(play.get('handlers', []), None, + errors, file, + f".[{play_idx}].handlers") + else: + # Process as task file (list of tasks directly) + self._check_tasks(data, None, errors, file, ".") + + return errors + + def _check_tasks( + self, + tasks: list[dict[str, Any]], + parent_become: bool | None, + errors: list[MatchError], + file: Lintable, + path: str + ) -> None: + """Recursively check tasks and blocks. + + Check for container exec commands with become. + + Args: + tasks: List of tasks to check + parent_become: The become value inherited from parent block + errors: List to append errors to + file: The file being linted + path: Current path in the YAML structure + """ + if not tasks: + return + + for task_idx, task in enumerate(tasks): + if not isinstance(task, dict): + continue + + task_path = f"{path}[{task_idx}]" + + # Determine effective become value for this task + task_become = task.get('become') + if task_become is not None: + effective_become = task_become + else: + effective_become = parent_become + + # Check if this is a block + if 'block' in task: + # For blocks, pass down the effective become value + block_become = task.get('become') + if block_become is not None: + inherited_become = block_become + else: + inherited_become = parent_become + + # Recursively check tasks in the block + self._check_tasks( + task.get('block', []), + inherited_become, + errors, + file, + f"{task_path}.block" + ) + + # Also check rescue and always sections + if 'rescue' in task: + self._check_tasks( + task.get('rescue', []), + inherited_become, + errors, + file, + f"{task_path}.rescue" + ) + + if 'always' in task: + self._check_tasks( + task.get('always', []), + inherited_become, + errors, + file, + f"{task_path}.always" + ) + + continue + + # Check if this task uses shell or command module + module_name = None + command_value = None + + # Check for shell/command modules + shell_modules = [ + 'ansible.builtin.shell', 'shell', + 'ansible.builtin.command', 'command' + ] + + for shell_module in shell_modules: + if shell_module in task: + module_name = shell_module + # Get the command - can be a string or dict + cmd = task[shell_module] + if isinstance(cmd, str): + command_value = cmd + elif isinstance(cmd, dict): + # Command might be in 'cmd' key or the module args + command_value = (cmd.get('cmd') or + cmd.get('_raw_params')) + break + + # If this is a shell/command task, check if it starts with + # docker/podman exec + if module_name and command_value: + # Strip leading whitespace and newlines, check if it starts + # with docker/podman exec + cmd_stripped = command_value.strip() + + # Check for hardcoded docker/podman exec (should use variable) + uses_hardcoded_exec = ( + cmd_stripped.startswith('docker exec') or + cmd_stripped.startswith('podman exec') + ) + + if uses_hardcoded_exec: + # Flag hardcoded container engine usage + task_name = task.get('name', 'unnamed task') + if cmd_stripped.startswith('docker exec'): + exec_type = 'docker exec' + else: + exec_type = 'podman exec' + + message = (f"Task '{task_name}' uses hardcoded " + f"'{exec_type}' - use " + f"'{{{{ kolla_container_engine }}}} exec' " + f"instead") + + errors.append( + self.create_matcherror( + message=message, + filename=file, + lineno=task.get('__line__', 1) + ) + ) + # Continue to also check become requirement + + # Check for variable-based container engine followed by exec + # e.g., "{{ kolla_container_engine }} exec", + # "{{ container_engine }} exec" + import re + variable_exec_pattern = r'^\{\{[^}]+\}\}\s+exec\s+' + uses_variable_exec = re.match(variable_exec_pattern, + cmd_stripped) + + is_container_exec = uses_hardcoded_exec or uses_variable_exec + + if is_container_exec: + # Check if become is True + if effective_become is not True: + task_name = task.get('name', 'unnamed task') + + # Determine exec type for error message + if cmd_stripped.startswith('docker exec'): + exec_type = 'docker exec' + elif cmd_stripped.startswith('podman exec'): + exec_type = 'podman exec' + else: + exec_type = 'container exec (via variable)' + + if task_become is False: + message = (f"Task '{task_name}' uses " + f"'{exec_type}' but has " + f"'become: false'") + if parent_become is True: + message += """ which overrides block-level + 'become: true'""" + elif task_become is None and parent_become is False: + message = (f"Task '{task_name}' uses " + f"'{exec_type}' and inherits " + f"'become: false' from block") + elif task_become is None and parent_become is None: + message = (f"Task '{task_name}' uses " + f"'{exec_type}' but is missing " + f"'become: true' at task or " + f"block level") + else: + message = (f"Task '{task_name}' uses " + f"'{exec_type}' but has " + f"'become: {task_become}' instead of " + f"'true'") + + errors.append( + self.create_matcherror( + message=message, + filename=file, + lineno=task.get('__line__', 1) + ) + ) diff --git a/.ansible-lint-rules/kolla_container_become.py b/.ansible-lint-rules/kolla_container_become.py new file mode 100644 index 000000000..867b728dd --- /dev/null +++ b/.ansible-lint-rules/kolla_container_become.py @@ -0,0 +1,209 @@ +# Copyright 2026 Michal Nasiadka +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Custom ansible-lint rule to enforce become on + kolla_container/kolla_container_facts/kolla_toolbox modules.""" + +from typing import Any + +from ansiblelint.errors import MatchError +from ansiblelint.file_utils import Lintable +from ansiblelint.rules import AnsibleLintRule + + +class KollaContainerBecomeRule(AnsibleLintRule): + """Kolla container modules should have become set to true.""" + + id = "kolla-container-become" + description = """Kolla container module invocations should have become set + to true (task or block level)""" + severity = "MEDIUM" + tags = ["security", "kolla"] + version_added = "v6.0.0" + version_changed = "v6.0.0" + + def matchyaml(self, file: Lintable) -> list[MatchError]: + """Check if Kolla container module tasks have become set to True. + + Args: + file: The file being linted + + Returns: + List of MatchError objects if violations found + """ + errors = [] + + # Get the parsed YAML data + data = file.data + if not data: + return errors + + # Process plays or task files + if isinstance(data, list): + # Check if this is a playbook (contains plays) or + # a task file (just tasks) + if data and isinstance(data[0], dict): + # If first item has 'hosts' or 'import_playbook', + # it's a playbook + first_item = data[0] + if 'hosts' in first_item or 'import_playbook' in first_item: + # Process as playbook + for play_idx, play in enumerate(data): + if not isinstance(play, dict): + continue + + # Check tasks at play level + self._check_tasks(play.get('tasks', []), None, errors, + file, f".[{play_idx}].tasks") + + # Check pre_tasks + self._check_tasks(play.get('pre_tasks', []), None, + errors, file, + f".[{play_idx}].pre_tasks") + + # Check post_tasks + self._check_tasks(play.get('post_tasks', []), None, + errors, file, + f".[{play_idx}].post_tasks") + + # Check handlers + self._check_tasks(play.get('handlers', []), None, + errors, file, + f".[{play_idx}].handlers") + else: + # Process as task file (list of tasks directly) + self._check_tasks(data, None, errors, file, ".") + + return errors + + def _check_tasks( + self, + tasks: list[dict[str, Any]], + parent_become: bool | None, + errors: list[MatchError], + file: Lintable, + path: str + ) -> None: + """Recursively check tasks and blocks. + + Checks kolla_container/kolla_container_facts/kolla_toolbox modules + with become. + + Args: + tasks: List of tasks to check + parent_become: The become value inherited from parent block + errors: List to append errors to + file: The file being linted + path: Current path in the YAML structure + """ + + if not tasks: + return + + for task_idx, task in enumerate(tasks): + if not isinstance(task, dict): + continue + + task_path = f"{path}[{task_idx}]" + + # Determine effective become value for this task + task_become = task.get('become') + if task_become is not None: + effective_become = task_become + else: + effective_become = parent_become + + # Check if this is a block + if 'block' in task: + # For blocks, pass down the effective become value + block_become = task.get('become') + if block_become is not None: + inherited_become = block_become + else: + inherited_become = parent_become + + # Recursively check tasks in the block + self._check_tasks( + task.get('block', []), + inherited_become, + errors, + file, + f"{task_path}.block" + ) + + # Also check rescue and always sections + if 'rescue' in task: + self._check_tasks( + task.get('rescue', []), + inherited_become, + errors, + file, + f"{task_path}.rescue" + ) + + if 'always' in task: + self._check_tasks( + task.get('always', []), + inherited_become, + errors, + file, + f"{task_path}.always" + ) + + continue + + # Check if this task uses Kolla container modules + module_name = None + + # Check for Kolla modules in various formats + kolla_modules = ['kolla_container', 'kolla_container_facts', + 'kolla_toolbox'] + + for kolla_module in kolla_modules: + if kolla_module in task: + module_name = kolla_module + break + + # If this is a Kolla container task, check for become + if module_name: + if effective_become is not True: + task_name = task.get('name', 'unnamed task') + + if task_become is False: + message = (f"Kolla container task '{task_name}' " + f"(module: {module_name}) has 'become: " + f"false'") + if parent_become is True: + message += """ which overrides block-level + 'become: true'""" + elif task_become is None and parent_become is False: + message = (f"Kolla container task '{task_name}' " + f"(module: {module_name}) inherits " + f"'become: false' from block") + elif task_become is None and parent_become is None: + message = (f"Kolla container task '{task_name}' " + f"(module: {module_name}) is missing " + f"'become: true' at task or block level") + else: + message = (f"Kolla container task '{task_name}' " + f"(module: {module_name}) has 'become: " + f"{task_become}' instead of 'true'") + + errors.append( + self.create_matcherror( + message=message, + filename=file, + lineno=task.get('__line__', 1) + ) + ) diff --git a/ansible/roles/haproxy-config/tasks/main.yml b/ansible/roles/haproxy-config/tasks/main.yml index 4a93e428e..b0f88b9c4 100644 --- a/ansible/roles/haproxy-config/tasks/main.yml +++ b/ansible/roles/haproxy-config/tasks/main.yml @@ -1,5 +1,5 @@ --- -- name: "Copying over {{ project_name }} haproxy config" +- name: "Copying over haproxy config for {{ project_name }}" vars: service: "{{ item.value }}" haproxy_templates: @@ -20,7 +20,7 @@ - enable_haproxy | bool with_dict: "{{ project_services }}" -- name: "Add configuration for {{ project_name }} when using single external frontend" +- name: "Add configuration when using single external frontend for {{ project_name }}" vars: service: "{{ item.value }}" blockinfile: diff --git a/ansible/roles/loadbalancer-config/tasks/main.yml b/ansible/roles/loadbalancer-config/tasks/main.yml index 5658d8515..3e82e0b35 100644 --- a/ansible/roles/loadbalancer-config/tasks/main.yml +++ b/ansible/roles/loadbalancer-config/tasks/main.yml @@ -1,8 +1,10 @@ --- -- import_role: +- name: Import haproxy-config role + import_role: name: haproxy-config when: haproxy_config_install | bool -- import_role: +- name: Import proxysql-config role + import_role: name: proxysql-config when: enable_proxysql | bool diff --git a/ansible/roles/module-load/tasks/main.yml b/ansible/roles/module-load/tasks/main.yml index 3037f87f3..8a1bedccb 100644 --- a/ansible/roles/module-load/tasks/main.yml +++ b/ansible/roles/module-load/tasks/main.yml @@ -20,6 +20,7 @@ template: src: module-load.conf.j2 dest: "/etc/modules-load.d/{{ item.name }}.conf" + mode: "0644" loop: "{{ modules }}" loop_control: label: "{{ item.name }}" diff --git a/ansible/roles/proxysql-config/tasks/main.yml b/ansible/roles/proxysql-config/tasks/main.yml index 6e637f30c..7ce2b208f 100644 --- a/ansible/roles/proxysql-config/tasks/main.yml +++ b/ansible/roles/proxysql-config/tasks/main.yml @@ -1,5 +1,5 @@ --- -- name: "Copying over {{ proxysql_project }} ProxySQL users config" +- name: "Copying over ProxySQL users config for {{ proxysql_project }}" template: src: "users.yaml.j2" dest: "{{ node_config_directory }}/proxysql/users/{{ proxysql_project }}.yaml" @@ -8,7 +8,7 @@ when: - proxysql_config_users | bool -- name: "Copying over {{ proxysql_project }} ProxySQL rules config" +- name: "Copying over ProxySQL rules config for {{ proxysql_project }}" template: src: "rules.yaml.j2" dest: "{{ node_config_directory }}/proxysql/rules/{{ proxysql_project }}.yaml" diff --git a/ansible/roles/service-cert-copy/tasks/main.yml b/ansible/roles/service-cert-copy/tasks/main.yml index e9dd74eab..06f213095 100644 --- a/ansible/roles/service-cert-copy/tasks/main.yml +++ b/ansible/roles/service-cert-copy/tasks/main.yml @@ -1,5 +1,5 @@ --- -- name: "{{ project_name }} | Copying over extra CA certificates" +- name: "Copying over extra CA certificates for {{ project_name }}" become: true copy: src: "{{ kolla_certificates_dir }}/ca/" @@ -9,7 +9,7 @@ - kolla_copy_ca_into_containers | bool with_dict: "{{ project_services | select_services_enabled_and_mapped_to_host }}" -- name: "{{ project_name }} | Copying over backend internal TLS certificate" +- name: "Copying over backend internal TLS certificate for {{ project_name }}" vars: certs: - "{{ kolla_certificates_dir }}/{{ inventory_hostname }}/{{ project_name }}-cert.pem" @@ -27,7 +27,7 @@ - inventory_hostname is in groups["tls-backend"] with_dict: "{{ project_services | select_services_enabled_and_mapped_to_host }}" -- name: "{{ project_name }} | Copying over backend internal TLS key" +- name: "Copying over backend internal TLS key for {{ project_name }}" vars: keys: - "{{ kolla_certificates_dir }}/{{ inventory_hostname }}/{{ project_name }}-key.pem" diff --git a/ansible/roles/service-check-containers/tasks/iterated.yml b/ansible/roles/service-check-containers/tasks/iterated.yml index a08614de6..fcbe77eef 100644 --- a/ansible/roles/service-check-containers/tasks/iterated.yml +++ b/ansible/roles/service-check-containers/tasks/iterated.yml @@ -1,5 +1,5 @@ --- -- name: "{{ kolla_role_name | default(project_name) }} | Check containers with iteration" +- name: "Check containers with iteration for {{ kolla_role_name | default(project_name) }}" become: true vars: service: "{{ outer_item.value }}" @@ -23,13 +23,13 @@ command: "{{ service.command | default(omit) }}" cgroupns_mode: "{{ service.cgroupns_mode | default(omit) }}" loop: - - "{{ range(1,(service.iterate_var | int) + 1) | list }}" + - "{{ range(1, (service.iterate_var | int) + 1) | list }}" register: container_check # NOTE(yoctozepto): Must be a separate task because one cannot see the whole # result in the previous task and Ansible has a quirk regarding notifiers. # For details see https://github.com/ansible/ansible/issues/22579 -- name: "{{ kolla_role_name | default(project_name) }} | Notify handlers to restart containers" +- name: "Notify handlers to restart containers for {{ kolla_role_name | default(project_name) }}" debug: msg: Notifying handlers changed_when: container_check is changed diff --git a/ansible/roles/service-check-containers/tasks/main.yml b/ansible/roles/service-check-containers/tasks/main.yml index 9e4c2e532..e68016aaa 100644 --- a/ansible/roles/service-check-containers/tasks/main.yml +++ b/ansible/roles/service-check-containers/tasks/main.yml @@ -1,7 +1,7 @@ --- # NOTE(r-krcek): List of arguments should follow argument_spec in # kolla_container module -- name: "{{ kolla_role_name | default(project_name) }} | Check containers" +- name: "Check containers for {{ kolla_role_name | default(project_name) }}" become: true vars: service: "{{ item.value }}" @@ -31,7 +31,7 @@ # NOTE(yoctozepto): Must be a separate task because one cannot see the whole # result in the previous task and Ansible has a quirk regarding notifiers. # For details see https://github.com/ansible/ansible/issues/22579 -- name: "{{ kolla_role_name | default(project_name) }} | Notify handlers to restart containers" +- name: "Notify handlers to restart containers for {{ kolla_role_name | default(project_name) }}" vars: service: "{{ item.value }}" debug: @@ -40,7 +40,7 @@ when: not (service.iterate | default(False)) | bool notify: "{{ container_check.results | select('changed') | map(attribute='item.key') | map('regex_replace', '^(.*)$', 'Restart \\1 container') | list }}" -- name: "{{ kolla_role_name | default(project_name) }} | Check containers that require iteration" +- name: "Check containers that require iteration for {{ kolla_role_name | default(project_name) }}" vars: service: "{{ outer_item.value }}" include_tasks: iterated.yml diff --git a/ansible/roles/service-check/tasks/main.yml b/ansible/roles/service-check/tasks/main.yml index e9af8998b..de614f149 100644 --- a/ansible/roles/service-check/tasks/main.yml +++ b/ansible/roles/service-check/tasks/main.yml @@ -1,6 +1,6 @@ --- # Check whether all necessary containers are running. -- name: "{{ kolla_role_name | default(project_name) }} | Get container facts" +- name: "Get container facts for {{ kolla_role_name | default(project_name) }}" become: true kolla_container_facts: action: get_containers @@ -9,7 +9,7 @@ register: container_facts when: service_check_enabled_container_names | length > 0 -- name: "{{ kolla_role_name | default(project_name) }} | Fail if containers are missing or not running" +- name: "Fail if containers are missing or not running for {{ kolla_role_name | default(project_name) }}" vars: missing_containers: >- {{ service_check_enabled_container_names | @@ -23,7 +23,7 @@ - container_facts.containers is defined - missing_containers | length > 0 -- name: "{{ kolla_role_name | default(project_name) }} | Fail if containers are unhealthy" +- name: "Fail if containers are unhealthy for {{ kolla_role_name | default(project_name) }}" vars: unhealthy_containers: >- {{ container_facts.containers | diff --git a/ansible/roles/service-config-validate/tasks/main.yml b/ansible/roles/service-config-validate/tasks/main.yml index ae2cbe2ea..bc737328d 100644 --- a/ansible/roles/service-config-validate/tasks/main.yml +++ b/ansible/roles/service-config-validate/tasks/main.yml @@ -1,5 +1,5 @@ --- -- name: "{{ project_name }} | Validate configurations for each service" +- name: "Validate configurations for each service for {{ project_name }}" vars: service_name: "{{ outer_item.key }}" service: "{{ outer_item.value }}" diff --git a/ansible/roles/service-config-validate/tasks/validate.yml b/ansible/roles/service-config-validate/tasks/validate.yml index 9cf956ed7..d5fb827f4 100644 --- a/ansible/roles/service-config-validate/tasks/validate.yml +++ b/ansible/roles/service-config-validate/tasks/validate.yml @@ -1,5 +1,5 @@ --- -- name: "{{ project_name }} : {{ service.container_name }} | Get info on container" +- name: "Get info on container for {{ service.container_name }}" become: true kolla_container_facts: action: get_containers @@ -8,7 +8,7 @@ - "{{ service.container_name }}" register: container_info -- name: "{{ project_name }} : {{ service.container_name }} | Validate configurations" +- name: "Validate configurations for {{ service.container_name }}" become: true command: > {{ kolla_container_engine }} exec {{ service.container_name }} @@ -23,21 +23,23 @@ loop_var: inner_item changed_when: false -- name: "{{ project_name }} : {{ service.container_name }} | Ensure log directory exists" +- name: "Ensure log directory exists for {{ service.container_name }}" become: true file: path: "{{ output_dir }}" state: directory + mode: "0755" when: - result.results | map(attribute='rc', default=0) | select('equalto', 1) | list | length > 0 - result.results | map(attribute='stderr', default="") | select('ne', "") | list | length > 0 delegate_to: localhost -- name: "{{ project_name }} : {{ service.container_name }} | Log configuration errors" +- name: "Log configuration errors for {{ service.container_name }}" become: true copy: content: "{{ inner_item.stderr }}" dest: "{{ output_dir }}/{{ inner_item.inner_item.config | basename }}.err" + mode: "0644" when: - container_info.containers | length > 0 - inner_item.rc is defined diff --git a/ansible/roles/service-images-pull/tasks/main.yml b/ansible/roles/service-images-pull/tasks/main.yml index fbb9e8b8b..ca2aafa3d 100644 --- a/ansible/roles/service-images-pull/tasks/main.yml +++ b/ansible/roles/service-images-pull/tasks/main.yml @@ -1,5 +1,5 @@ --- -- name: "{{ kolla_role_name | default(project_name) }} | Pull images" +- name: "Pull images for {{ kolla_role_name | default(project_name) }}" vars: service: "{{ item.value }}" become: true diff --git a/ansible/roles/service-ks-register/tasks/main.yml b/ansible/roles/service-ks-register/tasks/main.yml index 58a308125..242e597b6 100644 --- a/ansible/roles/service-ks-register/tasks/main.yml +++ b/ansible/roles/service-ks-register/tasks/main.yml @@ -1,6 +1,9 @@ --- -- block: - - name: "{{ project_name }} | Creating/deleting services" +- name: "Create/delete services/endpoints/projects/users/roles for {{ project_name }}" + become: true + run_once: true + block: + - name: "Creating/deleting services for {{ project_name }}" kolla_toolbox: container_engine: "{{ kolla_container_engine }}" module_name: openstack.cloud.catalog_service @@ -22,7 +25,7 @@ delay: "{{ service_ks_register_delay }}" when: item.enabled | default(True) | bool - - name: "{{ project_name }} | Creating/deleting endpoints" + - name: "Creating/deleting endpoints for {{ project_name }}" kolla_toolbox: container_engine: "{{ kolla_container_engine }}" module_name: openstack.cloud.endpoint @@ -47,7 +50,7 @@ delay: "{{ service_ks_register_delay }}" when: item.0.enabled | default(True) | bool - - name: "{{ project_name }} | Creating projects" + - name: "Creating projects for {{ project_name }}" kolla_toolbox: container_engine: "{{ kolla_container_engine }}" module_name: openstack.cloud.project @@ -64,7 +67,7 @@ retries: "{{ service_ks_register_retries }}" delay: "{{ service_ks_register_delay }}" - - name: "{{ project_name }} | Creating/deleting users" + - name: "Creating/deleting users for {{ project_name }}" kolla_toolbox: container_engine: "{{ kolla_container_engine }}" module_name: openstack.cloud.identity_user @@ -90,7 +93,7 @@ retries: "{{ service_ks_register_retries }}" delay: "{{ service_ks_register_delay }}" - - name: "{{ project_name }} | Creating roles" + - name: "Creating roles for {{ project_name }}" kolla_toolbox: container_engine: "{{ kolla_container_engine }}" module_name: openstack.cloud.identity_role @@ -106,7 +109,7 @@ retries: "{{ service_ks_register_retries }}" delay: "{{ service_ks_register_delay }}" - - name: "{{ project_name }} | Granting/revoking user roles" + - name: "Granting/revoking user roles for {{ project_name }}" kolla_toolbox: container_engine: "{{ kolla_container_engine }}" module_name: openstack.cloud.role_assignment @@ -128,6 +131,3 @@ until: service_ks_register_result is success retries: "{{ service_ks_register_retries }}" delay: "{{ service_ks_register_delay }}" - - become: true - run_once: True diff --git a/ansible/roles/service-precheck/tasks/main.yml b/ansible/roles/service-precheck/tasks/main.yml index 24d0259d0..1660bb474 100644 --- a/ansible/roles/service-precheck/tasks/main.yml +++ b/ansible/roles/service-precheck/tasks/main.yml @@ -1,5 +1,5 @@ --- -- name: "{{ project_name }} | Validate inventory groups" +- name: "Validate inventory groups for {{ project_name }}" vars: service_name: "{{ item.key }}" service: "{{ item.value }}" diff --git a/ansible/roles/service-stop/tasks/main.yml b/ansible/roles/service-stop/tasks/main.yml index ea502f714..63cf1ec68 100644 --- a/ansible/roles/service-stop/tasks/main.yml +++ b/ansible/roles/service-stop/tasks/main.yml @@ -1,5 +1,5 @@ --- -- name: "Stopping {{ service_name }} containers" +- name: "Stopping containers for {{ service_name }}" vars: service: "{{ item.value }}" become: true diff --git a/ansible/roles/service-uwsgi-config/tasks/main.yml b/ansible/roles/service-uwsgi-config/tasks/main.yml index c0e21a331..5e36d8433 100644 --- a/ansible/roles/service-uwsgi-config/tasks/main.yml +++ b/ansible/roles/service-uwsgi-config/tasks/main.yml @@ -1,5 +1,5 @@ --- -- name: "Copying over {{ service_name }} uWSGI config" +- name: "Copying over uWSGI config for {{ service_name }}" template: src: "uwsgi.ini.j2" dest: "{{ service_uwsgi_config_file }}" diff --git a/roles/bridge/tasks/main.yml b/roles/bridge/tasks/main.yml index f96c19e4f..a764d41f2 100644 --- a/roles/bridge/tasks/main.yml +++ b/roles/bridge/tasks/main.yml @@ -1,12 +1,18 @@ --- - name: Create bridge become: true - command: ip link add {{ bridge_name }} type bridge + changed_when: true + ansible.builtin.command: + cmd: ip link add {{ bridge_name }} type bridge - name: Bring bridge interface up become: true - command: ip link set {{ bridge_name }} up + changed_when: true + ansible.builtin.command: + cmd: ip link set {{ bridge_name }} up - name: Add member interface to bridge become: true - command: ip link set {{ bridge_member_name }} master {{ bridge_name }} + changed_when: true + ansible.builtin.command: + cmd: ip link set {{ bridge_member_name }} master {{ bridge_name }} diff --git a/roles/cephadm/tasks/main.yml b/roles/cephadm/tasks/main.yml index 63ba7b0e3..7f0133779 100644 --- a/roles/cephadm/tasks/main.yml +++ b/roles/cephadm/tasks/main.yml @@ -1,39 +1,43 @@ --- -- include_tasks: pkg_{{ ansible_os_family | lower }}.yml +- name: Include package installation + include_tasks: pkg_{{ ansible_os_family | lower }}.yml - name: Ensure /etc/ceph exists file: path: /etc/ceph state: directory - become: True + mode: "0755" + become: true - name: Generate ssh key for cephadm openssh_keypair: path: "/etc/ceph/cephadm.id" + mode: "0600" size: 4096 comment: "cephadm" - become: True + become: true register: cephadm_ssh_key - name: Save public key copy: content: "{{ cephadm_ssh_key.public_key }}" dest: /etc/ceph/cephadm.pub - become: True + mode: "0644" + become: true - name: Copy cephadm public key to all hosts authorized_key: user: root state: present key: "{{ cephadm_ssh_key.public_key }}" - become: True + become: true with_inventory_hostnames: - all delegate_to: "{{ item }}" - name: Bootstrap cephadm vars: - mon_ip: "{{ hostvars[inventory_hostname]['ansible_' + api_interface_name | replace('-','_')].ipv4.address }}" + mon_ip: "{{ hostvars[inventory_hostname]['ansible_' + api_interface_name | replace('-', '_')].ipv4.address }}" command: cmd: > cephadm @@ -46,7 +50,8 @@ --skip-firewalld --log-to-file --mon-ip {{ mon_ip }} - become: True + become: true + changed_when: true register: cephadm_bootstrap_output - name: Get ceph fsid @@ -59,20 +64,23 @@ template: src: templates/cephadm.yml.j2 dest: "/var/run/ceph/{{ ceph_fsid }}/cluster.yml" - become: True + mode: "0600" + become: true - name: Template out command spec template: src: templates/commands.sh.j2 dest: "/var/run/ceph/{{ ceph_fsid }}/commands.sh" - become: True + mode: "0600" + become: true - name: Run commands command: cmd: > cephadm shell -- bash -x /var/run/ceph/commands.sh - become: True + become: true + changed_when: true # TODO(mnasiadka): Fix merge_configs to support tabs - name: Generate ceph.conf without tabs @@ -80,8 +88,9 @@ ceph_conf_fixed: | [global] fsid = {{ ceph_fsid }} - mon_host = {% for host in groups['all'] %} {{ hostvars[host]['ansible_' + api_interface_name | replace('-','_')].ipv4.address }} {% if not loop.last %},{% endif %} {% endfor %} + mon_host = {% for host in groups['all'] %} {{ hostvars[host]['ansible_' + api_interface_name | replace('-', '_')].ipv4.address }} {% if not loop.last %},{% endif %} {% endfor %} copy: content: "{{ ceph_conf_fixed }}" dest: "/etc/ceph/ceph.conf.fixed" - become: True + mode: "0644" + become: true diff --git a/roles/cephadm/tasks/pkg_debian.yml b/roles/cephadm/tasks/pkg_debian.yml index da1747982..92dd08221 100644 --- a/roles/cephadm/tasks/pkg_debian.yml +++ b/roles/cephadm/tasks/pkg_debian.yml @@ -1,23 +1,23 @@ --- - name: Ensure apt sources list directory exists + become: true file: path: /etc/apt/sources.list.d state: directory - recurse: yes - become: True + recurse: true - name: Enable Ceph apt repository + become: true apt_repository: repo: "{{ cephadm_ceph_apt_repo }}" filename: ceph - become: True when: not cephadm_use_package_from_distribution | bool - name: Install cephadm + become: true apt: name: - cephadm - python3-jinja2 - python3-yaml - install_recommends: False - become: True + install_recommends: false diff --git a/roles/cephadm/tasks/pkg_redhat.yml b/roles/cephadm/tasks/pkg_redhat.yml index af8c747b8..9f679c9f1 100644 --- a/roles/cephadm/tasks/pkg_redhat.yml +++ b/roles/cephadm/tasks/pkg_redhat.yml @@ -1,32 +1,32 @@ --- - name: Ensure yum repos directory exists + become: true file: path: /etc/yum.repos.d/ state: directory - recurse: yes - become: True + recurse: true - name: Install centos-release-ceph + become: true dnf: name: "centos-release-ceph-{{ cephadm_ceph_release }}" - become: True when: cephadm_use_package_from_distribution - name: Enable Ceph base yum repository + become: true yum_repository: name: "{{ item.shortname }}" description: "{{ item.name }}" baseurl: "{{ item.url }}" gpgkey: "{{ cephadm_ceph_rpm_gpg_key }}" loop: "{{ cephadm_ceph_rpm_repos }}" - become: True when: not cephadm_use_package_from_distribution # NOTE(mnasiadka): cephadm bootstrap failing on jinja2 missing - name: Install cephadm and jinja2 + become: true dnf: name: - cephadm - python3-jinja2 - install_weak_deps: False - become: True + install_weak_deps: false diff --git a/roles/kolla-ansible-deploy-bifrost/tasks/main.yml b/roles/kolla-ansible-deploy-bifrost/tasks/main.yml index 5b510da40..98254d321 100644 --- a/roles/kolla-ansible-deploy-bifrost/tasks/main.yml +++ b/roles/kolla-ansible-deploy-bifrost/tasks/main.yml @@ -6,4 +6,4 @@ kolla-ansible deploy-bifrost -i /etc/kolla/inventory >/tmp/logs/ansible/deploy-bifrost 2>&1 - + changed_when: true diff --git a/roles/kolla-ansible-deploy/tasks/certificates.yml b/roles/kolla-ansible-deploy/tasks/certificates.yml index 6296a1dbe..42910bc67 100644 --- a/roles/kolla-ansible-deploy/tasks/certificates.yml +++ b/roles/kolla-ansible-deploy/tasks/certificates.yml @@ -7,6 +7,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/certificates 2>&1 + changed_when: true - name: Init pebble when Lets Encrypt is enabled when: (le_enabled | default(False)) | bool @@ -30,10 +31,12 @@ become: true ansible.builtin.command: cmd: "docker cp pebble:/test/certs/pebble.minica.pem /etc/kolla/certificates/ca/pebble-root.crt" + changed_when: true - name: "Fetch pebble.crt and store it in /etc/kolla/certificates/ca/" become: true ansible.builtin.get_url: url: "https://127.0.0.1:15000/roots/0" dest: "/etc/kolla/certificates/ca/pebble.crt" + mode: "0644" validate_certs: false diff --git a/roles/kolla-ansible-deploy/tasks/deploy.yml b/roles/kolla-ansible-deploy/tasks/deploy.yml index 771006735..eb7637bd4 100644 --- a/roles/kolla-ansible-deploy/tasks/deploy.yml +++ b/roles/kolla-ansible-deploy/tasks/deploy.yml @@ -7,6 +7,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/deploy-prechecks 2>&1 + changed_when: false - name: Run kolla-ansible pull ansible.builtin.shell: @@ -16,6 +17,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/pull 2>&1 + changed_when: true - name: Run kolla-ansible deploy ansible.builtin.shell: @@ -25,6 +27,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/deploy 2>&1 + changed_when: true - name: Run kolla-ansible post-deploy ansible.builtin.shell: @@ -34,6 +37,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/post-deploy 2>&1 + changed_when: true - name: Run kolla-ansible validate-config ansible.builtin.shell: @@ -43,6 +47,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/validate-config 2>&1 + changed_when: false when: not is_upgrade | bool - name: Run kolla-ansible check @@ -53,3 +58,4 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/check 2>&1 + changed_when: false diff --git a/roles/kolla-ansible-deploy/tasks/main.yml b/roles/kolla-ansible-deploy/tasks/main.yml index e02765d99..b2ec759cc 100644 --- a/roles/kolla-ansible-deploy/tasks/main.yml +++ b/roles/kolla-ansible-deploy/tasks/main.yml @@ -7,5 +7,8 @@ mode: "0777" recurse: true -- import_tasks: certificates.yml -- import_tasks: deploy.yml +- name: Import certificates.yml + import_tasks: certificates.yml + +- name: Import deploy.yml + import_tasks: deploy.yml diff --git a/roles/kolla-ansible-reconfigure/tasks/main.yml b/roles/kolla-ansible-reconfigure/tasks/main.yml index 9cc0f1416..287c3688b 100644 --- a/roles/kolla-ansible-reconfigure/tasks/main.yml +++ b/roles/kolla-ansible-reconfigure/tasks/main.yml @@ -7,6 +7,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/reconfigure-prechecks 2>&1 + changed_when: false - name: Remove OVN DB containers and volumes on primary to test recreation (docker) become: true @@ -42,8 +43,9 @@ # NOTE(blanson): there is apparently no module to do that (!?) - name: List docker containers ansible.builtin.command: - cmd: "docker ps --format '{{'{{'}}.Names{{'}}'}}'" + cmd: "docker ps --format '{{ '{{' }}.Names{{ '}}' }}'" register: _deploy_docker_ps_raw + changed_when: false - name: Get details of all containers on host community.docker.docker_container_info: @@ -137,6 +139,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/reconfigure 2>&1 + changed_when: true - name: "Capture state of containers post reconfigure (docker)" become: true @@ -149,8 +152,9 @@ block: - name: List docker containers ansible.builtin.command: - cmd: "docker ps --format '{{'{{'}}.Names{{'}}'}}'" + cmd: "docker ps --format '{{ '{{' }}.Names{{ '}}' }}'" register: _reconfigure_docker_ps_raw + changed_when: false - name: Get details of all containers on host community.docker.docker_container_info: diff --git a/roles/kolla-ansible-setup-disks/tasks/main.yml b/roles/kolla-ansible-setup-disks/tasks/main.yml index e4e25f736..49c9c31e8 100644 --- a/roles/kolla-ansible-setup-disks/tasks/main.yml +++ b/roles/kolla-ansible-setup-disks/tasks/main.yml @@ -15,8 +15,9 @@ - name: Get free loop device become: true - ansible.builtin.shell: + ansible.builtin.command: cmd: "losetup -f" + changed_when: false register: _loop_device - name: Mount file on loop device @@ -25,6 +26,7 @@ cmd: > losetup {{ _loop_device.stdout }} {{ kolla_ansible_setup_disks_file_path }} + changed_when: true - name: Create LVM extents on loop device become: true diff --git a/roles/kolla-ansible-tempest/tasks/main.yml b/roles/kolla-ansible-tempest/tasks/main.yml index 5476b1183..315c33213 100644 --- a/roles/kolla-ansible-tempest/tasks/main.yml +++ b/roles/kolla-ansible-tempest/tasks/main.yml @@ -14,6 +14,8 @@ creates: "/home/zuul/tempest" - name: Discover tempest config + environment: + OS_CLIENT_CONFIG_FILE: "/etc/kolla/clouds.yaml" vars: ver: "{{ kolla_ansible_tempest_cirros_ver }}" image: "https://download.cirros-cloud.net/{{ ver }}/cirros-{{ ver }}-x86_64-disk.img" @@ -26,8 +28,7 @@ --os-cloud kolla-admin compute.build_timeout {{ kolla_ansible_tempest_build_timeout }} >/tmp/logs/ansible/test-init-tempest-discover 2>&1 - environment: - OS_CLIENT_CONFIG_FILE: "/etc/kolla/clouds.yaml" + changed_when: false - name: Run tempest tests environment: @@ -49,3 +50,4 @@ --exclude-regex '{{ kolla_ansible_tempest_exclude_regex | join("|") }}' {% endif %} >/tmp/logs/ansible/{{ tempest_log_file }} 2>&1 + changed_when: true diff --git a/roles/kolla-ansible-test-bifrost/tasks/main.yml b/roles/kolla-ansible-test-bifrost/tasks/main.yml index 431aed584..90851504a 100644 --- a/roles/kolla-ansible-test-bifrost/tasks/main.yml +++ b/roles/kolla-ansible-test-bifrost/tasks/main.yml @@ -5,6 +5,7 @@ cmd: > {{ container_engine }} exec bifrost_deploy bash -c 'OS_CLOUD=bifrost baremetal driver list' + changed_when: false register: bdl until: bdl.rc == 0 retries: 5 @@ -16,6 +17,7 @@ cmd: > {{ container_engine }} exec bifrost_deploy bash -c 'OS_CLOUD=bifrost baremetal node list' + changed_when: false - name: Create baremetal node become: true @@ -24,6 +26,7 @@ {{ container_engine }} exec bifrost_deploy bash -c 'OS_CLOUD=bifrost baremetal node create --driver redfish --name test-node' + changed_when: true - name: Delete baremetal node become: true @@ -32,4 +35,4 @@ {{ container_engine }} exec bifrost_deploy bash -c 'OS_CLOUD=bifrost baremetal node delete test-node' - + changed_when: true diff --git a/roles/kolla-ansible-test-dashboard/tasks/main.yml b/roles/kolla-ansible-test-dashboard/tasks/main.yml index 534769182..b55f5078d 100644 --- a/roles/kolla-ansible-test-dashboard/tasks/main.yml +++ b/roles/kolla-ansible-test-dashboard/tasks/main.yml @@ -32,11 +32,13 @@ ansible.builtin.file: path: "/home/zuul/testinfra" state: directory + mode: "0755" - name: Ensure screenshots directory exists ansible.builtin.file: path: "/home/zuul/testinfra/screenshots" state: directory + mode: "0755" - name: Ensure required packages are installed ansible.builtin.pip: @@ -88,3 +90,4 @@ --html=/home/zuul/testinfra/test-results-testinfra.html --self-contained-html -v tests/testinfra chdir: "{{ zuul.project.src_dir }}" + changed_when: false diff --git a/roles/kolla-ansible-upgrade-bifrost/tasks/main.yml b/roles/kolla-ansible-upgrade-bifrost/tasks/main.yml index ac8d11c1c..77ece6975 100644 --- a/roles/kolla-ansible-upgrade-bifrost/tasks/main.yml +++ b/roles/kolla-ansible-upgrade-bifrost/tasks/main.yml @@ -6,3 +6,4 @@ kolla-ansible deploy-bifrost -i /etc/kolla/inventory >/tmp/logs/ansible/upgrade-bifrost 2>&1 + changed_when: true diff --git a/roles/kolla-ansible-upgrade/tasks/main.yml b/roles/kolla-ansible-upgrade/tasks/main.yml index c66e06fe2..87b3c8fae 100644 --- a/roles/kolla-ansible-upgrade/tasks/main.yml +++ b/roles/kolla-ansible-upgrade/tasks/main.yml @@ -7,6 +7,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/upgrade-certificates 2>&1 + changed_when: true # NOTE(mnasiadka): Need to run bootstrap before upgrade - name: Run kolla-ansible bootstrap-servers @@ -17,6 +18,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/upgrade-bootstrap 2>&1 + changed_when: true - name: Run kolla-ansible prechecks ansible.builtin.shell: @@ -26,6 +28,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/upgrade-prechecks 2>&1 + changed_when: false - name: Run kolla-ansible pull ansible.builtin.shell: @@ -35,6 +38,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/upgrade-pull 2>&1 + changed_when: true - name: Run kolla-ansible upgrade ansible.builtin.shell: @@ -44,6 +48,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/upgrade 2>&1 + changed_when: true - name: Run kolla-ansible post-deploy ansible.builtin.shell: @@ -53,6 +58,7 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/upgrade-post-deploy 2>&1 + changed_when: true - name: Run kolla-ansible validate-config on upgrades ansible.builtin.shell: @@ -62,4 +68,4 @@ -i /etc/kolla/inventory -vvv >/tmp/logs/ansible/upgrade-validate-config 2>&1 - + changed_when: false diff --git a/roles/multi-node-managed-addressing/tasks/main.yml b/roles/multi-node-managed-addressing/tasks/main.yml index dcf189905..925468b8b 100644 --- a/roles/multi-node-managed-addressing/tasks/main.yml +++ b/roles/multi-node-managed-addressing/tasks/main.yml @@ -21,13 +21,17 @@ # broadcast address as ansible picks up scope ('global') as the interface's # broadcast address which fails checks logic managed_network_broadcast_address: "{{ managed_network_cidr | ansible.utils.ipaddr('broadcast') }}" - command: ip address add {{ managed_network_cidr }} broadcast {{ managed_network_broadcast_address }} dev {{ managed_interface_name }} + ansible.builtin.command: + cmd: ip address add {{ managed_network_cidr }} broadcast {{ managed_network_broadcast_address }} dev {{ managed_interface_name }} + changed_when: true when: managed_network_address_family == 'ipv4' # NOTE(yoctozepto): IPv6 has no broadcast address, let's not create confusion by setting it - name: Add IPv6 address for managed network become: true - command: ip address add {{ managed_interface_address }}/{{ managed_network_prefix_length }} dev {{ managed_interface_name }} + ansible.builtin.command: + cmd: ip address add {{ managed_interface_address }}/{{ managed_network_prefix_length }} dev {{ managed_interface_name }} + changed_when: true when: managed_network_address_family == 'ipv6' - name: Accept traffic on the managed network (IN) @@ -57,7 +61,9 @@ # hence we only check whether it's no longer tentative - name: Ensure IPv6 addresses on the managed interface are no longer tentative become: true - command: ip -o address show tentative dev {{ managed_interface_name }} + ansible.builtin.command: + cmd: ip -o address show tentative dev {{ managed_interface_name }} + changed_when: false register: tentative_addresses until: tentative_addresses.stdout == '' retries: 30 @@ -69,5 +75,7 @@ become: true vars: ping_command: "{{ 'ping' if managed_network_address_family == 'ipv4' else 'ping6' }}" - command: "{{ ping_command }} -c1 {{ hostvars[item].managed_interface_address }}" + ansible.builtin.command: + cmd: "{{ ping_command }} -c1 {{ hostvars[item].managed_interface_address }}" + changed_when: false with_inventory_hostnames: all diff --git a/roles/multi-node-vxlan-overlay/tasks/main.yml b/roles/multi-node-vxlan-overlay/tasks/main.yml index 6a169a13f..27ae67bab 100644 --- a/roles/multi-node-vxlan-overlay/tasks/main.yml +++ b/roles/multi-node-vxlan-overlay/tasks/main.yml @@ -21,7 +21,9 @@ - name: Create VXLAN interface become: true - command: ip link add {{ vxlan_interface_name }} type vxlan id {{ vxlan_vni }} local {{ tunnel_local_address }} dstport {{ vxlan_dstport }} + ansible.builtin.command: + cmd: ip link add {{ vxlan_interface_name }} type vxlan id {{ vxlan_vni }} local {{ tunnel_local_address }} dstport {{ vxlan_dstport }} + changed_when: true - name: Set VXLAN interface MTU become: true @@ -35,17 +37,23 @@ first }} # Allow 50 bytes overhead for VXLAN headers. mtu: "{{ parent_interface.mtu | int - 50 }}" - command: ip link set {{ vxlan_interface_name }} mtu {{ mtu }} + ansible.builtin.command: + cmd: ip link set {{ vxlan_interface_name }} mtu {{ mtu }} + changed_when: true # emulate BUM by multiplicating traffic to unicast targets - name: Add fdb entries for BUM traffic become: true vars: dest_ip: "{{ hostvars[item].tunnel_local_address }}" - command: bridge fdb append 00:00:00:00:00:00 dev {{ vxlan_interface_name }} dst {{ dest_ip }} + ansible.builtin.command: + cmd: bridge fdb append 00:00:00:00:00:00 dev {{ vxlan_interface_name }} dst {{ dest_ip }} + changed_when: true with_inventory_hostnames: all when: item != inventory_hostname - name: Bring VXLAN interface up become: true - command: ip link set {{ vxlan_interface_name }} up + ansible.builtin.command: + cmd: ip link set {{ vxlan_interface_name }} up + changed_when: true diff --git a/roles/veth/tasks/main.yml b/roles/veth/tasks/main.yml index 034fec675..2b5556dbe 100644 --- a/roles/veth/tasks/main.yml +++ b/roles/veth/tasks/main.yml @@ -1,12 +1,18 @@ --- - name: Create veth pair become: true - command: ip link add {{ veth_pair.0 }} type veth peer name {{ veth_pair.1 }} + ansible.builtin.command: + cmd: ip link add {{ veth_pair.0 }} type veth peer name {{ veth_pair.1 }} + changed_when: true - name: Bring veth pair up become: true - shell: ip link set {{ veth_pair.0 }} up && ip link set {{ veth_pair.1 }} up + ansible.builtin.shell: + cmd: ip link set {{ veth_pair.0 }} up && ip link set {{ veth_pair.1 }} up + changed_when: true - name: Add first veth pair port to bridge become: true - command: ip link set {{ veth_pair.0 }} master {{ bridge_name }} + ansible.builtin.command: + cmd: ip link set {{ veth_pair.0 }} master {{ bridge_name }} + changed_when: true diff --git a/tools/validate-all-file.py b/tools/validate-all-file.py deleted file mode 100755 index 7753971ab..000000000 --- a/tools/validate-all-file.py +++ /dev/null @@ -1,227 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import collections -import fnmatch -import json -import logging -import os -import re -import sys - -import jinja2 -import yaml - - -from kolla_ansible.put_address_in_context import put_address_in_context - - -PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) - -NEWLINE_EOF_INCLUDE_PATTERNS = ['*.j2', '*.yml', '*.py', '*.sh'] -NEWLINE_EOF_EXCLUDE_PATTERNS = ['.tox', '.testrepository', '.git'] - -# Render json file by using jinja2 template is OK -JSON_J2_INCLUDE_PATTERNS = ['*.json.j2', '*.json'] -JSON_J2_EXCLUDE_PATTERNS = ['.tox', '.testrepository', '.git'] - -YAML_INCLUDE_PATTERNS = ['*.yml'] -YAML_EXCLUDE_PATTERNS = ['.tox', '.testrepository', '.git', - 'defaults', 'templates', 'vars'] - -KOLLA_NETWORKS = [ - 'api', - 'storage', - 'migration', - 'tunnel', - 'octavia_network', - 'bifrost_network', - 'dns', # designate -] - -logging.basicConfig() -LOG = logging.getLogger(__name__) - - -def check_newline_eof(): - includes = r'|'.join([fnmatch.translate(x) - for x in NEWLINE_EOF_INCLUDE_PATTERNS]) - excludes = r'|'.join([fnmatch.translate(x) - for x in NEWLINE_EOF_EXCLUDE_PATTERNS]) - return_code = 0 - - def has_newline_eof(path): - with open(path, 'r') as f: - data = f.read() - if data and data[-1] != '\n': - LOG.error('%s file error: no newline at end of file', path) - return False - return True - - for root, dirs, files in os.walk(PROJECT_ROOT): - dirs[:] = [d for d in dirs if not re.match(excludes, d)] - for f in files: - if not re.match(excludes, f) and re.match(includes, f): - if not has_newline_eof(os.path.join(root, f)): - return_code = 1 - return return_code - - -def check_json_j2(): - includes = r'|'.join([fnmatch.translate(x) - for x in JSON_J2_INCLUDE_PATTERNS]) - excludes = r'|'.join([fnmatch.translate(x) - for x in JSON_J2_EXCLUDE_PATTERNS]) - return_code = 0 - - def bool_filter(value): - return True - - def basename_filter(text): - return text.split('\\')[-1] - - def kolla_address_filter_mock(network_name, hostname=None): - # no validation is possible for the hostname - - if network_name not in KOLLA_NETWORKS: - raise ValueError("{network_name} not in KOLLA_NETWORKS" - .format(network_name=network_name)) - - return "127.0.0.1" - - # Mock ansible hostvars variable, which is a nested dict - def hostvars(): - return collections.defaultdict(hostvars) - - # Mock Ansible groups variable, which is a dict of lists. - def groups(): - return collections.defaultdict(list) - - def validate_json_j2(root, filename): - env = jinja2.Environment( # nosec: not used to render HTML - loader=jinja2.FileSystemLoader(root)) - env.filters['bool'] = bool_filter - env.filters['basename'] = basename_filter - env.filters['kolla_address'] = kolla_address_filter_mock - env.filters['put_address_in_context'] = \ - put_address_in_context - template = env.get_template(filename) - # Mock ansible variables. - context = { - 'hostvars': hostvars(), - 'groups': groups(), - 'inventory_hostname': 'hostname', - 'api_interface_address': '', - 'kolla_internal_fqdn': '', - 'octavia_provider_drivers': '', - 'ovn_sb_db_relay_active_inactivity_probe': 120000, - 'ovn_sb_db_relay_passive_inactivity_probe': 60000, - 'ovn_sb_db_relay_max_backoff': 60000, - 'rabbitmq_ha_replica_count': 2, - 'rabbitmq_message_ttl_ms': 600000, - 'rabbitmq_queue_expiry_ms': 3600000, - - } - data = template.render(**context) - json.loads(data) - for root, dirs, files in os.walk(PROJECT_ROOT): - dirs[:] = [d for d in dirs if not re.match(excludes, d)] - for filename in files: - if not re.match(excludes, filename) and \ - re.match(includes, filename): - fullpath = os.path.join(root, filename) - try: - validate_json_j2(root, filename) - except (ValueError, jinja2.exceptions.TemplateError): - return_code = 1 - LOG.exception('%s file error', fullpath) - return return_code - - -def check_task_contents(): - """All tasks that use Docker should have 'become: true'.""" - includes = r'|'.join([fnmatch.translate(x) - for x in YAML_INCLUDE_PATTERNS]) - excludes = r'|'.join([fnmatch.translate(x) - for x in YAML_EXCLUDE_PATTERNS]) - roles_path = os.path.join(PROJECT_ROOT, 'ansible', 'roles') - return_code = 0 - for root, dirs, files in os.walk(roles_path): - dirs[:] = [d for d in dirs if not re.match(excludes, d)] - for filename in files: - if not re.match(excludes, filename) and \ - re.match(includes, filename): - fullpath = os.path.join(root, filename) - with open(fullpath) as fp: - tasks = yaml.safe_load(fp) - tasks = tasks or [] - for task in tasks: - if task.get('block'): - block = task - for task in task['block']: - if check_container_become(fullpath, task, block): - return_code = 1 - else: - if check_container_become(fullpath, task): - return_code = 1 - - return return_code - - -def check_container_become(fullpath, task, block=''): - - ce_modules = ('kolla_container', 'kolla_container_facts', 'kolla_toolbox') - cmd_modules = ('command', 'shell') - return_code = 0 - - for module in ce_modules: - if (module in task and not task.get('become') and - not block.get('become')): - return_code = 1 - LOG.error("Use of %s module without become in " - "task %s in %s", - module, task['name'], fullpath) - for module in cmd_modules: - ce_without_become = False - if (module in task and not task.get('become')): - if (isinstance(task[module], str) and - (task[module].startswith('docker') or - task[module].startswith('podman')) and - not block.get('become')): - ce_without_become = True - if (isinstance(task[module], dict) and - (task[module]['cmd'].startswith('docker') or - task[module]['cmd'].startswith('podman')) and - not block.get('become')): - ce_without_become = True - if ce_without_become: - return_code = 1 - LOG.error("Use of container engine in %s " - "module without " - "become in task %s in %s block %s", - module, task['name'], fullpath, block) - return return_code - - -def main(): - checks = ( - check_newline_eof, - check_json_j2, - check_task_contents, - ) - return sum([check() for check in checks]) - - -if __name__ == "__main__": - sys.exit(main()) @@ -156,5 +156,4 @@ commands = j2lint ansible/ roles/ tests/ --ignore single-statement-per-line setenv = {[testenv:linters]setenv} deps = {[testenv:linters]deps} commands = - python {toxinidir}/tools/validate-all-file.py ansible-lint -p |
