Skip to content
Draft
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
10 changes: 6 additions & 4 deletions chaosk8s/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
# -*- coding: utf-8 -*-
import json
import os
import os.path
from typing import List

from chaoslib.discovery.discover import discover_actions, discover_probes, \
initialize_discovery_result
from chaoslib.exceptions import DiscoveryFailed
from chaoslib.types import Discovery, DiscoveredActivities, \
DiscoveredSystemInfo, Secrets
from chaoslib.types import Discovery, DiscoveredActivities, Secrets
from kubernetes import client, config
from logzero import logger

Expand Down Expand Up @@ -139,3 +136,8 @@ def load_exported_activities() -> List[DiscoveredActivities]:
activities.extend(discover_probes("chaosk8s.pod.probes"))
activities.extend(discover_actions("chaosk8s.node.actions"))
return activities


def _log_deprecated(name: str, alt_name: str):
logger.warning("{} function is DEPRECATED and will be removed in the next releases, please use {} instead".format(
name, alt_name))
131 changes: 26 additions & 105 deletions chaosk8s/actions.py
Original file line number Diff line number Diff line change
@@ -1,123 +1,44 @@
# -*- coding: utf-8 -*-
import json
import os.path

import yaml
from chaoslib.exceptions import ActivityFailed
from chaoslib.types import Secrets
from kubernetes import client
from kubernetes.client.rest import ApiException
from logzero import logger

from chaosk8s import create_k8s_api_client
from chaosk8s import _log_deprecated
from chaosk8s.deployment.actions import create_deployment, delete_deployment, scale_deployment
from chaosk8s.replicaset.actions import delete_replica_set
from chaosk8s.pod.actions import delete_pods
from chaosk8s.service.actions import delete_service

__all__ = ["start_microservice", "kill_microservice", "scale_microservice",
"remove_service_endpoint"]


def start_microservice(spec_path: str, ns: str = "default",
secrets: Secrets = None):
def start_microservice(spec_path: str, ns: str = "default", secrets: Secrets = None):
"""
Start a microservice described by the deployment config, which must be the
path to the JSON or YAML representation of the deployment.
!!!DEPRECATED!!!
"""
api = create_k8s_api_client(secrets)

with open(spec_path) as f:
p, ext = os.path.splitext(spec_path)
if ext == '.json':
deployment = json.loads(f.read())
elif ext in ['.yml', '.yaml']:
deployment = yaml.load(f.read())
else:
raise ActivityFailed(
"cannot process {path}".format(path=spec_path))

v1 = client.AppsV1beta1Api(api)
resp = v1.create_namespaced_deployment(ns, body=deployment)
return resp
_log_deprecated("start_microservice", "create_deployment")
create_deployment(spec_path, ns, secrets)


def kill_microservice(name: str, ns: str = "default",
label_selector: str = "name in ({name})",
secrets: Secrets = None):
def remove_service_endpoint(name: str, ns: str = "default", secrets: Secrets = None):
"""
Kill a microservice by `name` in the namespace `ns`.

The microservice is killed by deleting the deployment for it without
a graceful period to trigger an abrupt termination.

The selected resources are matched by the given `label_selector`.
!!!DEPRECATED!!!
"""
label_selector = label_selector.format(name=name)
api = create_k8s_api_client(secrets)

v1 = client.AppsV1beta1Api(api)
if label_selector:
ret = v1.list_namespaced_deployment(ns, label_selector=label_selector)
else:
ret = v1.list_namespaced_deployment(ns)

logger.debug("Found {d} deployments named '{n}'".format(
d=len(ret.items), n=name))

body = client.V1DeleteOptions()
for d in ret.items:
res = v1.delete_namespaced_deployment(
d.metadata.name, ns, body)

v1 = client.ExtensionsV1beta1Api(api)
if label_selector:
ret = v1.list_namespaced_replica_set(ns, label_selector=label_selector)
else:
ret = v1.list_namespaced_replica_set(ns)
_log_deprecated("remove_service_endpoint", "delete_service")
delete_service(name, ns, secrets)

