Skip to content
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

Daemonset ready check #88

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added chaosk8s/daemonset/__init__.py
Empty file.
49 changes: 49 additions & 0 deletions chaosk8s/daemonset/probes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
from typing import Union
import urllib3
from chaoslib.types import Secrets
from chaoslib.exceptions import ActivityFailed
from kubernetes import client
from logzero import logger
from chaosk8s import create_k8s_api_client

__all__ = ["daemonset_ready"]


def daemonset_ready(name: str, ns: str = "default",
label_selector: str = "name in ({name})",
timeout: int = 30,
secrets: Secrets = None):
"""
Check that the DaemonSet has no misscheduled or unavailable pods

Raises :exc:`chaoslib.exceptions.ActivityFailed` when the state is not
as expected.
"""
api = create_k8s_api_client(secrets)

v1 = client.AppsV1Api(api)

ret = v1.list_namespaced_daemon_set(ns, label_selector=label_selector)
logger.debug("Found {d} daemonsets".format(d=len(ret.items)))

if not ret.items:
raise ActivityFailed(
"DaemonSet '{name}' was not found".format(name=name))

for ds in ret.items:
logger.debug("DaemonSet has '{u}' unavailable replicas and \
'{m}' misscheduled".format(
u=ds.status.number_unavailable,
m=ds.status.number_misscheduled))
if (
(ds.status.number_unavailable is not None
and ds.status.number_unavailable != 0)
or ds.status.number_misscheduled != 0
):
raise ActivityFailed(
"DaemonSet has '{u}' unavailable replicas "
"and '{m}' misscheduled".format(
u=ds.status.number_unavailable,
m=ds.status.number_misscheduled))
return True
66 changes: 66 additions & 0 deletions tests/test_daemonset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
from unittest.mock import MagicMock, patch, ANY, call

import pytest
from kubernetes import stream
from chaoslib.exceptions import ActivityFailed, InvalidActivity
from chaoslib.provider.python import validate_python_activity

from chaosk8s.daemonset.probes import daemonset_ready


@patch('chaosk8s.has_local_config_file', autospec=True)
@patch('chaosk8s.daemonset.probes.client', autospec=True)
@patch('chaosk8s.client')
def test_daemonset_ready(cl, client, has_conf):
has_conf.return_value = False

ds = MagicMock()
ds.status.number_unavailable = None
ds.status.number_misscheduled = 0
result = MagicMock()
result.items = [ds,ds]

v1 = MagicMock()
v1.list_namespaced_daemon_set.return_value = result
client.AppsV1Api.return_value = v1

assert daemonset_ready("test")


@patch('chaosk8s.has_local_config_file', autospec=True)
@patch('chaosk8s.daemonset.probes.client', autospec=True)
@patch('chaosk8s.client')
def test_daemonset_not_ready(cl, client, has_conf):
has_conf.return_value = False

ds = MagicMock()
ds.status.number_unavailable = 1
ds.status.number_misscheduled = 0
result = MagicMock()
result.items = [ds,ds]

v1 = MagicMock()
v1.list_namespaced_daemon_set.return_value = result
client.AppsV1Api.return_value = v1

with pytest.raises(ActivityFailed) as excinfo:
daemonset_ready("test")
assert "DaemonSet has '1' unavailable replicas and '0' misscheduled" in str(excinfo.value)

@patch('chaosk8s.has_local_config_file', autospec=True)
@patch('chaosk8s.daemonset.probes.client', autospec=True)
@patch('chaosk8s.client')
def test_daemonset_ready_not_found(cl, client, has_conf):
has_conf.return_value = False
result = MagicMock()
result.items = []

v1 = MagicMock()
v1.list_namespaced_daemon_set.return_value = result
client.AppsV1Api.return_value = v1

name = "test"
with pytest.raises(ActivityFailed) as excinfo:
daemonset_ready(name)
assert "DaemonSet '{name}' was not found".format(name=name) in str(excinfo.value)