-
Notifications
You must be signed in to change notification settings - Fork 14.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better support for Boto Waiters #28236
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
<!-- | ||
Licensed to the Apache Software Foundation (ASF) under one | ||
or more contributor license agreements. See the NOTICE file | ||
distributed with this work for additional information | ||
regarding copyright ownership. The ASF licenses this file | ||
to you 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. | ||
--> | ||
|
||
This module is for custom Boto3 waiter configuration files. Since documentation | ||
on creating custom waiters is pretty sparse out in the wild, this document can | ||
act as a rough quickstart guide. It is not meant to cover all edge cases. | ||
|
||
# To add a new custom waiter | ||
|
||
## Create or modify the service waiter config file | ||
|
||
Find or create a file for the service it is related to, for example waiters/eks.json | ||
|
||
### In the service waiter config file | ||
|
||
Build or add to the waiter model config json in that file. For examples of what these | ||
should look like, have a look through some official waiter models. Some examples: | ||
|
||
* [Cloudwatch](https://github.com/boto/botocore/blob/develop/botocore/data/cloudwatch/2010-08-01/waiters-2.json) | ||
* [EC2](https://github.com/boto/botocore/blob/develop/botocore/data/ec2/2016-11-15/waiters-2.json) | ||
* [EKS](https://github.com/boto/botocore/blob/develop/botocore/data/eks/2017-11-01/waiters-2.json) | ||
|
||
Below is an example of a working waiter model config that will make an EKS waiter which will wait for | ||
all Nodegroups in a cluster to be deleted. An explanation follows the code snippet. Note the backticks | ||
to escape the integers in the "argument" values. | ||
|
||
```json | ||
{ | ||
"version": 2, | ||
"waiters": { | ||
"all_nodegroups_deleted": { | ||
"operation": "ListNodegroups", | ||
"delay": 30, | ||
"maxAttempts": 60, | ||
"acceptors": [ | ||
{ | ||
"matcher": "path", | ||
"argument": "length(nodegroups[]) == `0`", | ||
"expected": true, | ||
"state": "success" | ||
}, | ||
{ | ||
"matcher": "path", | ||
"expected": true, | ||
"argument": "length(nodegroups[]) > `0`", | ||
"state": "retry" | ||
} | ||
] | ||
} | ||
} | ||
} | ||
``` | ||
|
||
In the model config above we create a new waiter called `all_nodegroups_deleted` which calls | ||
the `ListNodegroups` API endpoint. The parameters for the endpoint call must be passed into | ||
the `waiter.wait()` call, the same as when using an official waiter. The waiter then performs | ||
"argument" (in this case `len(result) == 0`) on the result. If the argument returns the value | ||
in "expected" (in this case `True`) then the waiter's state is set to `success`, the waiter can | ||
close down, and the operator which called it can continue. If `len(result) > 0` is `True` then | ||
the state is set to `retry`. The waiter will "delay" 30 seconds before trying again. If the | ||
state does not go to `success` before the maxAttempts number of tries, the waiter raises a | ||
WaiterException. Both `retry` and `maxAttempts` can be overridden by the user when calling | ||
`waiter.wait()` like any other waiter. | ||
|
||
### That's It! | ||
|
||
The AwsBaseHook handles the rest. Using the above waiter will look like this: | ||
`EksHook().get_waiter("all_nodegroups_deleted").wait(clusterName="my_cluster")` | ||
and for testing purposes, a `list_custom_waiters()` helper method is proved which can | ||
be used the same way: `EksHook().list_custom_waiters()` | ||
|
||
|
||
### In your Operators (How to use these) | ||
|
||
Once configured correctly, the custom waiter will be nearly indistinguishable from an official waiter. | ||
Below is an example of an official waiter followed by a custom one. | ||
|
||
```python | ||
EksHook().conn.get_waiter("nodegroup_deleted").wait(clusterName=cluster_name, nodegroupName=nodegroup_name) | ||
EksHook().get_waiter("all_nodegroups_deleted").wait(clusterName=cluster_name) | ||
``` | ||
|
||
Note that since the get_waiter is in the hook instead of on the client side, a custom waiter is | ||
just `hook.get_waiter` and not `hook.conn.get_waiter`. Other than that, they should be identical. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Licensed to the Apache Software Foundation (ASF) under one | ||
# or more contributor license agreements. See the NOTICE file | ||
# distributed with this work for additional information | ||
# regarding copyright ownership. The ASF licenses this file | ||
# to you 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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Licensed to the Apache Software Foundation (ASF) under one | ||
# or more contributor license agreements. See the NOTICE file | ||
# distributed with this work for additional information | ||
# regarding copyright ownership. The ASF licenses this file | ||
# to you 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. | ||
|
||
from __future__ import annotations | ||
|
||
import boto3 | ||
from botocore.waiter import Waiter, WaiterModel, create_waiter_with_client | ||
|
||
|
||
class BaseBotoWaiter: | ||
""" | ||
Used to create custom Boto3 Waiters. | ||
|
||
For more details, see airflow/providers/amazon/aws/waiters/README.md | ||
""" | ||
|
||
def __init__(self, client: boto3.client, model_config: dict) -> None: | ||
self.model = WaiterModel(model_config) | ||
self.client = client | ||
|
||
def waiter(self, waiter_name: str) -> Waiter: | ||
return create_waiter_with_client(waiter_name=waiter_name, waiter_model=self.model, client=self.client) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"version": 2, | ||
"waiters": { | ||
"all_nodegroups_deleted": { | ||
"operation": "ListNodegroups", | ||
"delay": 30, | ||
"maxAttempts": 60, | ||
"acceptors": [ | ||
{ | ||
"matcher": "path", | ||
"argument": "length(nodegroups[]) == `0`", | ||
"expected": true, | ||
"state": "success" | ||
}, | ||
{ | ||
"matcher": "path", | ||
"expected": true, | ||
"argument": "length(nodegroups[]) > `0`", | ||
"state": "retry" | ||
} | ||
] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought BatchClient already implements some kind of waiters (I personally never use it in this hook)
airflow/providers/amazon/aws/hooks/batch_waiters.json
airflow/providers/amazon/aws/hooks/batch_waiters.py
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes? Looks like it. I've never used that one and it's not something you could inherit and use for other services.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean a good point one day also migrate batch waiters to generic solution
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this would lay the framework for that and adding whatever other custom waiters that folks want to make. The more I look at it, the more I think it'll either simplify or replace a lot of Sensors as well, which wasn't the intended purpose but a very nice side effect.