logger.debug("Found {d} replica sets named '{n}'".format(
d=len(ret.items), n=name))

body = client.V1DeleteOptions()
for r in ret.items:
res = v1.delete_namespaced_replica_set(
r.metadata.name, ns, body)

v1 = client.CoreV1Api(api)
if label_selector:
ret = v1.list_namespaced_pod(ns, label_selector=label_selector)
else:
ret = v1.list_namespaced_pod(ns)

logger.debug("Found {d} pods named '{n}'".format(
d=len(ret.items), n=name))

body = client.V1DeleteOptions()
for p in ret.items:
res = v1.delete_namespaced_pod(
p.metadata.name, ns, body)


def remove_service_endpoint(name: str, ns: str = "default",
secrets: Secrets = None):
def scale_microservice(name: str, replicas: int, ns: str = "default",
secrets: Secrets = None):
"""
Remove the service endpoint that sits in front of microservices (pods).
!!!DEPRECATED!!!
"""
api = create_k8s_api_client(secrets)
_log_deprecated("scale_microserviceal", "scale_deployment")
scale_deployment(name, replicas, ns, secrets)

v1 = client.CoreV1Api(api)
v1.delete_namespaced_service(name, namespace=ns)


def scale_microservice(name: str, replicas: int, ns: str = "default",
secrets: Secrets = None):
def kill_microservice(name: str, ns: str = "default",
label_selector: str = "name in ({name})",
secrets: Secrets = None):
"""
Scale a deployment up or down. The `name` is the name of the deployment.
!!!DEPRECATED!!!
"""
api = create_k8s_api_client(secrets)

v1 = client.ExtensionsV1beta1Api(api)
body = {"spec": {"replicas": replicas}}
try:
v1.patch_namespaced_deployment_scale(name, namespace=ns, body=body)
except ApiException as e:
raise ActivityFailed(
"failed to scale '{s}' to {r} replicas: {e}".format(
s=name, r=replicas, e=str(e)))
_log_deprecated("kill_microservice", "delete_deployment/delete_replica_set/delete_pods")
delete_deployment(name, ns, label_selector, secrets)
delete_replica_set(name, ns, label_selector, secrets)
delete_pods(name, ns, label_selector, secrets)
Empty file added chaosk8s/deployment/__init__.py
Empty file.
79 changes: 79 additions & 0 deletions chaosk8s/deployment/actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import json
import os.path
import yaml

from chaoslib.exceptions import ActivityFailed
from chaoslib.types import Secrets
from kubernetes import client
from logzero import logger
from kubernetes.client.rest import ApiException

from chaosk8s import create_k8s_api_client

__all__ = ["create_deployment", "delete_deployment"]


def create_deployment(spec_path: str, ns: str = "default", secrets: Secrets = None):
"""
Create a deployment described by the deployment config, which must be the
path to the JSON or YAML representation of the deployment.
"""
api = create_k8s_api_client(secrets)

with open(spec_path) as f:
p, ext = os.path.splitext(spec_path)
if ext == '.json':
deployment = json.loads(f.read())
elif ext in ['.yml', '.yaml']:
deployment = yaml.load(f.read())
else:
raise ActivityFailed(
"cannot process {path}".format(path=spec_path))

v1 = client.AppsV1beta1Api(api)
resp = v1.create_namespaced_deployment(ns, body=deployment)
return resp


def delete_deployment(name: str, ns: str = "default",
label_selector: str = "name in ({name})",
secrets: Secrets = None):
"""
Delete a deployment by `name` in the namespace `ns`.

The deployment is deleted without a graceful period to trigger an abrupt termination.

The selected resources are matched by the given `label_selector`.
"""
label_selector = label_selector.format(name=name)
api = create_k8s_api_client(secrets)

v1 = client.AppsV1beta1Api(api)
if label_selector:
ret = v1.list_namespaced_deployment(ns, label_selector=label_selector)
else:
ret = v1.list_namespaced_deployment(ns)

