github.skymusic.top/operator-framework/operator-sdk@v0.8.2/doc/ansible/dev/finalizers.md (about) 1 # Handling deletion events 2 3 The default behavior of an Ansible Operator is to delete all resources the operator 4 created during reconciliation when a managed resource is marked for deletion. This 5 behavior is usually sufficient for applications that exist only in Kubernetes, but 6 sometimes it is necessary to perform more complex operations (for example, when 7 your action performed against a third party API needs to be undone). These more 8 complex cases can still be handled by Ansible Operator, through the use of a finalizer. 9 10 Finalizers allow controllers (such as an Ansible Operator) to implement asynchronous pre-delete hooks. 11 This allows custom logic to run after a resource has been marked for deletion, but 12 before the resource has actually been deleted from the Kubernetes cluster. 13 For Ansible Operator, this hook takes the form of an Ansible playbook or role. You can 14 define the mapping from your finalizer to a playbook or role by simply setting the 15 `finalizer` field on the entry in your `watches.yaml`. You can also choose to re-run 16 your top-level playbook or role with different variables set. The `watches.yaml` 17 finalizer configuration accepts the following options: 18 19 20 #### name 21 `name` is required. 22 23 This is the name of the finalizer. This is basically an arbitrary string, the existence 24 of any finalizer string on a resource will prevent that resource from being deleted until 25 the finalizer is removed. Ansible Operator will remove this string from the list of 26 finalizers on successful execution of the specified role or playbook. A typical finalizer 27 will be `finalizer.<group>`, where `<group>` is the group of the resource being managed. 28 29 #### playbook 30 31 One of `playbook`, `role`, or `vars` must be provided. If `playbook` is not provided, it 32 will default to the playbook specified at the top level of the `watches.yaml` 33 entry. 34 35 This field is identical to the top-level `playbook` field. It requires an absolute 36 path to a playbook on the operator’s file system. 37 38 #### role 39 40 One of `playbook`, `role`, or `vars` must be provided. If `role` is not provided, it 41 will default to the role specified at the top level of the `watches.yaml` entry. 42 43 This field is identical to the top-level `role` field. It requires an absolute 44 path to a role on the operator’s file system. 45 46 #### vars 47 48 One of `playbook`, `role`, or `vars` must be provided. 49 50 `vars` is an arbitrary map of key-value pairs. The contents of `vars` will be passed as `extra_vars` to the 51 playbook or role specified in the finalizer block, or at the top-level if neither `playbook` 52 or `role` was set for the finalizer. 53 54 ## Examples 55 56 Here are a few examples of `watches.yaml` files that specify a finalizer: 57 58 ### Run top-level playbook or role with new variables 59 ```yaml 60 --- 61 - version: v1alpha1 62 group: app.example.com 63 kind: Database 64 playbook: /opt/ansible/playbook.yml 65 finalizer: 66 name: finalizer.app.example.com 67 vars: 68 state: absent 69 ``` 70 71 This example will run `/opt/ansible/playbook.yml` when the Custom Resource 72 is deleted. Because `vars` is set, the playbook will be run with `state` set to `absent`. Inside the playbook, 73 the author can check this value and perform whatever cleanup is necessary. 74 75 ```yaml 76 --- 77 - version: v1alpha1 78 group: app.example.com 79 kind: Database 80 role: /opt/ansible/roles/database 81 finalizer: 82 name: finalizer.app.example.com 83 vars: 84 state: absent 85 ``` 86 87 This example is nearly identical to the first, except it will run the `/opt/ansible/roles/database` 88 role, rather than a playbook, with the `state` variable set to `absent`. 89 90 ### Run a different playbook or role 91 ```yaml 92 --- 93 - version: v1alpha1 94 group: app.example.com 95 kind: Database 96 playbook: /opt/ansible/playbook.yml 97 finalizer: 98 name: finalizer.app.example.com 99 role: /opt/ansible/roles/teardown_database 100 ``` 101 102 This example will run the `/opt/ansible/roles/teardown_database` role when the Custom Resource is deleted. 103 104 ```yaml 105 --- 106 - version: v1alpha1 107 group: app.example.com 108 kind: Database 109 playbook: /opt/ansible/playbook.yml 110 finalizer: 111 name: finalizer.app.example.com 112 playbook: /opt/ansible/destroy.yml 113 ``` 114 115 This example will run the `/opt/ansible/destroy.yml` playbook when the Custom Resource is deleted. 116 117 ### Run a different playbook or role with vars 118 119 You can set `playbook` or `role` and `vars` at the same time. This can be useful if only a small 120 part of your logic handles interacting with the component that requires cleanup. Rather than 121 run all the logic again, you can specify only to run the role or playbook that handled the 122 interaction, with a different variable set. 123 124 ```yaml 125 --- 126 - version: v1alpha1 127 group: app.example.com 128 kind: Database 129 playbook: /opt/ansible/playbook.yml 130 finalizer: 131 name: finalizer.app.example.com 132 role: /opt/ansible/roles/manage_credentials 133 vars: 134 state: revoked 135 ``` 136 137 138 For this example, assume our application configures automated backups to a third party service. 139 On deletion, all we want to do is revoke the credentials used to backup the data. We run 140 just the `/opt/ansible/roles/manage_credentials` role, which is imported by our playbook to 141 create the credentials in the first place, but we pass the `state: revoked` option, which 142 causes the role to invalidate our credentials. For everything else in our application, 143 automatic deletion of dependent resources will be sufficient, so we can exit successfully and 144 let the operator remove our finalizer and allow the resource to be deleted. 145 146 ## Further reading 147 • [Kubernetes finalizers](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#finalizers)