Skip to content

Commit ecfd167

Browse files
committed
Include latest tests improvements.
Add pytest hook to update test report. Change condition back to 'ContainersReady'. Increase time of waiting fot Deployment removal. Set strict versions to python libraries.
1 parent b7df06c commit ecfd167

12 files changed

+84
-46
lines changed

deployments/custom-resource-definitions/virtualserver.yaml

Lines changed: 0 additions & 17 deletions
This file was deleted.

tests/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ NODE_IP =
88
TAG = latest
99
PREFIX = test-runner
1010
KUBE_CONFIG_FOLDER = $${HOME}/.kube
11+
SHOW_IC_LOGS = no
12+
PYTEST_ARGS =
1113

1214
build:
1315
docker build -t $(PREFIX):$(TAG) -f docker/Dockerfile ..
1416

1517
run-tests:
16-
docker run --rm -v $(KUBE_CONFIG_FOLDER):/root/.kube $(PREFIX):$(TAG) --context=$(CONTEXT) --image=$(BUILD_IMAGE) --image-pull-policy=$(PULL_POLICY) --deployment-type=$(DEPLOYMENT_TYPE) --ic-type=$(IC_TYPE) --service=$(SERVICE) --node-ip=$(NODE_IP)
18+
docker run --rm -v $(KUBE_CONFIG_FOLDER):/root/.kube $(PREFIX):$(TAG) --context=$(CONTEXT) --image=$(BUILD_IMAGE) --image-pull-policy=$(PULL_POLICY) --deployment-type=$(DEPLOYMENT_TYPE) --ic-type=$(IC_TYPE) --service=$(SERVICE) --node-ip=$(NODE_IP) --show-ic-logs=$(SHOW_IC_LOGS) $(PYTEST_ARGS)

tests/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,7 @@ The table below shows various configuration options for the tests. If you use Py
5252
| `--node-ip` | `NODE_IP` | The public IP of a cluster node. Not required if you use the loadbalancer service (see --service argument). | `""` |
5353
| `--kubeconfig` | `N/A` | An absolute path to a kubeconfig file. | `~/.kube/config` or the value of the `KUBECONFIG` env variable |
5454
| `N/A` | `KUBE_CONFIG_FOLDER` | A path to a folder with a kubeconfig file. | `~/.kube/` |
55+
| `--show-ic-logs` | `SHOW_IC_LOGS` | A flag to control accumulating IC logs in stdout. | `no` |
56+
| `N/A` | `PYTEST_ARGS` | Any additional pytest command-line arguments (i.e `-m "smoke"`) | `""` |
5557

5658
If you would like to use an IDE (such as PyCharm) to run the tests, use the [pytest.ini](pytest.ini) file to set the command-line arguments.

tests/conftest.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from kubernetes.config.kube_config import KUBE_CONFIG_DEFAULT_LOCATION
77
from settings import DEFAULT_IMAGE, DEFAULT_PULL_POLICY, DEFAULT_IC_TYPE, DEFAULT_SERVICE, DEFAULT_DEPLOYMENT_TYPE
8+
from suite.resources_utils import get_first_pod_name
89

910

1011
def pytest_addoption(parser) -> None:
@@ -33,6 +34,7 @@ def pytest_addoption(parser) -> None:
3334
action="store",
3435
default=os.path.expanduser(KUBE_CONFIG_DEFAULT_LOCATION),
3536
help="An absolute path to a kubeconfig file.")
37+
parser.addoption("--show-ic-logs", action="store", default="no", help="Show IC logs in stdout on test failure")
3638

3739

3840
# import fixtures into pytest global namespace
@@ -54,3 +56,32 @@ def pytest_collection_modifyitems(config, items) -> None:
5456
for item in items:
5557
if "skip_for_nginx_oss" in item.keywords:
5658
item.add_marker(skip_for_nginx_oss)
59+
if config.getoption("--ic-type") == "nginx-plus-ingress":
60+
skip_for_nginx_plus = pytest.mark.skip(reason="Skip a test for Nginx Plus")
61+
for item in items:
62+
if "skip_for_nginx_plus" in item.keywords:
63+
item.add_marker(skip_for_nginx_plus)
64+
65+
66+
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
67+
def pytest_runtest_makereport(item) -> None:
68+
"""
69+
Print out IC Pod logs on test failure.
70+
71+
Only look at actual failing test calls, not setup/teardown.
72+
Only show the logs if commandline argument `--show-ic-logs` is set to 'yes'
73+
74+
:param item:
75+
:return:
76+
"""
77+
# execute all other hooks to obtain the report object
78+
outcome = yield
79+
rep = outcome.get_result()
80+
81+
# we only look at actual failing test calls, not setup/teardown
82+
if rep.when == "call" and rep.failed and item.config.getoption("--show-ic-logs") == "yes":
83+
pod_namespace = item.funcargs['ingress_controller_prerequisites'].namespace
84+
pod_name = get_first_pod_name(item.funcargs['kube_apis'].v1, pod_namespace)
85+
print("\n===================== IC Logs Start =====================")
86+
print(item.funcargs['kube_apis'].v1.read_namespaced_pod_log(pod_name, pod_namespace))
87+
print("\n===================== IC Logs End =====================")