logger.debug("Found {d} deployments named '{n}'".format(
d=len(ret.items), n=name))

body = client.V1DeleteOptions()
for d in ret.items:
v1.delete_namespaced_deployment(d.metadata.name, ns, body)


def scale_deployment(name: str, replicas: int, ns: str = "default",
secrets: Secrets = None):
"""
Scale a deployment up or down. The `name` is the name of the deployment.
"""
api = create_k8s_api_client(secrets)

v1 = client.ExtensionsV1beta1Api(api)
body = {"spec": {"replicas": replicas}}
try:
v1.patch_namespaced_deployment_scale(name, namespace=ns, body=body)
except ApiException as e:
raise ActivityFailed(
"failed to scale '{s}' to {r} replicas: {e}".format(
s=name, r=replicas, e=str(e)))
30 changes: 28 additions & 2 deletions chaosk8s/pod/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from chaosk8s import create_k8s_api_client

__all__ = ["terminate_pods"]
__all__ = ["terminate_pods", "delete_pods"]


def terminate_pods(label_selector: str = None, name_pattern: str = None,
Expand Down Expand Up @@ -93,4 +93,30 @@ def terminate_pods(label_selector: str = None, name_pattern: str = None,
body = client.V1DeleteOptions(grace_period_seconds=grace_period)

for p in pods:
res = v1.delete_namespaced_pod(p.metadata.name, ns, body=body)
v1.delete_namespaced_pod(p.metadata.name, ns, body=body)


def delete_pods(name: str, ns: str = "default",
label_selector: str = "name in ({name})",
secrets: Secrets = None):
"""
Delete pods by `name` in the namespace `ns`.

The pods are deleted without a graceful period to trigger an abrupt termination.

The selected resources are matched by the given `label_selector`.
"""
label_selector = label_selector.format(name=name)
api = create_k8s_api_client(secrets)
v1 = client.CoreV1Api(api)
if label_selector:
ret = v1.list_namespaced_pod(ns, label_selector=label_selector)
else:
ret = v1.list_namespaced_pod(ns)

logger.debug("Found {d} pods named '{n}'".format(
d=len(ret.items), n=name))

body = client.V1DeleteOptions()
for p in ret.items:
v1.delete_namespaced_pod(p.metadata.name, ns, body)
Empty file added chaosk8s/replicaset/__init__.py
Empty file.
33 changes: 33 additions & 0 deletions chaosk8s/replicaset/actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from chaoslib.types import Secrets
from kubernetes import client
from logzero import logger

from chaosk8s import create_k8s_api_client

__all__ = ["delete_replica_set"]


def delete_replica_set(name: str, ns: str = "default",
label_selector: str = "name in ({name})",
secrets: Secrets = None):
"""
Delete a replica set by `name` in the namespace `ns`.

The replica set is deleted without a graceful period to trigger an abrupt termination.

The selected resources are matched by the given `label_selector`.
"""
label_selector = label_selector.format(name=name)
api = create_k8s_api_client(secrets)
v1 = client.ExtensionsV1beta1Api(api)
if label_selector:
ret = v1.list_namespaced_replica_set(ns, label_selector=label_selector)
else:
ret = v1.list_namespaced_replica_set(ns)

logger.debug("Found {d} replica sets named '{n}'".format(
d=len(ret.items), n=name))

body = client.V1DeleteOptions()
for r in ret.items:
v1.delete_namespaced_replica_set(r.metadata.name, ns, body)
Empty file added chaosk8s/service/__init__.py
Empty file.
15 changes: 15 additions & 0 deletions chaosk8s/service/actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from chaoslib.types import Secrets
from kubernetes import client

from chaosk8s import create_k8s_api_client

__all__ = ["delete_service"]


def delete_service(name: str, ns: str = "default", secrets: Secrets = None):
"""
Remove the given service
"""
api = create_k8s_api_client(secrets)
v1 = client.CoreV1Api(api)
v1.delete_namespaced_service(name, namespace=ns)
Loading