mirror of
https://github.com/krkn-chaos/krkn.git
synced 2026-04-15 06:57:28 +00:00
125 lines
5.0 KiB
Python
125 lines
5.0 KiB
Python
#!/usr/bin/env python
|
|
|
|
import sys
|
|
import os
|
|
import time
|
|
import optparse
|
|
import logging
|
|
import yaml
|
|
import requests
|
|
import kraken.kubernetes.client as kubecli
|
|
import kraken.invoke.command as runcommand
|
|
import pyfiglet
|
|
|
|
|
|
# Main function
|
|
def main(cfg):
|
|
# Start kraken
|
|
print(pyfiglet.figlet_format("kraken"))
|
|
logging.info("Starting kraken")
|
|
|
|
# Parse and read the config
|
|
if os.path.isfile(cfg):
|
|
with open(cfg, 'r') as f:
|
|
config = yaml.full_load(f)
|
|
kubeconfig_path = config["kraken"]["kubeconfig_path"]
|
|
scenarios = config["kraken"]["scenarios"]
|
|
cerberus_enabled = config["cerberus"]["cerberus_enabled"]
|
|
wait_duration = config["tunings"]["wait_duration"]
|
|
iterations = config["tunings"]["iterations"]
|
|
daemon_mode = config["tunings"]['daemon_mode']
|
|
|
|
# Initialize clients
|
|
if not os.path.isfile(kubeconfig_path):
|
|
kubeconfig_path = None
|
|
logging.info("Initializing client to talk to the Kubernetes cluster")
|
|
kubecli.initialize_clients(kubeconfig_path)
|
|
|
|
# find node kraken might be running on
|
|
kubecli.find_kraken_node()
|
|
|
|
# Cluster info
|
|
logging.info("Fetching cluster info")
|
|
cluster_version = runcommand.invoke("kubectl get clusterversion")
|
|
cluster_info = runcommand.invoke("kubectl cluster-info | awk 'NR==1' | sed -r "
|
|
"'s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g'") # noqa
|
|
logging.info("\n%s%s" % (cluster_version, cluster_info))
|
|
|
|
# Initialize the start iteration to 0
|
|
iteration = 0
|
|
|
|
# Set the number of iterations to loop to infinity if daemon mode is
|
|
# enabled or else set it to the provided iterations count in the config
|
|
if daemon_mode:
|
|
logging.info("Daemon mode enabled, kraken will cause chaos forever")
|
|
logging.info("Ignoring the iterations set")
|
|
iterations = float('inf')
|
|
else:
|
|
logging.info("Daemon mode not enabled, will run through %s iterations"
|
|
% str(iterations))
|
|
iterations = int(iterations)
|
|
|
|
# Loop to run the chaos starts here
|
|
while (int(iteration) < iterations):
|
|
# Inject chaos scenarios specified in the config
|
|
try:
|
|
# Loop to run the scenarios starts here
|
|
for scenario in scenarios:
|
|
logging.info("Injecting scenario: %s" % (scenario))
|
|
runcommand.invoke("powerfulseal autonomous --use-pod-delete-instead-of-ssh-kill"
|
|
" --policy-file %s --kubeconfig %s --no-cloud"
|
|
" --inventory-kubernetes --headless"
|
|
% (scenario, kubeconfig_path))
|
|
logging.info("Scenario: %s has been successfully injected!" % (scenario))
|
|
|
|
if cerberus_enabled:
|
|
cerberus_url = config["cerberus"]["cerberus_url"]
|
|
if not cerberus_url:
|
|
logging.error("url where Cerberus publishes True/False signal "
|
|
"is not provided.")
|
|
sys.exit(1)
|
|
cerberus_status = requests.get(cerberus_url).content
|
|
cerberus_status = True if cerberus_status == b'True' else False
|
|
if not cerberus_status:
|
|
logging.error("Received a no-go signal from Cerberus, looks like the"
|
|
" cluster is unhealthy. Please check the Cerberus report"
|
|
" for more details. Test failed.")
|
|
sys.exit(1)
|
|
else:
|
|
logging.info("Received a go signal from Ceberus, the cluster is "
|
|
"healthy. Test passed.")
|
|
logging.info("Waiting for the specified duration: %s" % (wait_duration))
|
|
time.sleep(wait_duration)
|
|
except Exception as e:
|
|
logging.error("Failed to run scenario: %s. Encountered the following exception: %s"
|
|
% (scenario, e))
|
|
iteration += 1
|
|
else:
|
|
logging.error("Cannot find a config at %s, please check" % (cfg))
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Initialize the parser to read the config
|
|
parser = optparse.OptionParser()
|
|
parser.add_option(
|
|
"-c", "--config",
|
|
dest="cfg",
|
|
help="config location",
|
|
default="config/config.yaml",
|
|
)
|
|
(options, args) = parser.parse_args()
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format="%(asctime)s [%(levelname)s] %(message)s",
|
|
handlers=[
|
|
logging.FileHandler("kraken.report", mode='w'),
|
|
logging.StreamHandler()
|
|
]
|
|
)
|
|
if (options.cfg is None):
|
|
logging.error("Please check if you have passed the config")
|
|
sys.exit(1)
|
|
else:
|
|
main(options.cfg)
|