tests/requirements.txt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
PyYAML
2-
requests
3-
forcediphttpsadapter
1+
PyYAML==5.1.2
2+
requests==2.22.0
3+
forcediphttpsadapter==1.0.1
44
kubernetes==8.0.1
5-
pytest
6-
ipaddress>=1.0.17
7-
pyopenssl
8-
certifi
9-
urllib3
5+
pytest==4.4.1
6+
ipaddress==1.0.22 # >= 1.0.17
7+
pyopenssl==19.0.0
8+
certifi==2019.6.16
9+
urllib3==1.25.3

tests/suite/resources_utils.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -157,21 +157,21 @@ def create_daemon_set(extensions_v1_beta1: ExtensionsV1beta1Api, namespace, body
157157

158158
def wait_until_all_pods_are_ready(v1: CoreV1Api, namespace) -> None:
159159
"""
160-
Wait for all the pods to be 'Ready'.
160+
Wait for all the pods to be 'ContainersReady'.
161161
162162
:param v1: CoreV1Api
163163
:param namespace: namespace of a pod
164164
:return:
165165
"""
166-
print("Start waiting for all pods in a namespace to be Ready")
166+
print("Start waiting for all pods in a namespace to be ContainersReady")
167167
counter = 0
168168
while not are_all_pods_in_ready_state(v1, namespace) and counter < 20:
169-
print("There are pods that are not running. Wait for 4 sec...")
169+
print("There are pods that are not ContainersReady. Wait for 4 sec...")
170170
time.sleep(4)
171171
counter = counter + 1
172172
if counter >= 20:
173-
pytest.fail("After several seconds the pods aren't Ready. Exiting...")
174-
print("All pods are Ready")
173+
pytest.fail("After several seconds the pods aren't ContainersReady. Exiting...")
174+
print("All pods are ContainersReady")
175175

176176

177177
def get_first_pod_name(v1: CoreV1Api, namespace) -> str:
@@ -188,7 +188,7 @@ def get_first_pod_name(v1: CoreV1Api, namespace) -> str:
188188

189189
def are_all_pods_in_ready_state(v1: CoreV1Api, namespace) -> bool:
190190
"""
191-
Check if all the pods have Ready condition.
191+
Check if all the pods have ContainersReady condition.
192192
193193
:param v1: CoreV1Api
194194
:param namespace: namespace
@@ -202,8 +202,8 @@ def are_all_pods_in_ready_state(v1: CoreV1Api, namespace) -> bool:
202202
if pod.status.conditions is None:
203203
return False
204204
for condition in pod.status.conditions:
205-
# wait for 'Ready' state instead of 'ContainersReady' for backwards compatibility with k8s 1.10
206-
if condition.type == 'Ready' and condition.status == 'True':
205+
# wait for 'ContainersReady' no backwards compatibility with k8s 1.10
206+
if condition.type == 'ContainersReady' and condition.status == 'True':
207207
pod_ready_amount = pod_ready_amount + 1
208208
break
209209
return pod_ready_amount == len(pods.items)
@@ -385,12 +385,12 @@ def ensure_item_removal(get_item, *args, **kwargs) -> None:
385385
"""
386386
try:
387387
counter = 0
388-
while counter < 20:
388+
while counter < 30:
389389
time.sleep(1)
390390
get_item(*args, **kwargs)
391391
counter = counter + 1
392-
if counter >= 20:
393-
pytest.fail("Failed to remove the item after 20 seconds")
392+
if counter >= 30:
393+
pytest.fail("Failed to remove the item after 30 seconds")
394394
except ApiException as ex:
395395
if ex.status == 404:
396396
print("Item was removed")
@@ -938,9 +938,10 @@ def ensure_response_from_backend(req_url, host) -> None:
938938
:param host:
939939
:return:
940940
"""
941-
for _ in range(5):
941+
for _ in range(10):
942942
resp = requests.get(req_url, headers={"host": host}, verify=False)
943943
if resp.status_code != 502:
944+
print(f"At last after {_ * 2} seconds got 200. Continue...")
944945
return
945946
time.sleep(2)
946-
pytest.fail(f"Keep getting 502 from {req_url} after 10 seconds. Exiting...")
947+
pytest.fail(f"Keep getting 502 from {req_url} after 20 seconds. Exiting...")

tests/suite/test_v_s_route.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ def assert_event_and_get_count(event_text, events_list) -> int:
190190
pytest.fail(f"Failed to find the event \"{event_text}\" in the list. Exiting...")
191191

192192

193+
@pytest.mark.smoke
193194
@pytest.mark.parametrize('crd_ingress_controller',
194195
[({"type": "complete", "extra_args": [f"-enable-custom-resources"]})],
195196
indirect=True)

tests/suite/test_virtual_server.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from suite.yaml_utils import get_paths_from_vs_yaml, get_first_vs_host_from_yaml, get_names_from_yaml
1010

1111

12+
@pytest.mark.smoke
1213
@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup',
1314
[({"type": "complete", "extra_args": [f"-enable-custom-resources"]}, {"example": "virtual-server", "app_type": "simple"})],
1415
indirect=True)
@@ -179,6 +180,24 @@ def test_responses_after_crd_removal_on_the_fly(self, kube_apis, crd_ingress_con
179180
assert resp.status_code == 200
180181

181182

183+
def wait_and_assert_status_code(code, req_url, host) -> None:
184+
"""
185+
Wait for a specific response status code.
186+
187+
:param code: status_code
188+
:param req_url: request url
189+
:param host: request headers if any
190+
:return:
191+
"""
192+
counter = 0
193+
resp = requests.get(req_url, headers={"host": host})
194+
while not resp.status_code == code and counter <= 4:
195+
wait_before_test(1)
196+
counter = counter + 1
197+
resp = requests.get(req_url, headers={"host": host})
198+
assert resp.status_code == code, f"After a few seconds the status_code is not {code}"
199+
200+
182201
@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup',
183202
[({"type": "rbac-without-vs", "extra_args": [f"-enable-custom-resources"]},
184203
{"example": "virtual-server", "app_type": "simple"})],
@@ -195,10 +214,5 @@ def test_responses_after_rbac_misconfiguration(self, kube_apis, crd_ingress_cont
195214

196215
print("Step 2: configure RBAC and check")
197216
patch_rbac(kube_apis.rbac_v1_beta1, f"{DEPLOYMENTS}/rbac/rbac.yaml")
198-
wait_before_test(1)
199-
resp = requests.get(virtual_server_setup.backend_1_url,
200-
headers={"host": virtual_server_setup.vs_host})
201-
assert resp.status_code == 200
202-
resp = requests.get(virtual_server_setup.backend_2_url,
203-
headers={"host": virtual_server_setup.vs_host})
204-
assert resp.status_code == 200
217+
wait_and_assert_status_code(200, virtual_server_setup.backend_1_url, virtual_server_setup.vs_host)
218+
wait_and_assert_status_code(200, virtual_server_setup.backend_2_url, virtual_server_setup.vs_host)

tests/suite/test_virtual_server_advanced_routing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ def execute_assertions(resp_1, resp_2, resp_3):
1616
assert "Server name: backend4-" in resp_3.text
1717

1818

19+
@pytest.mark.smoke
1920
@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup',
2021
[({"type": "complete", "extra_args": [f"-enable-custom-resources"]},
2122
{"example": "virtual-server-advanced-routing", "app_type": "advanced-routing"})],

tests/suite/test_virtual_server_split_traffic.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def get_upstreams_of_splitting(file) -> []:
3838
return upstreams
3939

4040

41+
@pytest.mark.smoke
4142
@pytest.mark.parametrize('crd_ingress_controller, virtual_server_setup',
4243
[({"type": "complete", "extra_args": [f"-enable-custom-resources"]},
4344
{"example": "virtual-server-split-traffic", "app_type": "split"})],

0 commit comments

Comments
 (0)