diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0baa39bc..387ab60a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -84,9 +84,9 @@ jobs: echo "test_namespace" >> ./CI/tests/functional_tests echo "test_net_chaos" >> ./CI/tests/functional_tests echo "test_time" >> ./CI/tests/functional_tests - echo "test_arca_cpu_hog" >> ./CI/tests/functional_tests - echo "test_arca_memory_hog" >> ./CI/tests/functional_tests - echo "test_arca_io_hog" >> ./CI/tests/functional_tests + echo "test_cpu_hog" >> ./CI/tests/functional_tests + echo "test_memory_hog" >> ./CI/tests/functional_tests + echo "test_io_hog" >> ./CI/tests/functional_tests # Push on main only steps + all other functional to collect coverage @@ -113,9 +113,9 @@ jobs: echo "test_namespace" >> ./CI/tests/functional_tests echo "test_net_chaos" >> ./CI/tests/functional_tests echo "test_time" >> ./CI/tests/functional_tests - echo "test_arca_cpu_hog" >> ./CI/tests/functional_tests - echo "test_arca_memory_hog" >> ./CI/tests/functional_tests - echo "test_arca_io_hog" >> ./CI/tests/functional_tests + echo "test_cpu_hog" >> ./CI/tests/functional_tests + echo "test_memory_hog" >> ./CI/tests/functional_tests + echo "test_io_hog" >> ./CI/tests/functional_tests # Final common steps - name: Run Functional tests diff --git a/CI/tests/test_arca_cpu_hog.sh b/CI/tests/test_arca_cpu_hog.sh deleted file mode 100644 index 7989be21..00000000 --- a/CI/tests/test_arca_cpu_hog.sh +++ /dev/null @@ -1,19 +0,0 @@ -set -xeEo pipefail - -source CI/tests/common.sh - -trap error ERR -trap finish EXIT - - -function functional_test_arca_cpu_hog { - yq -i '.input_list[0].node_selector={"kubernetes.io/hostname":"kind-worker2"}' scenarios/kube/cpu-hog/input.yaml - export scenario_type="hog_scenarios" - export scenario_file="scenarios/kube/cpu-hog/input.yaml" - export post_config="" - envsubst < CI/config/common_test_config.yaml > CI/config/arca_cpu_hog.yaml - python3 -m coverage run -a run_kraken.py -c CI/config/arca_cpu_hog.yaml - echo "Arcaflow CPU Hog: Success" -} - -functional_test_arca_cpu_hog \ No newline at end of file diff --git a/CI/tests/test_arca_io_hog.sh b/CI/tests/test_arca_io_hog.sh deleted file mode 100644 index 155cbd11..00000000 --- a/CI/tests/test_arca_io_hog.sh +++ /dev/null @@ -1,19 +0,0 @@ -set -xeEo pipefail - -source CI/tests/common.sh - -trap error ERR -trap finish EXIT - - -function functional_test_arca_io_hog { - yq -i '.input_list[0].node_selector={"kubernetes.io/hostname":"kind-worker2"}' scenarios/kube/io-hog/input.yaml - export scenario_type="hog_scenarios" - export scenario_file="scenarios/kube/io-hog/input.yaml" - export post_config="" - envsubst < CI/config/common_test_config.yaml > CI/config/arca_io_hog.yaml - python3 -m coverage run -a run_kraken.py -c CI/config/arca_io_hog.yaml - echo "Arcaflow IO Hog: Success" -} - -functional_test_arca_io_hog \ No newline at end of file diff --git a/CI/tests/test_arca_memory_hog.sh b/CI/tests/test_arca_memory_hog.sh deleted file mode 100644 index 83e12961..00000000 --- a/CI/tests/test_arca_memory_hog.sh +++ /dev/null @@ -1,19 +0,0 @@ -set -xeEo pipefail - -source CI/tests/common.sh - -trap error ERR -trap finish EXIT - - -function functional_test_arca_memory_hog { - yq -i '.input_list[0].node_selector={"kubernetes.io/hostname":"kind-worker2"}' scenarios/kube/memory-hog/input.yaml - export scenario_type="hog_scenarios" - export scenario_file="scenarios/kube/memory-hog/input.yaml" - export post_config="" - envsubst < CI/config/common_test_config.yaml > CI/config/arca_memory_hog.yaml - python3 -m coverage run -a run_kraken.py -c CI/config/arca_memory_hog.yaml - echo "Arcaflow Memory Hog: Success" -} - -functional_test_arca_memory_hog \ No newline at end of file diff --git a/CI/tests/test_cpu_hog.sh b/CI/tests/test_cpu_hog.sh new file mode 100644 index 00000000..edc09e7e --- /dev/null +++ b/CI/tests/test_cpu_hog.sh @@ -0,0 +1,20 @@ +set -xeEo pipefail + +source CI/tests/common.sh + +trap error ERR +trap finish EXIT + + +function functional_test_cpu_hog { + yq -i '.node_selector="kubernetes.io/hostname=kind-worker2"' scenarios/kube/cpu-hog.yml + + export scenario_type="hog_scenarios" + export scenario_file="scenarios/kube/cpu-hog.yml" + export post_config="" + envsubst < CI/config/common_test_config.yaml > CI/config/cpu_hog.yaml + python3 -m coverage run -a run_kraken.py -c CI/config/cpu_hog.yaml + echo "CPU Hog: Success" +} + +functional_test_cpu_hog \ No newline at end of file diff --git a/CI/tests/test_io_hog.sh b/CI/tests/test_io_hog.sh new file mode 100644 index 00000000..bf7b44ff --- /dev/null +++ b/CI/tests/test_io_hog.sh @@ -0,0 +1,19 @@ +set -xeEo pipefail + +source CI/tests/common.sh + +trap error ERR +trap finish EXIT + + +function functional_test_io_hog { + yq -i '.node_selector="kubernetes.io/hostname=kind-worker2"' scenarios/kube/io-hog.yml + export scenario_type="hog_scenarios" + export scenario_file="scenarios/kube/io-hog.yml" + export post_config="" + envsubst < CI/config/common_test_config.yaml > CI/config/io_hog.yaml + python3 -m coverage run -a run_kraken.py -c CI/config/io_hog.yaml + echo "IO Hog: Success" +} + +functional_test_io_hog \ No newline at end of file diff --git a/CI/tests/test_memory_hog.sh b/CI/tests/test_memory_hog.sh new file mode 100644 index 00000000..5239e281 --- /dev/null +++ b/CI/tests/test_memory_hog.sh @@ -0,0 +1,19 @@ +set -xeEo pipefail + +source CI/tests/common.sh + +trap error ERR +trap finish EXIT + + +function functional_test_memory_hog { + yq -i '.node_selector="kubernetes.io/hostname=kind-worker2"' scenarios/kube/memory-hog.yml + export scenario_type="hog_scenarios" + export scenario_file="scenarios/kube/memory-hog.yml" + export post_config="" + envsubst < CI/config/common_test_config.yaml > CI/config/memory_hog.yaml + python3 -m coverage run -a run_kraken.py -c CI/config/memory_hog.yaml + echo "Memory Hog: Success" +} + +functional_test_memory_hog \ No newline at end of file diff --git a/README.md b/README.md index c75052f9..184c4897 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ Scenario type | Kubernetes [Container Scenarios](docs/container_scenarios.md) | :heavy_check_mark: | [Node Scenarios](docs/node_scenarios.md) | :heavy_check_mark: | [Time Scenarios](docs/time_scenarios.md) | :heavy_check_mark: | -[Hog Scenarios: CPU, Memory](docs/arcaflow_scenarios.md) | :heavy_check_mark: | +[Hog Scenarios: CPU, Memory](docs/hog_scenarios.md) | :heavy_check_mark: | [Cluster Shut Down Scenarios](docs/cluster_shut_down_scenarios.md) | :heavy_check_mark: | [Service Disruption Scenarios](docs/service_disruption_scenarios.md.md) | :heavy_check_mark: | [Zone Outage Scenarios](docs/zone_outage.md) | :heavy_check_mark: | diff --git a/config/config.yaml b/config/config.yaml index f26121de..bf95b95e 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -9,10 +9,9 @@ kraken: chaos_scenarios: # List of policies/chaos scenarios to load - hog_scenarios: - - scenarios/kube/cpu-hog/input.yaml - - scenarios/kube/memory-hog/input.yaml - - scenarios/kube/io-hog/input.yaml - - scenarios/kube/io-hog/input.yaml + - scenarios/kube/cpu-hog.yml + - scenarios/kube/memory-hog.yml + - scenarios/kube/io-hog.yml - application_outages_scenarios: - scenarios/openshift/app_outage.yaml - container_scenarios: # List of chaos pod scenarios to load diff --git a/docs/arcaflow_scenarios.md b/docs/arcaflow_scenarios.md deleted file mode 100644 index 02483d1d..00000000 --- a/docs/arcaflow_scenarios.md +++ /dev/null @@ -1,70 +0,0 @@ -## Arcaflow Scenarios -Arcaflow is a workflow engine in development which provides the ability to execute workflow steps in sequence, in parallel, repeatedly, etc. The main difference to competitors such as Netflix Conductor is the ability to run ad-hoc workflows without an infrastructure setup required. - -The engine uses containers to execute plugins and runs them either locally in Docker/Podman or remotely on a Kubernetes cluster. The workflow system is strongly typed and allows for generating JSON schema and OpenAPI documents for all data formats involved. - -### Available Scenarios -#### Hog scenarios: -- [CPU Hog](arcaflow_scenarios/cpu_hog.md) -- [Memory Hog](arcaflow_scenarios/memory_hog.md) -- [I/O Hog](arcaflow_scenarios/io_hog.md) - - -### Prequisites -Arcaflow supports three deployment technologies: -- Docker -- Podman -- Kubernetes - -#### Docker -In order to run Arcaflow Scenarios with the Docker deployer, be sure that: -- Docker is correctly installed in your Operating System (to find instructions on how to install docker please refer to [Docker Documentation](https://www.docker.com/)) -- The Docker daemon is running - -#### Podman -The podman deployer is built around the podman CLI and doesn't need necessarily to be run along with the podman daemon. -To run Arcaflow Scenarios in your Operating system be sure that: -- podman is correctly installed in your Operating System (to find instructions on how to install podman refer to [Podman Documentation](https://podman.io/)) -- the podman CLI is in your shell PATH - -#### Kubernetes -The kubernetes deployer integrates directly the Kubernetes API Client and needs only a valid kubeconfig file and a reachable Kubernetes/OpenShift Cluster. - -### Usage - -To enable arcaflow scenarios edit the kraken config file, go to the section `kraken -> chaos_scenarios` of the yaml structure -and add a new element to the list named `arcaflow_scenarios` then add the desired scenario -pointing to the `input.yaml` file. -``` -kraken: - ... - chaos_scenarios: - - arcaflow_scenarios: - - scenarios/arcaflow/cpu-hog/input.yaml -``` - -#### input.yaml -The implemented scenarios can be found in *scenarios/arcaflow/* folder. -The entrypoint of each scenario is the *input.yaml* file. -In this file there are all the options to set up the scenario accordingly to the desired target -### config.yaml -The arcaflow config file. Here you can set the arcaflow deployer and the arcaflow log level. -The supported deployers are: -- Docker -- Podman (podman daemon not needed, suggested option) -- Kubernetes - -The supported log levels are: -- debug -- info -- warning -- error -### workflow.yaml -This file contains the steps that will be executed to perform the scenario against the target. -Each step is represented by a container that will be executed from the deployer and its options. -Note that we provide the scenarios as a template, but they can be manipulated to define more complex workflows. -To have more details regarding the arcaflow workflows architecture and syntax it is suggested to refer to the [Arcaflow Documentation](https://arcalot.io/arcaflow/). - -This edit is no longer in quay image -Working on fix in ticket: https://issues.redhat.com/browse/CHAOS-494 -This will effect all versions 4.12 and higher of OpenShift \ No newline at end of file diff --git a/docs/arcaflow_scenarios/cpu_hog.md b/docs/arcaflow_scenarios/cpu_hog.md deleted file mode 100644 index 981a3ae4..00000000 --- a/docs/arcaflow_scenarios/cpu_hog.md +++ /dev/null @@ -1,19 +0,0 @@ -# CPU Hog -This scenario is based on the arcaflow [arcaflow-plugin-stressng](https://github.com/arcalot/arcaflow-plugin-stressng) plugin. -The purpose of this scenario is to create cpu pressure on a particular node of the Kubernetes/OpenShift cluster for a time span. -To enable this plugin add the pointer to the scenario input file `scenarios/arcaflow/cpu-hog/input.yaml` as described in the -Usage section. -This scenario takes a list of objects named `input_list` with the following properties: - -- **kubeconfig :** *string* the kubeconfig needed by the deployer to deploy the sysbench plugin in the target cluster -- **namespace :** *string* the namespace where the scenario container will be deployed -**Note:** this parameter will be automatically filled by kraken if the `kubeconfig_path` property is correctly set -- **node_selector :** *key-value map* the node label that will be used as `nodeSelector` by the pod to target a specific cluster node -- **duration :** *string* stop stress test after N seconds. One can also specify the units of time in seconds, minutes, hours, days or years with the suffix s, m, h, d or y. -- **cpu_count :** *int* the number of CPU cores to be used (0 means all) -- **cpu_method :** *string* a fine-grained control of which cpu stressors to use (ackermann, cfloat etc. see [manpage](https://manpages.org/sysbench) for all the cpu_method options) -- **cpu_load_percentage :** *int* the CPU load by percentage - -To perform several load tests in the same run simultaneously (eg. stress two or more nodes in the same run) add another item -to the `input_list` with the same properties (and eventually different values eg. different node_selectors -to schedule the pod on different nodes). To reduce (or increase) the parallelism change the value `parallelism` in `workload.yaml` file \ No newline at end of file diff --git a/docs/arcaflow_scenarios/io_hog.md b/docs/arcaflow_scenarios/io_hog.md deleted file mode 100644 index d6ebb698..00000000 --- a/docs/arcaflow_scenarios/io_hog.md +++ /dev/null @@ -1,21 +0,0 @@ -# I/O Hog -This scenario is based on the arcaflow [arcaflow-plugin-stressng](https://github.com/arcalot/arcaflow-plugin-stressng) plugin. -The purpose of this scenario is to create disk pressure on a particular node of the Kubernetes/OpenShift cluster for a time span. -The scenario allows to attach a node path to the pod as a `hostPath` volume. -To enable this plugin add the pointer to the scenario input file `scenarios/arcaflow/io-hog/input.yaml` as described in the -Usage section. -This scenario takes a list of objects named `input_list` with the following properties: - -- **kubeconfig :** *string* the kubeconfig needed by the deployer to deploy the sysbench plugin in the target cluster -- **namespace :** *string* the namespace where the scenario container will be deployed -**Note:** this parameter will be automatically filled by kraken if the `kubeconfig_path` property is correctly set -- **node_selector :** *key-value map* the node label that will be used as `nodeSelector` by the pod to target a specific cluster node -- **duration :** *string* stop stress test after N seconds. One can also specify the units of time in seconds, minutes, hours, days or years with the suffix s, m, h, d or y. -- **target_pod_folder :** *string* the path in the pod where the volume is mounted -- **target_pod_volume :** *object* the `hostPath` volume definition in the [Kubernetes/OpenShift](https://docs.openshift.com/container-platform/3.11/install_config/persistent_storage/using_hostpath.html) format, that will be attached to the pod as a volume -- **io_write_bytes :** *string* writes N bytes for each hdd process. The size can be expressed as % of free space on the file system or in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g -- **io_block_size :** *string* size of each write in bytes. Size can be from 1 byte to 4m. - -To perform several load tests in the same run simultaneously (eg. stress two or more nodes in the same run) add another item -to the `input_list` with the same properties (and eventually different values eg. different node_selectors -to schedule the pod on different nodes). To reduce (or increase) the parallelism change the value `parallelism` in `workload.yaml` file \ No newline at end of file diff --git a/docs/arcaflow_scenarios/memory_hog.md b/docs/arcaflow_scenarios/memory_hog.md deleted file mode 100644 index 2eee25f4..00000000 --- a/docs/arcaflow_scenarios/memory_hog.md +++ /dev/null @@ -1,18 +0,0 @@ -# Memory Hog -This scenario is based on the arcaflow [arcaflow-plugin-stressng](https://github.com/arcalot/arcaflow-plugin-stressng) plugin. -The purpose of this scenario is to create Virtual Memory pressure on a particular node of the Kubernetes/OpenShift cluster for a time span. -To enable this plugin add the pointer to the scenario input file `scenarios/arcaflow/memory-hog/input.yaml` as described in the -Usage section. -This scenario takes a list of objects named `input_list` with the following properties: - -- **kubeconfig :** *string* the kubeconfig needed by the deployer to deploy the sysbench plugin in the target cluster -- **namespace :** *string* the namespace where the scenario container will be deployed -**Note:** this parameter will be automatically filled by kraken if the `kubeconfig_path` property is correctly set -- **node_selector :** *key-value map* the node label that will be used as `nodeSelector` by the pod to target a specific cluster node -- **duration :** *string* stop stress test after N seconds. One can also specify the units of time in seconds, minutes, hours, days or years with the suffix s, m, h, d or y. -- **vm_bytes :** *string* N bytes per vm process or percentage of memory used (using the % symbol). The size can be expressed in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. -- **vm_workers :** *int* Number of VM stressors to be run (0 means 1 stressor per CPU) - -To perform several load tests in the same run simultaneously (eg. stress two or more nodes in the same run) add another item -to the `input_list` with the same properties (and eventually different values eg. different node_selectors -to schedule the pod on different nodes). To reduce (or increase) the parallelism change the value `parallelism` in `workload.yaml` file \ No newline at end of file diff --git a/docs/hog_scenarios.md b/docs/hog_scenarios.md new file mode 100644 index 00000000..fa10108a --- /dev/null +++ b/docs/hog_scenarios.md @@ -0,0 +1,49 @@ +### Hog Scenarios + +Hog Scenarios are designed to push the limits of memory, CPU, or I/O on one or more nodes in your cluster. +They also serve to evaluate whether your cluster can withstand rogue pods that excessively consume resources +without any limits. + +These scenarios involve deploying one or more workloads in the cluster. Based on the specific configuration, +these workloads will use a predetermined amount of resources for a specified duration. + +#### Common options + +| Option | Type | Description | +|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +|`duration`| number | the duration of the stress test in seconds | +|`workers`| number (Optional) | the number of threads instantiated by stress-ng, if left empty the number of workers will match the number of available cores in the node. | +|`hog-type`| string (Enum) | can be cpu, memory or io. | +|`image`| string | the container image of the stress workload | +|`namespace`| string | the namespace where the stress workload will be deployed | +|`node-selector`| string (Optional) | defines the node selector for choosing target nodes. If not specified, one schedulable node in the cluster will be chosen at random. If multiple nodes match the selector, all of them will be subjected to stress. If number-of-nodes is specified, that many nodes will be randomly selected from those identified by the selector. | +|`number-of-nodes`| number (Optional) | restricts the number of selected nodes by the selector| + + +#### `cpu-hog` options + +| Option | Type |Description| +|---|--------|---| +|`cpu-load-percentage`| number | the amount of cpu that will be consumed by the hog| +|`cpu-method`| string | reflects the cpu load strategy adopted by stress-ng, please refer to the stress-ng documentation for all the available options| + + + + +#### `io-hog` options + +| Option | Type | Description | +|-----------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `io-block-size` |string| the block size written by the stressor | +| `io-write-bytes` |string| the total amount of data that will be written by the stressor. The size can be specified as % of free space on the file system or in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g | +| `io-target-pod-folder` |string| the folder where the volume will be mounted in the pod | +| `io-target-pod-volume`| dictionary | the pod volume definition that will be stressed by the scenario. | + +> [!CAUTION] +> Modifying the structure of `io-target-pod-volume` might alter how the hog operates, potentially rendering it ineffective. + +#### `memory-hog` options + +| Option | Type |Description| +|-----------------------|--------|---| +|`memory-vm-bytes`| string | the amount of memory that the scenario will try to hog.The size can be specified as % of free space on the file system or in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g | \ No newline at end of file diff --git a/krkn/scenario_plugins/arcaflow/arcaflow_scenario_plugin.py b/krkn/scenario_plugins/arcaflow/arcaflow_scenario_plugin.py deleted file mode 100644 index a61cd167..00000000 --- a/krkn/scenario_plugins/arcaflow/arcaflow_scenario_plugin.py +++ /dev/null @@ -1,197 +0,0 @@ -import logging -import os -from pathlib import Path -import arcaflow -import yaml -from krkn_lib.models.telemetry import ScenarioTelemetry -from krkn_lib.telemetry.ocp import KrknTelemetryOpenshift -from krkn.scenario_plugins.abstract_scenario_plugin import AbstractScenarioPlugin -from krkn.scenario_plugins.arcaflow.context_auth import ContextAuth - - -class ArcaflowScenarioPlugin(AbstractScenarioPlugin): - - def run( - self, - run_uuid: str, - scenario: str, - krkn_config: dict[str, any], - lib_telemetry: KrknTelemetryOpenshift, - scenario_telemetry: ScenarioTelemetry, - ) -> int: - try: - engine_args = self.build_args(scenario) - status_code = self.run_workflow( - engine_args, lib_telemetry.get_lib_kubernetes().get_kubeconfig_path() - ) - return status_code - except Exception as e: - logging.error("ArcaflowScenarioPlugin exiting due to Exception %s" % e) - return 1 - - def get_scenario_types(self) -> [str]: - return ["hog_scenarios", "arcaflow_scenario"] - - def run_workflow( - self, engine_args: arcaflow.EngineArgs, kubeconfig_path: str - ) -> int: - self.set_arca_kubeconfig(engine_args, kubeconfig_path) - exit_status = arcaflow.run(engine_args) - return exit_status - - def build_args(self, input_file: str) -> arcaflow.EngineArgs: - """sets the kubeconfig parsed by setArcaKubeConfig as an input to the arcaflow workflow""" - current_path = Path().resolve() - context = f"{current_path}/{Path(input_file).parent}" - workflow = f"{context}/workflow.yaml" - config = f"{context}/config.yaml" - if not os.path.exists(context): - raise Exception( - "context folder for arcaflow workflow not found: {}".format(context) - ) - if not os.path.exists(input_file): - raise Exception( - "input file for arcaflow workflow not found: {}".format(input_file) - ) - if not os.path.exists(workflow): - raise Exception( - "workflow file for arcaflow workflow not found: {}".format(workflow) - ) - if not os.path.exists(config): - raise Exception( - "configuration file for arcaflow workflow not found: {}".format(config) - ) - - engine_args = arcaflow.EngineArgs() - engine_args.context = context - engine_args.config = config - engine_args.workflow = workflow - engine_args.input = f"{current_path}/{input_file}" - return engine_args - - def set_arca_kubeconfig( - self, engine_args: arcaflow.EngineArgs, kubeconfig_path: str - ): - - context_auth = ContextAuth() - if not os.path.exists(kubeconfig_path): - raise Exception("kubeconfig not found in {}".format(kubeconfig_path)) - - with open(kubeconfig_path, "r") as stream: - try: - kubeconfig = yaml.safe_load(stream) - context_auth.fetch_auth_data(kubeconfig) - except Exception as e: - logging.error( - "impossible to read kubeconfig file in: {}".format(kubeconfig_path) - ) - raise e - - kubeconfig_str = self.set_kubeconfig_auth(kubeconfig, context_auth) - - with open(engine_args.input, "r") as stream: - input_file = yaml.safe_load(stream) - if "input_list" in input_file and isinstance( - input_file["input_list"], list - ): - for index, _ in enumerate(input_file["input_list"]): - if isinstance(input_file["input_list"][index], dict): - input_file["input_list"][index]["kubeconfig"] = kubeconfig_str - else: - input_file["kubeconfig"] = kubeconfig_str - stream.close() - with open(engine_args.input, "w") as stream: - yaml.safe_dump(input_file, stream) - - with open(engine_args.config, "r") as stream: - config_file = yaml.safe_load(stream) - if config_file["deployers"]["image"]["deployer_name"] == "kubernetes": - kube_connection = self.set_kubernetes_deployer_auth( - config_file["deployers"]["image"]["connection"], context_auth - ) - config_file["deployers"]["image"]["connection"] = kube_connection - with open(engine_args.config, "w") as stream: - yaml.safe_dump(config_file, stream, explicit_start=True, width=4096) - - def set_kubernetes_deployer_auth( - self, deployer: any, context_auth: ContextAuth - ) -> any: - if context_auth.clusterHost is not None: - deployer["host"] = context_auth.clusterHost - if context_auth.clientCertificateData is not None: - deployer["cert"] = context_auth.clientCertificateData - if context_auth.clientKeyData is not None: - deployer["key"] = context_auth.clientKeyData - if context_auth.clusterCertificateData is not None: - deployer["cacert"] = context_auth.clusterCertificateData - if context_auth.username is not None: - deployer["username"] = context_auth.username - if context_auth.password is not None: - deployer["password"] = context_auth.password - if context_auth.bearerToken is not None: - deployer["bearerToken"] = context_auth.bearerToken - return deployer - - def set_kubeconfig_auth(self, kubeconfig: any, context_auth: ContextAuth) -> str: - """ - Builds an arcaflow-compatible kubeconfig representation and returns it as a string. - In order to run arcaflow plugins in kubernetes/openshift the kubeconfig must contain client certificate/key - and server certificate base64 encoded within the kubeconfig file itself in *-data fields. That is not always the - case, infact kubeconfig may contain filesystem paths to those files, this function builds an arcaflow-compatible - kubeconfig file and returns it as a string that can be safely included in input.yaml - """ - - if "current-context" not in kubeconfig.keys(): - raise Exception( - "invalid kubeconfig file, impossible to determine current-context" - ) - user_id = None - cluster_id = None - user_name = None - cluster_name = None - current_context = kubeconfig["current-context"] - for context in kubeconfig["contexts"]: - if context["name"] == current_context: - user_name = context["context"]["user"] - cluster_name = context["context"]["cluster"] - if user_name is None: - raise Exception( - "user not set for context {} in kubeconfig file".format(current_context) - ) - if cluster_name is None: - raise Exception( - "cluster not set for context {} in kubeconfig file".format( - current_context - ) - ) - - for index, user in enumerate(kubeconfig["users"]): - if user["name"] == user_name: - user_id = index - for index, cluster in enumerate(kubeconfig["clusters"]): - if cluster["name"] == cluster_name: - cluster_id = index - - if cluster_id is None: - raise Exception( - "no cluster {} found in kubeconfig users".format(cluster_name) - ) - if "client-certificate" in kubeconfig["users"][user_id]["user"]: - kubeconfig["users"][user_id]["user"][ - "client-certificate-data" - ] = context_auth.clientCertificateDataBase64 - del kubeconfig["users"][user_id]["user"]["client-certificate"] - - if "client-key" in kubeconfig["users"][user_id]["user"]: - kubeconfig["users"][user_id]["user"][ - "client-key-data" - ] = context_auth.clientKeyDataBase64 - del kubeconfig["users"][user_id]["user"]["client-key"] - - if "certificate-authority" in kubeconfig["clusters"][cluster_id]["cluster"]: - kubeconfig["clusters"][cluster_id]["cluster"][ - "certificate-authority-data" - ] = context_auth.clusterCertificateDataBase64 - del kubeconfig["clusters"][cluster_id]["cluster"]["certificate-authority"] - kubeconfig_str = yaml.dump(kubeconfig) - return kubeconfig_str diff --git a/krkn/scenario_plugins/arcaflow/context_auth.py b/krkn/scenario_plugins/arcaflow/context_auth.py deleted file mode 100644 index bb07e926..00000000 --- a/krkn/scenario_plugins/arcaflow/context_auth.py +++ /dev/null @@ -1,142 +0,0 @@ -import os -import base64 - - -class ContextAuth: - clusterCertificate: str = None - clusterCertificateData: str = None - clusterHost: str = None - clientCertificate: str = None - clientCertificateData: str = None - clientKey: str = None - clientKeyData: str = None - clusterName: str = None - username: str = None - password: str = None - bearerToken: str = None - # TODO: integrate in krkn-lib-kubernetes in the next iteration - - @property - def clusterCertificateDataBase64(self): - if self.clusterCertificateData is not None: - return base64.b64encode(bytes(self.clusterCertificateData, "utf8")).decode( - "ascii" - ) - return - - @property - def clientCertificateDataBase64(self): - if self.clientCertificateData is not None: - return base64.b64encode(bytes(self.clientCertificateData, "utf8")).decode( - "ascii" - ) - return - - @property - def clientKeyDataBase64(self): - if self.clientKeyData is not None: - return base64.b64encode(bytes(self.clientKeyData, "utf-8")).decode("ascii") - return - - def fetch_auth_data(self, kubeconfig: any): - context_username = None - current_context = kubeconfig["current-context"] - if current_context is None: - raise Exception("no current-context found in kubeconfig") - - for context in kubeconfig["contexts"]: - if context["name"] == current_context: - context_username = context["context"]["user"] - self.clusterName = context["context"]["cluster"] - if context_username is None: - raise Exception("user not found for context {0}".format(current_context)) - if self.clusterName is None: - raise Exception("cluster not found for context {0}".format(current_context)) - cluster_id = None - user_id = None - for index, user in enumerate(kubeconfig["users"]): - if user["name"] == context_username: - user_id = index - if user_id is None: - raise Exception( - "user {0} not found in kubeconfig users".format(context_username) - ) - - for index, cluster in enumerate(kubeconfig["clusters"]): - if cluster["name"] == self.clusterName: - cluster_id = index - - if cluster_id is None: - raise Exception( - "no cluster {} found in kubeconfig users".format(self.clusterName) - ) - - user = kubeconfig["users"][user_id]["user"] - cluster = kubeconfig["clusters"][cluster_id]["cluster"] - # sets cluster api URL - self.clusterHost = cluster["server"] - # client certificates - - if "client-key" in user: - try: - self.clientKey = user["client-key"] - self.clientKeyData = self.read_file(user["client-key"]) - except Exception as e: - raise e - - if "client-key-data" in user: - try: - self.clientKeyData = base64.b64decode(user["client-key-data"]).decode( - "utf-8" - ) - except Exception as e: - raise Exception("impossible to decode client-key-data") - - if "client-certificate" in user: - try: - self.clientCertificate = user["client-certificate"] - self.clientCertificateData = self.read_file(user["client-certificate"]) - except Exception as e: - raise e - - if "client-certificate-data" in user: - try: - self.clientCertificateData = base64.b64decode( - user["client-certificate-data"] - ).decode("utf-8") - except Exception as e: - raise Exception("impossible to decode client-certificate-data") - - # cluster certificate authority - - if "certificate-authority" in cluster: - try: - self.clusterCertificate = cluster["certificate-authority"] - self.clusterCertificateData = self.read_file( - cluster["certificate-authority"] - ) - except Exception as e: - raise e - - if "certificate-authority-data" in cluster: - try: - self.clusterCertificateData = base64.b64decode( - cluster["certificate-authority-data"] - ).decode("utf-8") - except Exception as e: - raise Exception("impossible to decode certificate-authority-data") - - if "username" in user: - self.username = user["username"] - - if "password" in user: - self.password = user["password"] - - if "token" in user: - self.bearerToken = user["token"] - - def read_file(self, filename: str) -> str: - if not os.path.exists(filename): - raise Exception("file not found {0} ".format(filename)) - with open(filename, "rb") as file_stream: - return file_stream.read().decode("utf-8") diff --git a/krkn/scenario_plugins/arcaflow/fixtures/ca.crt b/krkn/scenario_plugins/arcaflow/fixtures/ca.crt deleted file mode 100644 index e3264358..00000000 --- a/krkn/scenario_plugins/arcaflow/fixtures/ca.crt +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDBjCCAe6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwptaW5p -a3ViZUNBMB4XDTIzMDMxMzE1NDAxM1oXDTMzMDMxMTE1NDAxM1owFTETMBEGA1UE -AxMKbWluaWt1YmVDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMnz -U/gIbJBRGOgNYVKX2fV03ANOwnM4VjquR28QMAdxURqgOFZ6IxYNysHEyxxE9I+I -DAm9hi4vQPbOX7FlxUezuzw+ExEfa6RRJ+n+AGJOV1lezCVph6OaJxB1+L1UqaDZ -eM3B4cUf/iCc5Y4bs927+CBG3MJL/jmCVPCO+MiSn/l73PXSFNJAYMvRj42zkXqD -CVG9CwY2vWgZnnzl01l7jNGtie871AmV2uqKakJrQ2ILhD+8fZk4jE5JBDTCZnqQ -pXIc+vERNKLUS8cvjO6Ux8dMv/Z7+xonpXOU59LlpUdHWP9jgCvMTwiOriwqGjJ+ -pQJWpX9Dm+oxJiVOJzsCAwEAAaNhMF8wDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQW -MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBQU9pDMtbayJdNM6bp0IG8dcs15qTANBgkqhkiG9w0BAQsFAAOCAQEAtl9TVKPA -hTnPODqv0AGTqreS9kLg4WUUjZRaPUkPWmtCoTh2Yf55nRWdHOHeZnCWDSg24x42 -lpt+13IdqKew1RKTpKCTkicMFi090A01bYu/w39Cm6nOAA5h8zkgSkV5czvQotuV -SoN2vB+nbuY28ah5PkdqjMHEZbNwa59cgEke8wB1R1DWFQ/pqflrH2v9ACAuY+5Q -i673tA6CXrb1YfaCQnVBzcfvjGS1MqShPKpOLMF+/GccPczNimaBxMnKvYLvf3pN -qEUrJC00mAcein8HmxR2Xz8wredbMUUyrQxW29pZJwfGE5GU0olnlsA0lZLbTwio -xoolo5y+fsK/dA== ------END CERTIFICATE----- \ No newline at end of file diff --git a/krkn/scenario_plugins/arcaflow/fixtures/client.crt b/krkn/scenario_plugins/arcaflow/fixtures/client.crt deleted file mode 100644 index 64e4aef9..00000000 --- a/krkn/scenario_plugins/arcaflow/fixtures/client.crt +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDITCCAgmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwptaW5p -a3ViZUNBMB4XDTIzMDUwMTA4NTc0N1oXDTI2MDUwMTA4NTc0N1owMTEXMBUGA1UE -ChMOc3lzdGVtOm1hc3RlcnMxFjAUBgNVBAMTDW1pbmlrdWJlLXVzZXIwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0b7uy9nQYrh7uC5NODve7dFNLAgo5 -pWRS6Kx13ULA55gOpieZiI5/1jwUBjOz0Hhl5QAdHC1HDNu5wf4MmwIEheuq3kMA -mfuvNxW2BnWSDuXyUMlBfqlwg5o6W8ndEWaK33D7wd2WQsSsAnhQPJSjnzWKvWKq -+Kbcygc4hdss/ZWN+SXLTahNpHBw0sw8AcJqddNeXs2WI5GdZmbXL4QZI36EaNUm -m4xKmKRKYIP9wYkmXOV/D2h1meM44y4lul5v2qvo6I+umJ84q4W1/W1vVmAzyVfL -v1TQCUx8cpKMHzw3ma6CTBCtU3Oq9HKHBnf8GyHZicmV7ESzf/phJu4ZAgMBAAGj -YDBeMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH -AwIwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBQU9pDMtbayJdNM6bp0IG8dcs15 -qTANBgkqhkiG9w0BAQsFAAOCAQEABNzEQQMYUcLsBASHladEjr46avKn7gREfaDl -Y5PBvgCPP42q/sW/9iCNY3UpT9TJZWM6s01+0p6I96jYbRQER1NX7O4OgQYHmFw2 -PF6UOG2vMo54w11OvL7sbr4d+nkE6ItdM9fLDIJ3fEOYJZkSoxhOL/U3jSjIl7Wu -KCIlpM/M/gcZ4w2IvcLrWtvswbFNUd+dwQfBGcQTmSQDOLE7MqSvzYAkeNv73GLB -ieba7gs/PmoTFsf9nW60iXymDDF4MtODn15kqT/y1uD6coujmiEiIomBfxqAkUCU -0ciP/KF5oOEMmMedm7/peQxaRTMdRSk4yu7vbj/BxnTcj039Qg== ------END CERTIFICATE----- \ No newline at end of file diff --git a/krkn/scenario_plugins/arcaflow/fixtures/client.key b/krkn/scenario_plugins/arcaflow/fixtures/client.key deleted file mode 100644 index 03cfb879..00000000 --- a/krkn/scenario_plugins/arcaflow/fixtures/client.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAtG+7svZ0GK4e7guTTg73u3RTSwIKOaVkUuisdd1CwOeYDqYn -mYiOf9Y8FAYzs9B4ZeUAHRwtRwzbucH+DJsCBIXrqt5DAJn7rzcVtgZ1kg7l8lDJ -QX6pcIOaOlvJ3RFmit9w+8HdlkLErAJ4UDyUo581ir1iqvim3MoHOIXbLP2Vjfkl -y02oTaRwcNLMPAHCanXTXl7NliORnWZm1y+EGSN+hGjVJpuMSpikSmCD/cGJJlzl -fw9odZnjOOMuJbpeb9qr6OiPrpifOKuFtf1tb1ZgM8lXy79U0AlMfHKSjB88N5mu -gkwQrVNzqvRyhwZ3/Bsh2YnJlexEs3/6YSbuGQIDAQABAoIBAQCdJxPb8zt6o2zc -98f8nJy378D7+3LccmjGrVBH98ZELXIKkDy9RGqYfQcmiaBOZKv4U1OeBwSIdXKK -f6O9ZuSC/AEeeSbyRysmmFuYhlewNrmgKyyelqsNDBIv8fIHUTh2i9Xj8B4G2XBi -QGR5vcnYGLqRdBGTx63Nb0iKuksDCwPAuPA/e0ySz9HdWL1j4bqpVSYsOIXsqTDr -CVnxUeSIL0fFQnRm3IASXQD7zdq9eEFX7vESeleZoz8qNcKb4Na/C3N6crScjgH7 -qyNZ2zNLfy1LT84k8uc1TMX2KcEVEmfdDv5cCnUH2ic12CwXMZ0vgId5LJTaHx4x -ytIQIe5hAoGBANB+TsRXP4KzcjZlUUfiAp/pWUM4kVktbsfZa1R2NEuIGJUxPk3P -7WS0WX5W75QKRg+UWTubg5kfd0f9fklLgofmliBnY/HrpgdyugJmUZBgzIxmy0k+ -aCe0biD1gULfyyrKtfe8k5wRFstzhfGszlOf2ebR87sSVNBuF2lEwPTvAoGBAN2M -0/XrsodGU4B9Mj86Go2gb2k2WU2izI0cO+tm2S5U5DvKmVEnmjXfPRaOFj2UUQjo -cljnDAinbN+O0+Inc35qsEeYdAIepNAPglzcpfTHagja9mhx2idLYTXGhbZLL+Ei -TRzMyP27NF+GVVfYU/cA86ns6NboG6spohmnqh13AoGAKPc4aNGv0/GIVnHP56zb -0SnbdR7PSFNp+fCZay4Slmi2U9IqKMXbIjdhgjZ4uoDORU9jvReQYuzQ1h9TyfkB -O8yt4M4P0D/6DmqXa9NI4XJznn6wIMMXWf3UybsTW913IQBVgsjVxAuDjBQ11Eec -/sdg3D6SgkZWzeFjzjZJJ5cCgYBSYVg7fE3hERxhjawOaJuRCBQFSklAngVzfwkk -yhR9ruFC/l2uGIy19XFwnprUgP700gIa3qbR3PeV1TUiRcsjOaacqKqSUzSzjODL -iNxIvZHHAyxWv+b/b38REOWNWD3QeAG2cMtX1bFux7OaO31VPkxcZhRaPOp05cE5 -yudtlwKBgDBbR7RLYn03OPm3NDBLLjTybhD8Iu8Oj7UeNCiEWAdZpqIKYnwSxMzQ -kdo4aTENA/seEwq+XDV7TwbUIFFJg5gDXIhkcK2c9kiO2bObCAmKpBlQCcrp0a5X -NSBk1N/ZG/Qhqns7z8k01KN4LNcdpRoNiYYPgY+p3xbY8+nWhv+q ------END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/krkn/scenario_plugins/arcaflow/test_context_auth.py b/krkn/scenario_plugins/arcaflow/test_context_auth.py deleted file mode 100644 index 75e48113..00000000 --- a/krkn/scenario_plugins/arcaflow/test_context_auth.py +++ /dev/null @@ -1,98 +0,0 @@ -import os -import unittest - -import yaml - -from .context_auth import ContextAuth - - -class TestCurrentContext(unittest.TestCase): - - def get_kubeconfig_with_data(self) -> str: - """ - This function returns a test kubeconfig file as a string. - - :return: a test kubeconfig file in string format (for unit testing purposes) - """ # NOQA - return """apiVersion: v1 -clusters: -- cluster: - certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM5ekNDQWQrZ0F3SUJBZ0lVV01PTVBNMVUrRi9uNXN6TSthYzlMcGZISHB3d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0hqRWNNQm9HQTFVRUF3d1RhM1ZpZFc1MGRTNXNiMk5oYkdSdmJXRnBiakFlRncweU1URXlNRFl4T0RBdwpNRFJhRncwek1URXlNRFF4T0RBd01EUmFNQjR4SERBYUJnTlZCQU1NRTJ0MVluVnVkSFV1Ykc5allXeGtiMjFoCmFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDNExhcG00SDB0T1NuYTNXVisKdzI4a0tOWWRwaHhYOUtvNjUwVGlOK2c5ZFNQU3VZK0V6T1JVOWVONlgyWUZkMEJmVFNodno4Y25rclAvNysxegpETEoxQ3MwRi9haEV3ZDQxQXN5UGFjbnRiVE80dGRLWm9POUdyODR3YVdBN1hSZmtEc2ZxRGN1YW5UTmVmT1hpCkdGbmdDVzU5Q285M056alB1eEFrakJxdVF6eE5GQkgwRlJPbXJtVFJ4cnVLZXo0aFFuUW1OWEFUNnp0M21udzMKWUtWTzU4b2xlcUxUcjVHNlRtVFQyYTZpVGdtdWY2N0cvaVZlalJGbkw3YkNHWmgzSjlCSTNMcVpqRzE4dWxvbgpaVDdQcGQrQTlnaTJOTm9UZlI2TVB5SndxU1BCL0xZQU5ZNGRoZDVJYlVydDZzbmViTlRZSHV2T0tZTDdNTWRMCmVMSzFBZ01CQUFHakxUQXJNQWtHQTFVZEV3UUNNQUF3SGdZRFZSMFJCQmN3RllJVGEzVmlkVzUwZFM1c2IyTmgKYkdSdmJXRnBiakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBQTVqUHVpZVlnMExySE1PSkxYY0N4d3EvVzBDNApZeFpncVd3VHF5VHNCZjVKdDlhYTk0SkZTc2dHQWdzUTN3NnA2SlBtL0MyR05MY3U4ZWxjV0E4UXViQWxueXRRCnF1cEh5WnYrZ08wMG83TXdrejZrTUxqQVZ0QllkRzJnZ21FRjViTEk5czBKSEhjUGpHUkl1VHV0Z0tHV1dPWHgKSEg4T0RzaG9wZHRXMktrR2c2aThKaEpYaWVIbzkzTHptM00xRUNGcXAvMEdtNkN1RFphVVA2SGpJMWRrYllLdgpsSHNVZ1U1SmZjSWhNYmJLdUllTzRkc1YvT3FHcm9iNW5vcmRjaExBQmRDTnc1cmU5T1NXZGZ1VVhSK0ViZVhrCjVFM0tFYzA1RGNjcGV2a1NTdlJ4SVQrQzNMOTltWGcxL3B5NEw3VUhvNFFLTXlqWXJXTWlLRlVKV1E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== - server: https://127.0.0.1:6443 - name: default -contexts: -- context: - cluster: default - namespace: default - user: testuser - name: default -current-context: default -kind: Config -preferences: {} -users: -- name: testuser - user: - client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM5ekNDQWQrZ0F3SUJBZ0lVV01PTVBNMVUrRi9uNXN6TSthYzlMcGZISHB3d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0hqRWNNQm9HQTFVRUF3d1RhM1ZpZFc1MGRTNXNiMk5oYkdSdmJXRnBiakFlRncweU1URXlNRFl4T0RBdwpNRFJhRncwek1URXlNRFF4T0RBd01EUmFNQjR4SERBYUJnTlZCQU1NRTJ0MVluVnVkSFV1Ykc5allXeGtiMjFoCmFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDNExhcG00SDB0T1NuYTNXVisKdzI4a0tOWWRwaHhYOUtvNjUwVGlOK2c5ZFNQU3VZK0V6T1JVOWVONlgyWUZkMEJmVFNodno4Y25rclAvNysxegpETEoxQ3MwRi9haEV3ZDQxQXN5UGFjbnRiVE80dGRLWm9POUdyODR3YVdBN1hSZmtEc2ZxRGN1YW5UTmVmT1hpCkdGbmdDVzU5Q285M056alB1eEFrakJxdVF6eE5GQkgwRlJPbXJtVFJ4cnVLZXo0aFFuUW1OWEFUNnp0M21udzMKWUtWTzU4b2xlcUxUcjVHNlRtVFQyYTZpVGdtdWY2N0cvaVZlalJGbkw3YkNHWmgzSjlCSTNMcVpqRzE4dWxvbgpaVDdQcGQrQTlnaTJOTm9UZlI2TVB5SndxU1BCL0xZQU5ZNGRoZDVJYlVydDZzbmViTlRZSHV2T0tZTDdNTWRMCmVMSzFBZ01CQUFHakxUQXJNQWtHQTFVZEV3UUNNQUF3SGdZRFZSMFJCQmN3RllJVGEzVmlkVzUwZFM1c2IyTmgKYkdSdmJXRnBiakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBQTVqUHVpZVlnMExySE1PSkxYY0N4d3EvVzBDNApZeFpncVd3VHF5VHNCZjVKdDlhYTk0SkZTc2dHQWdzUTN3NnA2SlBtL0MyR05MY3U4ZWxjV0E4UXViQWxueXRRCnF1cEh5WnYrZ08wMG83TXdrejZrTUxqQVZ0QllkRzJnZ21FRjViTEk5czBKSEhjUGpHUkl1VHV0Z0tHV1dPWHgKSEg4T0RzaG9wZHRXMktrR2c2aThKaEpYaWVIbzkzTHptM00xRUNGcXAvMEdtNkN1RFphVVA2SGpJMWRrYllLdgpsSHNVZ1U1SmZjSWhNYmJLdUllTzRkc1YvT3FHcm9iNW5vcmRjaExBQmRDTnc1cmU5T1NXZGZ1VVhSK0ViZVhrCjVFM0tFYzA1RGNjcGV2a1NTdlJ4SVQrQzNMOTltWGcxL3B5NEw3VUhvNFFLTXlqWXJXTWlLRlVKV1E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== - client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkFRQzRMYXBtNEgwdE9TbmEKM1dWK3cyOGtLTllkcGh4WDlLbzY1MFRpTitnOWRTUFN1WStFek9SVTllTjZYMllGZDBCZlRTaHZ6OGNua3JQLwo3KzF6RExKMUNzMEYvYWhFd2Q0MUFzeVBhY250YlRPNHRkS1pvTzlHcjg0d2FXQTdYUmZrRHNmcURjdWFuVE5lCmZPWGlHRm5nQ1c1OUNvOTNOempQdXhBa2pCcXVRenhORkJIMEZST21ybVRSeHJ1S2V6NGhRblFtTlhBVDZ6dDMKbW53M1lLVk81OG9sZXFMVHI1RzZUbVRUMmE2aVRnbXVmNjdHL2lWZWpSRm5MN2JDR1poM0o5QkkzTHFaakcxOAp1bG9uWlQ3UHBkK0E5Z2kyTk5vVGZSNk1QeUp3cVNQQi9MWUFOWTRkaGQ1SWJVcnQ2c25lYk5UWUh1dk9LWUw3Ck1NZExlTEsxQWdNQkFBRUNnZ0VBQ28rank4NW5ueVk5L2l6ZjJ3cjkzb2J3OERaTVBjYnIxQURhOUZYY1hWblEKT2c4bDZhbU9Ga2tiU0RNY09JZ0VDdkx6dEtXbmQ5OXpydU5sTEVtNEdmb0trNk5kK01OZEtKRUdoZHE5RjM1Qgpqdi91R1owZTIyRE5ZLzFHNVdDTE5DcWMwQkVHY2RFOTF0YzJuMlppRVBTNWZ6WVJ6L1k4cmJ5K1NqbzJkWE9RCmRHYWRlUFplbi9UbmlHTFlqZWhrbXZNQjJvU0FDbVMycTd2OUNrcmdmR1RZbWJzeGVjSU1QK0JONG9KS3BOZ28KOUpnRWJ5SUxkR1pZS2pQb2lLaHNjMVhmSy8zZStXSmxuYjJBaEE5Y1JMUzhMcDdtcEYySWp4SjNSNE93QTg3WQpNeGZvZWFGdnNuVUFHWUdFWFo4Z3BkWmhQMEoxNWRGdERjajIrcngrQVFLQmdRRDFoSE9nVGdFbERrVEc5bm5TCjE1eXYxRzUxYnJMQU1UaWpzNklEMU1qelhzck0xY2ZvazVaaUlxNVJsQ3dReTlYNDdtV1RhY0lZRGR4TGJEcXEKY0IydjR5Wm1YK1VleGJ3cDU1OWY0V05HdzF5YzQrQjdaNFF5aTRFelN4WmFjbldjMnBzcHJMUFVoOUFXRXVNcApOaW1vcXNiVGNnNGs5QWRxeUIrbWhIWmJRUUtCZ1FEQUNzU09qNXZMU1VtaVpxYWcrOVMySUxZOVNOdDZzS1VyCkprcjdCZEVpN3N2YmU5cldRR2RBb0xkQXNzcU94aENydmtPNkpSSHB1YjlRRjlYdlF4Riszc2ZpZm4yYkQ0ZloKMlVsclA1emF3RlNrNDNLbjdMZzRscURpaVUxVGlqTkJBL3dUcFlmbTB4dW5WeFRWNDZpNVViQW1XRk12TWV0bQozWUZYQmJkK2RRS0JnRGl6Q1B6cFpzeEcrazAwbUxlL2dYajl4ekNwaXZCbHJaM29teTdsVWk4YUloMmg5VlBaCjJhMzZNbVcyb1dLVG9HdW5xcCtibWU1eUxRRGlFcjVQdkJ0bGl2V3ppYmRNbFFMY2Nlcnpveml4WDA4QU5WUnEKZUpZdnIzdklDSGFFM25LRjdiVjNJK1NlSk1ra1BYL0QrV1R4WTQ5clZLYm1FRnh4c1JXRW04ekJBb0dBWEZ3UgpZanJoQTZqUW1DRmtYQ0loa0NJMVkwNEorSHpDUXZsY3NGT0EzSnNhUWduVUdwekl5OFUvdlFiLzhpQ0IzZ2RZCmpVck16YXErdnVkbnhYVnRFYVpWWGJIVitPQkVSdHFBdStyUkprZS9yYm1SNS84cUxsVUxOVWd4ZjA4RkRXeTgKTERxOUhKOUZPbnJnRTJvMU9FTjRRMGpSWU81U041dXFXODd0REEwQ2dZQXpXbk1KSFgrbmlyMjhRRXFyVnJKRAo4ZUEwOHIwWTJRMDhMRlcvMjNIVWQ4WU12VnhTUTdwcUwzaE41RXVJQ2dCbEpGVFI3TndBREo3eDY2M002akFMCm1DNlI4dWxSZStwa08xN2Y0UUs3MnVRanJGZEhESnlXQmdDL0RKSkV6d1dwY0Q4VVNPK3A5bVVIbllLTUJTOEsKTVB1ejYrZ3h0VEtsRU5pZUVacXhxZz09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K - username: testuser - password: testpassword - token: sha256~fFyEqjf1xxFMO0tbEyGRvWeNOd7QByuEgS4hyEq_A9o - """ # NOQA - - def get_kubeconfig_with_paths(self) -> str: - """ - This function returns a test kubeconfig file as a string. - - :return: a test kubeconfig file in string format (for unit testing purposes) - """ # NOQA - return """apiVersion: v1 -clusters: -- cluster: - certificate-authority: fixtures/ca.crt - server: https://127.0.0.1:6443 - name: default -contexts: -- context: - cluster: default - namespace: default - user: testuser - name: default -current-context: default -kind: Config -preferences: {} -users: -- name: testuser - user: - client-certificate: fixtures/client.crt - client-key: fixtures/client.key - username: testuser - password: testpassword - token: sha256~fFyEqjf1xxFMO0tbEyGRvWeNOd7QByuEgS4hyEq_A9o - """ # NOQA - - def test_current_context(self): - cwd = os.getcwd() - current_context_data = ContextAuth() - data = yaml.safe_load(self.get_kubeconfig_with_data()) - current_context_data.fetch_auth_data(data) - self.assertIsNotNone(current_context_data.clusterCertificateData) - self.assertIsNotNone(current_context_data.clientCertificateData) - self.assertIsNotNone(current_context_data.clientKeyData) - self.assertIsNotNone(current_context_data.username) - self.assertIsNotNone(current_context_data.password) - self.assertIsNotNone(current_context_data.bearerToken) - self.assertIsNotNone(current_context_data.clusterHost) - - current_context_no_data = ContextAuth() - data = yaml.safe_load(self.get_kubeconfig_with_paths()) - current_context_no_data.fetch_auth_data(data) - self.assertIsNotNone(current_context_no_data.clusterCertificate) - self.assertIsNotNone(current_context_no_data.clusterCertificateData) - self.assertIsNotNone(current_context_no_data.clientCertificate) - self.assertIsNotNone(current_context_no_data.clientCertificateData) - self.assertIsNotNone(current_context_no_data.clientKey) - self.assertIsNotNone(current_context_no_data.clientKeyData) - self.assertIsNotNone(current_context_no_data.username) - self.assertIsNotNone(current_context_no_data.password) - self.assertIsNotNone(current_context_no_data.bearerToken) - self.assertIsNotNone(current_context_data.clusterHost) diff --git a/krkn/scenario_plugins/arcaflow/__init__.py b/krkn/scenario_plugins/hogs/__init__.py similarity index 100% rename from krkn/scenario_plugins/arcaflow/__init__.py rename to krkn/scenario_plugins/hogs/__init__.py diff --git a/krkn/scenario_plugins/hogs/hogs_scenario_plugin.py b/krkn/scenario_plugins/hogs/hogs_scenario_plugin.py new file mode 100644 index 00000000..2ef0180c --- /dev/null +++ b/krkn/scenario_plugins/hogs/hogs_scenario_plugin.py @@ -0,0 +1,142 @@ +import copy +import logging +import queue +import random +import re +import threading +import time + + +import yaml +from krkn_lib.models.telemetry import ScenarioTelemetry +from krkn_lib.telemetry.ocp import KrknTelemetryOpenshift +from krkn_lib.models.krkn import HogConfig, HogType +from krkn_lib.models.k8s import NodeResources +from krkn_lib.k8s import KrknKubernetes +from krkn_lib.utils import get_random_string + +from krkn.scenario_plugins.abstract_scenario_plugin import AbstractScenarioPlugin + + +class HogsScenarioPlugin(AbstractScenarioPlugin): + def run(self, run_uuid: str, scenario: str, krkn_config: dict[str, any], lib_telemetry: KrknTelemetryOpenshift, + scenario_telemetry: ScenarioTelemetry) -> int: + try: + with open(scenario, "r") as f: + scenario = yaml.full_load(f) + scenario_config = HogConfig.from_yaml_dict(scenario) + has_selector = True + if not scenario_config.node_selector or not re.match("^.+=.*$", scenario_config.node_selector): + if scenario_config.node_selector: + logging.warning(f"node selector {scenario_config.node_selector} not in right format (key=value)") + node_selector = "" + else: + node_selector = scenario_config.node_selector + + available_nodes = lib_telemetry.get_lib_kubernetes().list_schedulable_nodes(node_selector) + if len(available_nodes) == 0: + raise Exception("no available nodes to schedule workload") + + if not has_selector: + # if selector not specified picks a random node between the available + available_nodes = [available_nodes[random.randint(0, len(available_nodes))]] + + if scenario_config.number_of_nodes and len(available_nodes) > scenario_config.number_of_nodes: + available_nodes = random.sample(available_nodes, scenario_config.number_of_nodes) + + exception_queue = queue.Queue() + self.run_scenario(scenario_config, lib_telemetry.get_lib_kubernetes(), available_nodes, exception_queue) + return 0 + except Exception as e: + logging.error(f"scenario exception: {e}") + return 1 + + def get_scenario_types(self) -> list[str]: + return ["hog_scenarios"] + + def run_scenario_worker(self, config: HogConfig, + lib_k8s: KrknKubernetes, node: str, + exception_queue: queue.Queue): + try: + if not config.workers: + config.workers = lib_k8s.get_node_cpu_count(node) + logging.info(f"[{node}] detected {config.workers} cpus for node {node}") + + logging.info(f"[{node}] workers number: {config.workers}") + + # using kubernetes.io/hostname = selector to + # precisely deploy each workload on each selected node + config.node_selector = f"kubernetes.io/hostname={node}" + pod_name = f"{config.type.value}-hog-{get_random_string(5)}" + node_resources_start = lib_k8s.get_node_resources_info(node) + lib_k8s.deploy_hog(pod_name, config) + start = time.time() + # waiting 3 seconds before starting sample collection + time.sleep(3) + node_resources_end = lib_k8s.get_node_resources_info(node) + + samples: list[NodeResources] = [] + avg_node_resources = NodeResources() + + while time.time() - start < config.duration-1: + samples.append(lib_k8s.get_node_resources_info(node)) + + max_wait = 30 + wait = 0 + logging.info(f"[{node}] waiting {max_wait} up to seconds pod: {pod_name} namespace: {config.namespace} to finish") + while lib_k8s.is_pod_running(pod_name, config.namespace): + if wait >= max_wait: + raise Exception(f"[{node}] hog workload pod: {pod_name} namespace: {config.namespace} " + f"didn't finish after {max_wait}") + time.sleep(1) + wait += 1 + continue + + logging.info(f"[{node}] deleting pod: {pod_name} namespace: {config.namespace}") + lib_k8s.delete_pod(pod_name, config.namespace) + + for resource in samples: + avg_node_resources.cpu += resource.cpu + avg_node_resources.memory += resource.memory + avg_node_resources.disk_space += resource.disk_space + + avg_node_resources.cpu = avg_node_resources.cpu/len(samples) + avg_node_resources.memory = avg_node_resources.memory / len(samples) + avg_node_resources.disk_space = avg_node_resources.disk_space / len(samples) + + if config.type == HogType.cpu: + logging.info(f"[{node}] detected cpu consumption: " + f"{(avg_node_resources.cpu / (config.workers * 1000000000)) * 100} %") + if config.type == HogType.memory: + logging.info(f"[{node}] detected memory increase: " + f"{avg_node_resources.memory / node_resources_start.memory * 100} %") + if config.type == HogType.io: + logging.info(f"[{node}] detected disk space allocated: " + f"{(avg_node_resources.disk_space - node_resources_end.disk_space) / 1024 / 1024} MB") + except Exception as e: + exception_queue.put(e) + + def run_scenario(self, config: HogConfig, + lib_k8s: KrknKubernetes, + available_nodes: list[str], + exception_queue: queue.Queue): + workers = [] + logging.info(f"running {config.type.value} hog scenario") + logging.info(f"targeting nodes: [{','.join(available_nodes)}]") + for node in available_nodes: + config_copy = copy.deepcopy(config) + worker = threading.Thread(target=self.run_scenario_worker, + args=(config_copy, lib_k8s, node, exception_queue)) + worker.daemon = True + worker.start() + workers.append(worker) + + for worker in workers: + worker.join() + + try: + while True: + exception = exception_queue.get_nowait() + raise exception + except queue.Empty: + pass diff --git a/requirements.txt b/requirements.txt index 54688893..828024f6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,6 @@ aliyun-python-sdk-core==2.13.36 aliyun-python-sdk-ecs==4.24.25 arcaflow-plugin-sdk==0.14.0 -arcaflow==0.19.1 boto3==1.28.61 azure-identity==1.16.1 azure-keyvault==4.2.0 @@ -16,7 +15,7 @@ google-cloud-compute==1.22.0 ibm_cloud_sdk_core==3.18.0 ibm_vpc==0.20.0 jinja2==3.1.5 -krkn-lib==4.0.4 +krkn-lib@git+https://github.com/krkn-chaos/krkn-lib.git@arca_to_native lxml==5.1.0 kubernetes==28.1.0 numpy==1.26.4 diff --git a/run_kraken.py b/run_kraken.py index 03677cde..3e143796 100644 --- a/run_kraken.py +++ b/run_kraken.py @@ -31,6 +31,10 @@ from krkn.scenario_plugins.scenario_plugin_factory import ( ScenarioPluginNotFound, ) +# removes TripleDES warning +import warnings +warnings.filterwarnings(action='ignore', module='.*paramiko.*') + report_file = "" diff --git a/scenarios/kube/cpu-hog.yml b/scenarios/kube/cpu-hog.yml new file mode 100644 index 00000000..0601efa7 --- /dev/null +++ b/scenarios/kube/cpu-hog.yml @@ -0,0 +1,9 @@ +duration: 60 +workers: '' # leave it empty '' node cpu auto-detection +hog-type: cpu +image: quay.io/krkn-chaos/krkn-hog +namespace: default +cpu-load-percentage: 90 +cpu-method: all +node-selector: "node-role.kubernetes.io/worker=" +number-of-nodes: 2 diff --git a/scenarios/kube/cpu-hog/config.yaml b/scenarios/kube/cpu-hog/config.yaml deleted file mode 100644 index 263cf503..00000000 --- a/scenarios/kube/cpu-hog/config.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -deployers: - image: - connection: {} - deployer_name: kubernetes -log: - level: error -logged_outputs: - error: - level: error - success: - level: debug diff --git a/scenarios/kube/cpu-hog/input.yaml b/scenarios/kube/cpu-hog/input.yaml deleted file mode 100644 index 28152c42..00000000 --- a/scenarios/kube/cpu-hog/input.yaml +++ /dev/null @@ -1,13 +0,0 @@ -input_list: - - cpu_count: 1 - cpu_load_percentage: 80 - cpu_method: all - duration: 30 - kubeconfig: '' - namespace: default - # set the node selector as a key-value pair eg. - # node_selector: - # kubernetes.io/hostname: kind-worker2 - node_selector: {} - - diff --git a/scenarios/kube/cpu-hog/sub-workflow.yaml b/scenarios/kube/cpu-hog/sub-workflow.yaml deleted file mode 100644 index 73c9fd1d..00000000 --- a/scenarios/kube/cpu-hog/sub-workflow.yaml +++ /dev/null @@ -1,98 +0,0 @@ -version: v0.2.0 -input: - root: SubRootObject - objects: - SubRootObject: - id: SubRootObject - properties: - kubeconfig: - display: - description: The complete kubeconfig file as a string - name: Kubeconfig file contents - type: - type_id: string - required: true - namespace: - display: - description: The namespace where the container will be deployed - name: Namespace - type: - type_id: string - required: true - node_selector: - display: - description: kubernetes node name where the plugin must be deployed - type: - type_id: map - values: - type_id: string - keys: - type_id: string - required: true - duration: - display: - name: duration the scenario expressed in seconds - description: stop stress test after T seconds. One can also specify the units of time in - seconds, minutes, hours, days or years with the suffix s, m, h, d or y - type: - type_id: integer - required: true - cpu_count: - display: - description: Number of CPU cores to be used (0 means all) - name: number of CPUs - type: - type_id: integer - required: true - cpu_method: - display: - description: CPU stress method - name: fine grained control of which cpu stressors to use (ackermann, cfloat etc.) - type: - type_id: string - required: true - cpu_load_percentage: - display: - description: load CPU by percentage - name: CPU load - type: - type_id: integer - required: true - -steps: - kubeconfig: - plugin: - src: quay.io/arcalot/arcaflow-plugin-kubeconfig:0.2.0 - deployment_type: image - input: - kubeconfig: !expr $.input.kubeconfig - stressng: - plugin: - src: quay.io/arcalot/arcaflow-plugin-stressng:0.6.0 - deployment_type: image - step: workload - input: - cleanup: "true" - - timeout: !expr $.input.duration - stressors: - - stressor: cpu - workers: !expr $.input.cpu_count - cpu-method: "all" - cpu-load: !expr $.input.cpu_load_percentage - deploy: - deployer_name: kubernetes - connection: !expr $.steps.kubeconfig.outputs.success.connection - pod: - metadata: - namespace: !expr $.input.namespace - labels: - arcaflow: stressng - spec: - nodeSelector: !expr $.input.node_selector - pluginContainer: - imagePullPolicy: Always -outputs: - success: - stressng: !expr $.steps.stressng.outputs.success - diff --git a/scenarios/kube/cpu-hog/workflow.yaml b/scenarios/kube/cpu-hog/workflow.yaml deleted file mode 100644 index ca33a0fc..00000000 --- a/scenarios/kube/cpu-hog/workflow.yaml +++ /dev/null @@ -1,25 +0,0 @@ -version: v0.2.0 -input: - root: RootObject - objects: - RootObject: - id: RootObject - properties: - input_list: - type: - type_id: list - items: - id: SubRootObject - type_id: ref - namespace: $.steps.workload_loop.execute.inputs.items - -steps: - workload_loop: - kind: foreach - items: !expr $.input.input_list - workflow: sub-workflow.yaml - parallelism: 1000 -outputs: - success: - workloads: !expr $.steps.workload_loop.outputs.success.data - diff --git a/scenarios/kube/io-hog.yml b/scenarios/kube/io-hog.yml new file mode 100644 index 00000000..bca41c2a --- /dev/null +++ b/scenarios/kube/io-hog.yml @@ -0,0 +1,14 @@ +duration: 30 +workers: '' # leave it empty '' node cpu auto-detection +hog-type: io +image: quay.io/krkn-chaos/krkn-hog +namespace: default +io-block-size: 1m +io-write-bytes: 1g +io-target-pod-folder: /hog-data +io-target-pod-volume: + name: node-volume + hostPath: + path: /root # a path writable by kubelet in the root filesystem of the node +node-selector: "node-role.kubernetes.io/worker=" +number-of-nodes: '' \ No newline at end of file diff --git a/scenarios/kube/io-hog/config.yaml b/scenarios/kube/io-hog/config.yaml deleted file mode 100644 index 431661a0..00000000 --- a/scenarios/kube/io-hog/config.yaml +++ /dev/null @@ -1,11 +0,0 @@ -deployers: - image: - connection: {} - deployer_name: kubernetes -log: - level: error -logged_outputs: - error: - level: error - success: - level: debug diff --git a/scenarios/kube/io-hog/input.yaml b/scenarios/kube/io-hog/input.yaml deleted file mode 100644 index bbb776cd..00000000 --- a/scenarios/kube/io-hog/input.yaml +++ /dev/null @@ -1,16 +0,0 @@ -input_list: -- duration: 30 - io_block_size: 1m - io_workers: 1 - io_write_bytes: 10m - kubeconfig: '' - namespace: default - # set the node selector as a key-value pair eg. - # node_selector: - # kubernetes.io/hostname: kind-worker2 - node_selector: {} - target_pod_folder: /hog-data - target_pod_volume: - hostPath: - path: /tmp - name: node-volume diff --git a/scenarios/kube/io-hog/sub-workflow.yaml b/scenarios/kube/io-hog/sub-workflow.yaml deleted file mode 100644 index c0f5dd0d..00000000 --- a/scenarios/kube/io-hog/sub-workflow.yaml +++ /dev/null @@ -1,141 +0,0 @@ -version: v0.2.0 -input: - root: SubRootObject - objects: - hostPath: - id: HostPathVolumeSource - properties: - path: - type: - type_id: string - Volume: - id: Volume - properties: - name: - type: - type_id: string - hostPath: - type: - id: hostPath - type_id: ref - SubRootObject: - id: SubRootObject - properties: - kubeconfig: - display: - description: The complete kubeconfig file as a string - name: Kubeconfig file contents - type: - type_id: string - required: true - namespace: - display: - description: The namespace where the container will be deployed - name: Namespace - type: - type_id: string - required: true - node_selector: - display: - description: kubernetes node name where the plugin must be deployed - type: - type_id: map - values: - type_id: string - keys: - type_id: string - required: true - duration: - display: - name: duration the scenario expressed in seconds - description: stop stress test after T seconds. One can also specify the units of time in - seconds, minutes, hours, days or years with the suffix s, m, h, d or y - type: - type_id: integer - required: true - io_workers: - display: - description: number of workers - name: start N workers continually writing, reading and removing temporary files - type: - type_id: integer - required: true - io_block_size: - display: - description: single write size - name: specify size of each write in bytes. Size can be from 1 byte to 4MB. - type: - type_id: string - required: true - io_write_bytes: - display: - description: Total number of bytes written - name: write N bytes for each hdd process, the default is 1 GB. One can specify the size - as % of free space on the file system or in units of Bytes, KBytes, MBytes and - GBytes using the suffix b, k, m or g - type: - type_id: string - required: true - target_pod_folder: - display: - description: Target Folder - name: Folder in the pod where the test will be executed and the test files will be written - type: - type_id: string - required: true - target_pod_volume: - display: - name: kubernetes volume definition - description: the volume that will be attached to the pod. In order to stress - the node storage only hosPath mode is currently supported - type: - type_id: ref - id: Volume - required: true - -steps: - kubeconfig: - plugin: - src: quay.io/arcalot/arcaflow-plugin-kubeconfig:0.2.0 - deployment_type: image - input: - kubeconfig: !expr $.input.kubeconfig - stressng: - plugin: - src: quay.io/arcalot/arcaflow-plugin-stressng:0.6.0 - deployment_type: image - step: workload - input: - cleanup: "true" - timeout: !expr $.input.duration - workdir: !expr $.input.target_pod_folder - stressors: - - stressor: hdd - workers: !expr $.input.io_workers - hdd-bytes: !expr $.input.io_write_bytes - hdd-write-size: !expr $.input.io_block_size - - deploy: - deployer_name: kubernetes - connection: !expr $.steps.kubeconfig.outputs.success.connection - pod: - metadata: - namespace: !expr $.input.namespace - labels: - arcaflow: stressng - spec: - nodeSelector: !expr $.input.node_selector - pluginContainer: - imagePullPolicy: Always - securityContext: - privileged: true - volumeMounts: - - mountPath: /hog-data - name: node-volume - volumes: - - !expr $.input.target_pod_volume - -outputs: - success: - stressng: !expr $.steps.stressng.outputs.success - diff --git a/scenarios/kube/io-hog/workflow.yaml b/scenarios/kube/io-hog/workflow.yaml deleted file mode 100644 index 13df6485..00000000 --- a/scenarios/kube/io-hog/workflow.yaml +++ /dev/null @@ -1,26 +0,0 @@ -version: v0.2.0 -input: - root: RootObject - objects: - RootObject: - id: RootObject - properties: - input_list: - type: - type_id: list - items: - id: SubRootObject - type_id: ref - namespace: $.steps.workload_loop.execute.inputs.items -steps: - workload_loop: - kind: foreach - items: !expr $.input.input_list - workflow: sub-workflow.yaml - parallelism: 1000 -outputs: - success: - workloads: !expr $.steps.workload_loop.outputs.success.data - - - diff --git a/scenarios/kube/memory-hog.yml b/scenarios/kube/memory-hog.yml new file mode 100644 index 00000000..c426fcb8 --- /dev/null +++ b/scenarios/kube/memory-hog.yml @@ -0,0 +1,8 @@ +duration: 60 +workers: '' # leave it empty '' node cpu auto-detection +hog-type: memory +image: quay.io/krkn-chaos/krkn-hog +namespace: default +memory-vm-bytes: 90% +node-selector: "node-role.kubernetes.io/worker=" +number-of-nodes: '' diff --git a/scenarios/kube/memory-hog/config.yaml b/scenarios/kube/memory-hog/config.yaml deleted file mode 100644 index 263cf503..00000000 --- a/scenarios/kube/memory-hog/config.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -deployers: - image: - connection: {} - deployer_name: kubernetes -log: - level: error -logged_outputs: - error: - level: error - success: - level: debug diff --git a/scenarios/kube/memory-hog/input.yaml b/scenarios/kube/memory-hog/input.yaml deleted file mode 100644 index 444b4767..00000000 --- a/scenarios/kube/memory-hog/input.yaml +++ /dev/null @@ -1,13 +0,0 @@ -input_list: -- duration: 30 - vm_bytes: 10% - vm_workers: 2 - # set the node selector as a key-value pair eg. - # node_selector: - # kubernetes.io/hostname: kind-worker2 - node_selector: { } - kubeconfig: "" - namespace: default - -# duplicate this section to run simultaneous stressors in the same run - diff --git a/scenarios/kube/memory-hog/sub-workflow.yaml b/scenarios/kube/memory-hog/sub-workflow.yaml deleted file mode 100644 index 06a0f523..00000000 --- a/scenarios/kube/memory-hog/sub-workflow.yaml +++ /dev/null @@ -1,89 +0,0 @@ -version: v0.2.0 -input: - root: SubRootObject - objects: - SubRootObject: - id: SubRootObject - properties: - kubeconfig: - display: - description: The complete kubeconfig file as a string - name: Kubeconfig file contents - type: - type_id: string - required: true - namespace: - display: - description: The namespace where the container will be deployed - name: Namespace - type: - type_id: string - required: true - node_selector: - display: - description: kubernetes node name where the plugin must be deployed - type: - type_id: map - values: - type_id: string - keys: - type_id: string - required: true - duration: - display: - name: duration the scenario expressed in seconds - description: stop stress test after T seconds. One can also specify the units of time in seconds, minutes, hours, days or years with the suffix s, m, h, d or y - type: - type_id: integer - required: true - vm_workers: - display: - description: Number of VM stressors to be run (0 means 1 stressor per CPU) - name: Number of VM stressors - type: - type_id: integer - required: true - vm_bytes: - display: - description: N bytes per vm process, the default is 256MB. The size can be expressed in units of Bytes, KBytes, MBytes and GBytes using the suffix b, k, m or g. - name: Kubeconfig file contents - type: - type_id: string - required: true - -steps: - kubeconfig: - plugin: - src: quay.io/arcalot/arcaflow-plugin-kubeconfig:0.2.0 - deployment_type: image - input: - kubeconfig: !expr $.input.kubeconfig - stressng: - plugin: - src: quay.io/arcalot/arcaflow-plugin-stressng:0.6.0 - deployment_type: image - step: workload - input: - cleanup: "true" - timeout: !expr $.input.duration - stressors: - - stressor: vm - workers: !expr $.input.vm_workers - vm-bytes: !expr $.input.vm_bytes - deploy: - deployer_name: kubernetes - connection: !expr $.steps.kubeconfig.outputs.success.connection - pod: - metadata: - namespace: !expr $.input.namespace - labels: - arcaflow: stressng - spec: - nodeSelector: !expr $.input.node_selector - pluginContainer: - imagePullPolicy: Always - -outputs: - success: - stressng: !expr $.steps.stressng.outputs.success - diff --git a/scenarios/kube/memory-hog/workflow.yaml b/scenarios/kube/memory-hog/workflow.yaml deleted file mode 100644 index fc51a5e4..00000000 --- a/scenarios/kube/memory-hog/workflow.yaml +++ /dev/null @@ -1,29 +0,0 @@ -version: v0.2.0 -input: - root: RootObject - objects: - RootObject: - id: RootObject - properties: - input_list: - type: - type_id: list - items: - id: SubRootObject - type_id: ref - namespace: $.steps.workload_loop.execute.inputs.items - -steps: - workload_loop: - kind: foreach - items: !expr $.input.input_list - workflow: sub-workflow.yaml - parallelism: 1000 -outputs: - success: - workloads: !expr $.steps.workload_loop.outputs.success.data - - - - -