diff --git a/ansible/roles/deploy-containers/defaults/main.yml b/ansible/roles/deploy-containers/defaults/main.yml index 9130164e9..0838be95c 100644 --- a/ansible/roles/deploy-containers/defaults/main.yml +++ b/ansible/roles/deploy-containers/defaults/main.yml @@ -1,4 +1,7 @@ --- +# Action to perform: One of: "deploy", "destroy". +deploy_containers_action: "deploy" + deploy_containers_defaults: comparisons: image: strict diff --git a/ansible/roles/deploy-containers/tasks/deploy-container.yml b/ansible/roles/deploy-containers/tasks/deploy-container.yml new file mode 100644 index 000000000..0c5ccc087 --- /dev/null +++ b/ansible/roles/deploy-containers/tasks/deploy-container.yml @@ -0,0 +1,38 @@ +--- +- name: "[{{ container_name }}] Ensure we have latest image" + docker_image: + name: "{{ container_config.image }}" + tag: "{{ container_config.tag | default(omit) }}" + source: pull + +- name: "[{{ container_name }}] Include tasks file for pre task(s)" + include_tasks: "{{ container_config.pre }}" + when: container_config.pre is defined + +- name: "[{{ container_name }}] Start container" + docker_container: + capabilities: "{{ container_config.capabilities | default(omit) }}" + command: "{{ container_config.command | default(omit) }}" + comparisons: "{{ container_config.comparisons | default(deploy_containers_defaults.comparisons) }}" + detach: "{{ container_config.detach | default(deploy_containers_defaults.detach) }}" + env: "{{ container_config.env | default(omit) }}" + name: "{{ container_name }}" + network_mode: "{{ container_config.network_mode | default(deploy_containers_defaults.network_mode) }}" + image: "{{ container_config.image }}:{{ container_config.tag | default('latest') }}" + init: "{{ container_config.init | default(deploy_containers_defaults.init) }}" + ipc_mode: "{{ container_config.ipc_mode | default(omit) }}" + pid_mode: "{{ container_config.pid_mode | default(omit) }}" + ports: "{{ container_config.ports | default(omit) }}" + privileged: "{{ container_config.privileged | default(omit) }}" + restart_policy: "{{ container_config.restart_policy | default(deploy_containers_defaults.restart_policy) }}" + shm_size: "{{ container_config.shm_size | default(omit) }}" + sysctls: "{{ container_config.sysctls | default(omit) }}" + timeout: "{{ deploy_containers_docker_api_timeout }}" + ulimits: "{{ container_config.ulimits | default(omit) }}" + user: "{{ container_config.user | default(omit) }}" + volumes: "{{ container_config.volumes | default(omit) }}" + become: true + +- name: "[{{ container_name }}] Include tasks file for post task(s)" + include_tasks: "{{ container_config.post }}" + when: container_config.post is defined diff --git a/ansible/roles/deploy-containers/tasks/deploy.yml b/ansible/roles/deploy-containers/tasks/deploy.yml index d146f21a1..79796b4b6 100644 --- a/ansible/roles/deploy-containers/tasks/deploy.yml +++ b/ansible/roles/deploy-containers/tasks/deploy.yml @@ -1,37 +1,17 @@ --- -- name: "[{{ container_name }}] Ensure we have latest image" - docker_image: - name: "{{ container_config.image }}" - tag: "{{ container_config.tag | default(omit) }}" - source: pull +- name: Login to docker registry + docker_login: + registry_url: "{{ kolla_docker_registry or omit }}" + username: "{{ kolla_docker_registry_username }}" + password: "{{ kolla_docker_registry_password }}" + reauthorize: yes + when: + - deploy_containers_registry_attempt_login | bool + become: true -- name: "[{{ container_name }}] Include tasks file for pre task(s)" - include_tasks: "{{ container_config.pre }}" - when: container_config.pre is defined - -- name: "[{{ container_name }}] Start container" - docker_container: - capabilities: "{{ container_config.capabilities | default(omit) }}" - command: "{{ container_config.command | default(omit) }}" - comparisons: "{{ container_config.comparisons | default(deploy_containers_defaults.comparisons) }}" - detach: "{{ container_config.detach | default(deploy_containers_defaults.detach) }}" - env: "{{ container_config.env | default(omit) }}" - name: "{{ container_name }}" - network_mode: "{{ container_config.network_mode | default(deploy_containers_defaults.network_mode) }}" - image: "{{ container_config.image }}:{{ container_config.tag | default('latest') }}" - init: "{{ container_config.init | default(deploy_containers_defaults.init) }}" - ipc_mode: "{{ container_config.ipc_mode | default(omit) }}" - pid_mode: "{{ container_config.pid_mode | default(omit) }}" - ports: "{{ container_config.ports | default(omit) }}" - privileged: "{{ container_config.privileged | default(omit) }}" - restart_policy: "{{ container_config.restart_policy | default(deploy_containers_defaults.restart_policy) }}" - shm_size: "{{ container_config.shm_size | default(omit) }}" - sysctls: "{{ container_config.sysctls | default(omit) }}" - timeout: "{{ deploy_containers_docker_api_timeout }}" - ulimits: "{{ container_config.ulimits | default(omit) }}" - user: "{{ container_config.user | default(omit) }}" - volumes: "{{ container_config.volumes | default(omit) }}" - -- name: "[{{ container_name }}] Include tasks file for post task(s)" - include_tasks: "{{ container_config.post }}" - when: container_config.post is defined +- name: Deploy containers (loop) + include_tasks: deploy-container.yml + vars: + container_name: "{{ item.key }}" + container_config: "{{ item.value }}" + with_dict: "{{ seed_containers }}" diff --git a/ansible/roles/deploy-containers/tasks/destroy-container.yml b/ansible/roles/deploy-containers/tasks/destroy-container.yml new file mode 100644 index 000000000..692ce2a63 --- /dev/null +++ b/ansible/roles/deploy-containers/tasks/destroy-container.yml @@ -0,0 +1,15 @@ +--- + +- name: "[{{ container_name }}] Include tasks file for pre destroy task(s)" + include_tasks: "{{ container_config.pre_destroy }}" + when: container_config.pre_destroy is defined + +- name: "[{{ container_name }}] Delete container" + docker_container: + name: "{{ container_name }}" + state: absent + become: true + +- name: "[{{ container_name }}] Include tasks file for post destroy task(s)" + include_tasks: "{{ container_config.post_destroy }}" + when: container_config.post_destroy is defined diff --git a/ansible/roles/deploy-containers/tasks/destroy.yml b/ansible/roles/deploy-containers/tasks/destroy.yml new file mode 100644 index 000000000..acf0d25bd --- /dev/null +++ b/ansible/roles/deploy-containers/tasks/destroy.yml @@ -0,0 +1,6 @@ +- name: Destroy containers (loop) + include_tasks: destroy-container.yml + vars: + container_name: "{{ item.key }}" + container_config: "{{ item.value }}" + with_dict: "{{ seed_containers }}" \ No newline at end of file diff --git a/ansible/roles/deploy-containers/tasks/main.yml b/ansible/roles/deploy-containers/tasks/main.yml index a16e6d8d7..bcbde1629 100644 --- a/ansible/roles/deploy-containers/tasks/main.yml +++ b/ansible/roles/deploy-containers/tasks/main.yml @@ -1,16 +1,2 @@ --- -- name: Login to docker registry - docker_login: - registry_url: "{{ kolla_docker_registry or omit }}" - username: "{{ kolla_docker_registry_username }}" - password: "{{ kolla_docker_registry_password }}" - reauthorize: yes - when: - - deploy_containers_registry_attempt_login | bool - -- name: Deploy containers (loop) - include_tasks: deploy.yml - vars: - container_name: "{{ item.key }}" - container_config: "{{ item.value }}" - with_dict: "{{ seed_containers }}" +- include_tasks: "{{ deploy_containers_action }}.yml" diff --git a/ansible/seed-deploy-containers.yml b/ansible/seed-deploy-containers.yml index 23eb241c9..585487af8 100644 --- a/ansible/seed-deploy-containers.yml +++ b/ansible/seed-deploy-containers.yml @@ -3,5 +3,7 @@ hosts: seed tags: - seed-deploy-containers + vars: + deploy_containers_action: "{{ kayobe_action }}" roles: - role: deploy-containers diff --git a/doc/source/administration/seed.rst b/doc/source/administration/seed.rst index ff8fab510..673e12152 100644 --- a/doc/source/administration/seed.rst +++ b/doc/source/administration/seed.rst @@ -13,6 +13,29 @@ To deprovision the seed VM:: (kayobe) $ kayobe seed vm deprovision +Destroying all services on the seed +=================================== + +.. warning:: + + This step will destroy all containers, container images, and volumes that were deployed by + Kayobe and Kolla. To destroy volumes and images associated with + :ref:`custom containers `, you must configure the + ``post_destroy`` and ``pre_destroy`` hooks to do the clean up manually as Kayobe will not + automatically clean these up. It is generally only advised to run this command when + you have no important data on the system. + +To destroy the seed services:: + + (kayobe) $ kayobe seed service destroy --yes-i-really-really-mean-it + +This can optionally be used with a tag:: + + (kayobe) $ kayobe seed service destroy --yes-i-really-really-mean-it -kt none -t docker-registry + +Care must be taken to set both kayobe and kolla tags to avoid accidentally +destroying other services. + Updating Packages ================= diff --git a/doc/source/configuration/reference/seed-custom-containers.rst b/doc/source/configuration/reference/seed-custom-containers.rst index 5b3e03cdd..b4f3035ac 100644 --- a/doc/source/configuration/reference/seed-custom-containers.rst +++ b/doc/source/configuration/reference/seed-custom-containers.rst @@ -20,10 +20,27 @@ For example, to deploy a squid container image: image: "stackhpc/squid:3.5.20-1" pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml" post: "{{ kayobe_env_config_path }}/containers/squid/post.yml" + pre_destroy: "{{ kayobe_env_config_path }}/containers/squid/pre_destroy.yml" + post_destroy: "{{ kayobe_env_config_path }}/containers/squid/post_destroy.yml" -Please notice the *optional* pre and post Ansible task files - those need to -be created in ``kayobe-config`` path and will be run before and after -particular container deployment. +Please notice the *optional* pre, post, pre_destroy, and post_destroy Ansible task +files - those need to be created in ``kayobe-config`` path. The table below describes +when they will run: + +.. list-table:: Container hooks + :widths: 25 75 + :header-rows: 1 + + * - Hook + - Trigger point + * - pre + - Before container deployment + * - post + - After container deployment + * - pre_destroy + - Before container is destroyed + * - post_destroy + - After container is destroyed Possible options for container deployment: diff --git a/kayobe/cli/commands.py b/kayobe/cli/commands.py index 7b059b9b5..adeed5426 100644 --- a/kayobe/cli/commands.py +++ b/kayobe/cli/commands.py @@ -730,7 +730,8 @@ class SeedServiceDeploy(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, self.app.LOG.debug("Deploying seed services") playbooks = _build_playbook_list( "seed-deploy-containers") - self.run_kayobe_playbooks(parsed_args, playbooks) + extra_vars = {"kayobe_action": "deploy"} + self.run_kayobe_playbooks(parsed_args, playbooks, extra_vars=extra_vars) self.generate_kolla_ansible_config(parsed_args, service_config=False, bifrost_config=True) @@ -739,8 +740,44 @@ class SeedServiceDeploy(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, "seed-credentials", "seed-introspection-rules", "dell-switch-bmp") - self.run_kayobe_playbooks(parsed_args, playbooks) + self.run_kayobe_playbooks(parsed_args, playbooks, extra_vars=extra_vars) +class SeedServiceDestroy(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, + Command): + """Destroy the seed services. + + * Destroys user defined containers + * Destroys kolla deployed containers + * Destroys docker registry + """ + + def take_action(self, parsed_args): + if not parsed_args.yes_i_really_really_mean_it: + self.app.LOG.error("This will permanently destroy all services " + "and data. Specify " + "--yes-i-really-really-mean-it to confirm that " + "you understand this.") + sys.exit(1) + self.app.LOG.debug("Destroying seed services") + self.generate_kolla_ansible_config(parsed_args, service_config=False, + bifrost_config=False) + extra_args = ["--yes-i-really-really-mean-it"] + self.run_kolla_ansible_seed(parsed_args, "destroy", extra_args=extra_args) + + extra_vars = {"kayobe_action": "destroy"} + playbooks = _build_playbook_list( + "seed-deploy-containers", + "docker-registry") + self.run_kayobe_playbooks(parsed_args, playbooks, extra_vars=extra_vars) + + def get_parser(self, prog_name): + parser = super(SeedServiceDestroy, self).get_parser(prog_name) + group = parser.add_argument_group("Services") + group.add_argument("--yes-i-really-really-mean-it", + action='store_true', + help="confirm that you understand that this will " + "permanently destroy all services and data.") + return parser class SeedServiceUpgrade(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, Command): @@ -762,7 +799,8 @@ class SeedServiceUpgrade(KollaAnsibleMixin, KayobeAnsibleMixin, VaultMixin, self.app.LOG.debug("Upgrading seed services") playbooks = _build_playbook_list( "seed-deploy-containers") - self.run_kayobe_playbooks(parsed_args, playbooks) + extra_vars = {"kayobe_action": "deploy"} + self.run_kayobe_playbooks(parsed_args, playbooks, extra_vars=extra_vars) self.generate_kolla_ansible_config(parsed_args, service_config=False, bifrost_config=True) diff --git a/kayobe/tests/unit/cli/test_commands.py b/kayobe/tests/unit/cli/test_commands.py index 83739c678..56c902e9b 100644 --- a/kayobe/tests/unit/cli/test_commands.py +++ b/kayobe/tests/unit/cli/test_commands.py @@ -810,6 +810,7 @@ class TestCase(unittest.TestCase): mock.call( mock.ANY, [utils.get_data_files_path("ansible", "seed-deploy-containers.yml")], # noqa + extra_vars={'kayobe_action': 'deploy'} ), mock.call( mock.ANY, @@ -834,6 +835,7 @@ class TestCase(unittest.TestCase): utils.get_data_files_path( "ansible", "dell-switch-bmp.yml"), ], + extra_vars={'kayobe_action': 'deploy'} ), ] self.assertListEqual(expected_calls, mock_run.call_args_list) @@ -862,6 +864,7 @@ class TestCase(unittest.TestCase): mock.call( mock.ANY, [utils.get_data_files_path("ansible", "seed-deploy-containers.yml")], # noqa + extra_vars={'kayobe_action': 'deploy'} ), mock.call( mock.ANY, diff --git a/releasenotes/notes/adds-seed-service-destroy-1bdf79990d050e68.yaml b/releasenotes/notes/adds-seed-service-destroy-1bdf79990d050e68.yaml new file mode 100644 index 000000000..06b7526ef --- /dev/null +++ b/releasenotes/notes/adds-seed-service-destroy-1bdf79990d050e68.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Adds the command ``kayobe seed service destroy``. This can be used to clean + up all services on the seed host. Caution is advised when using this command + as it will delete all of the data on the seed. diff --git a/setup.cfg b/setup.cfg index ce9dcb69e..df817dc0f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -96,6 +96,7 @@ kayobe.cli= seed_hypervisor_host_package_update = kayobe.cli.commands:SeedHypervisorHostPackageUpdate seed_hypervisor_host_upgrade = kayobe.cli.commands:SeedHypervisorHostUpgrade seed_service_deploy = kayobe.cli.commands:SeedServiceDeploy + seed_service_destroy = kayobe.cli.commands:SeedServiceDestroy seed_service_upgrade = kayobe.cli.commands:SeedServiceUpgrade seed_vm_deprovision = kayobe.cli.commands:SeedVMDeprovision seed_vm_provision = kayobe.cli.commands:SeedVMProvision @@ -221,6 +222,8 @@ kayobe.cli.seed_hypervisor_host_upgrade = hooks = kayobe.cli.commands:HookDispatcher kayobe.cli.seed_service_deploy = hooks = kayobe.cli.commands:HookDispatcher +kayobe.cli.seed_service_destroy = + hooks = kayobe.cli.commands:HookDispatcher kayobe.cli.seed_service_upgrade = hooks = kayobe.cli.commands:HookDispatcher kayobe.cli.seed_vm_deprovision =