This commit is contained in:
abikouo
2021-05-20 10:29:30 +02:00
parent e29e35de03
commit 0a28aa02e8
6 changed files with 113 additions and 20 deletions

View File

@@ -0,0 +1,3 @@
---
minor_changes:
- k8s - add new option ``wait_property`` to support ability to wait on arbitrary property (https://github.com/ansible-collections/kubernetes.core/pull/105).

View File

@@ -364,6 +364,93 @@
that:
- short_wait_remove_pod is failed
- name: add a simple crashing pod and wait until container is running
k8s:
definition:
apiVersion: v1
kind: Pod
metadata:
name: pod-crash-0
namespace: "{{ wait_namespace }}"
spec:
containers:
- name: crashing-container
image: busybox
command: ['/dummy/dummy-shell', '-c', 'sleep 2000']
wait: yes
wait_timeout: 10
wait_property:
property: status.containerStatuses[*].state.running
ignore_errors: true
register: crash_pod
- name: assert that task failed
assert:
that:
- crash_pod is failed
- crash_pod.changed
- '"Resource creation timed out" in crash_pod.msg'
- name: add a valid pod and wait until container is running
k8s:
definition:
apiVersion: v1
kind: Pod
metadata:
name: pod-valid-0
namespace: "{{ wait_namespace }}"
spec:
containers:
- name: crashing-container
image: busybox
command: ['/bin/sh', '-c', 'sleep 10000']
wait: yes
wait_timeout: 10
wait_property:
property: status.containerStatuses[*].state.running
ignore_errors: true
register: valid_pod
- name: assert that task failed
assert:
that:
- valid_pod is successful
- valid_pod.changed
- valid_pod.result.status.containerStatuses[0].state.running is defined
- name: create pod (waiting for container.ready set to false)
k8s:
definition:
apiVersion: v1
kind: Pod
metadata:
name: redis-pod
namespace: "{{ wait_namespace }}"
spec:
containers:
- name: redis-container
image: redis
volumeMounts:
- name: test
mountPath: "/etc/test"
readOnly: true
volumes:
- name: test
configMap:
name: redis-config
wait: yes
wait_timeout: 10
wait_property:
property: status.containerStatuses[0].ready
value: "false"
register: wait_boolean
- name: assert that pod was created but not running
assert:
that:
- wait_boolean.changed
- wait_boolean.result.status.phase == 'Pending'
always:
- name: Remove namespace
k8s:

View File

@@ -69,6 +69,7 @@ options:
- Specifies a property on the resource to wait for.
- Ignored if C(wait) is not set or is set to I(False).
type: dict
version_added: '2.0.0'
suboptions:
property:
type: str
@@ -80,5 +81,6 @@ options:
type: str
description:
- The expected value of the C(property).
- The value is not case-sensitive.
- If this is missing, we will check only that the attribute C(property) is present.
'''

View File

@@ -434,16 +434,8 @@ class K8sAnsibleMixin(object):
def _resource_absent(resource):
return not resource
with open("/tmp/resource.txt", "w+") as f:
import json
f.write("------- Property -------\n{}".format(json.dumps(property, indent=2)))
def _wait_for_property(resource):
test = match_json_property(self, resource.to_dict(), property.get('property'), property.get('value', None))
with open("/tmp/resource.txt", "w+") as f:
import json
f.write("------- test = {}\n{}".format(test, json.dumps(resource.to_dict(), indent=2)))
return test
return match_json_property(self, resource.to_dict(), property.get('property'), property.get('value', None))
waiter = dict(
Deployment=_deployment_ready,

View File

@@ -23,11 +23,10 @@ from ansible.module_utils._text import to_native
try:
import jmespath
HAS_JMESPATH_LIB = True
jmespath_import_exception = None
JMESPATH_IMP_ERR = None
except ImportError as e:
HAS_JMESPATH_LIB = False
jmespath_import_exception = e
JMESPATH_IMP_ERR = traceback.format_exc()
JMESPATH_IMP_ERR = e
def match_json_property(module, data, expr, value=None):
@@ -44,18 +43,29 @@ def match_json_property(module, data, expr, value=None):
raise err
def _match_value(buf, v):
# convert all values from bool to str and lowercase them
return v.lower() in [str(i).lower() for i in buf]
if isinstance(buf, list):
# convert all values from bool to str and lowercase them
return v.lower() in [str(i).lower() for i in buf]
elif isinstance(buf, str):
return v.lower() == content.lower()
elif isinstance(buf, bool):
return v.lower() == str(content).lower()
else:
# unable to test single value against dict
return False
if not HAS_JMESPATH_LIB:
_raise_or_fail(jmespath_import_exception, msg=missing_required_lib('jmespath'), exception=JMESPATH_IMP_ERR)
_raise_or_fail(JMESPATH_IMP_ERR, msg=missing_required_lib('jmespath'))
jmespath.functions.REVERSE_TYPES_MAP['string'] = jmespath.functions.REVERSE_TYPES_MAP['string'] + ('AnsibleUnicode', 'AnsibleUnsafeText', )
try:
content = jmespath.search(expr, data)
if not content:
with open("/tmp/play.cont", "w") as f:
f.write("{}".format(content))
if content is None or content == []:
return False
if not value or _match_value(content, value):
if value is None or _match_value(content, value):
# looking for state present
return True
return False
except Exception as err:

View File

@@ -24,7 +24,6 @@ jmespath = pytest.importorskip("jmespath")
def test_property_present():
data = {
"Kind": "Pod",
"containers": [
{"name": "t0", "image": "nginx"},
{"name": "t1", "image": "python"},
@@ -37,7 +36,6 @@ def test_property_present():
def test_property_value():
data = {
"Kind": "Pod",
"containers": [
{"name": "t0", "image": "nginx"},
{"name": "t1", "image": "python"},
@@ -52,7 +50,7 @@ def test_property_value():
def test_boolean_value():
data = {
"containers": [
{"image": "nginx"},
{"image": "nginx", "poweron": False},
{"image": "python"},
{"image": "mongo", "connected": True}
]
@@ -60,6 +58,7 @@ def test_boolean_value():
assert match_json_property(None, data, "containers[*].connected", "true")
assert match_json_property(None, data, "containers[*].connected", "True")
assert match_json_property(None, data, "containers[*].connected", "TRUE")
assert match_json_property(None, data, "containers[0].poweron", "false")
def test_valid_expression():