Esempio n. 1
0
 def __init__(self, logger=None):
     self.logger = logger or makeLogger(__name__)
 def __init__(self, cloud=None, conn=None, logger=None):
     self.logger = logger or makeLogger(__name__)
     self.conn = conn or create_connection_from_config(cloud)
     self.remote_servers = []
Esempio n. 3
0
 def __init__(self, name, namespace, k8s_inventory, logger=None):
     self.name = name
     self.namespace = namespace
     self.k8s_inventory = k8s_inventory
     self.logger = logger or makeLogger(__name__)
Esempio n. 4
0
def main(argv):
    """
        The main function to invoke the powerfulseal cli
    """
    args = parse_args(args=argv)

    if args.mode is None:
        return parse_args(['--help'])

    ##########################################################################
    # VALIDATE POLICY MODE
    ##########################################################################
    if args.mode == 'validate':
        policy = PolicyRunner.load_file(args.policy_file)
        if PolicyRunner.is_policy_valid(policy):
            return print('OK')
        print("Policy not valid. See log output above.")
        return sys.exit(1)

    ##########################################################################
    # LOGGING
    ##########################################################################
    # this is to calm down the flask stdout
    # calm down the workzeug
    logging.getLogger("werkzeug").setLevel(logging.ERROR)
    try:
        import click

        def echo(*args, **kwargs):
            pass

        click.echo = echo
        click.secho = echo
    except:
        pass

    # parse the verbosity flags
    if args.silent == 1:
        log_level = logging.WARNING
    elif args.silent == 2:
        log_level = logging.ERROR
    elif not args.verbose:
        log_level = logging.INFO
    else:
        log_level = logging.DEBUG

    server_log_handler = ServerStateLogHandler()
    server_log_handler.setLevel(log_level)

    # do a basic config with the server log handler
    logging.basicConfig(level=log_level, handlers=[server_log_handler])
    # this installs a stdout handler by default to the root
    coloredlogs.install(level=log_level,
                        fmt='%(asctime)s %(levelname)s %(name)s %(message)s')

    # the main cli handler
    logger = makeLogger(__name__)
    logger.setLevel(log_level)
    logger.info("verbosity: %s; log level: %s; handler level: %s",
                args.verbose, logging.getLevelName(logger.getEffectiveLevel()),
                logging.getLevelName(log_level))

    ##########################################################################
    # KUBERNETES
    ##########################################################################
    kube_config = parse_kubeconfig(args)
    k8s_client = K8sClient(kube_config=kube_config)
    operation_mode = args.execution_mode
    # backwards compatibility
    if args.use_pod_delete_instead_of_ssh_kill:
        operation_mode = "kubernetes"
    k8s_inventory = K8sInventory(k8s_client=k8s_client, )

    ##########################################################################
    # CLOUD DRIVER
    ##########################################################################
    if args.openstack:
        logger.info("Building OpenStack driver")
        driver = OpenStackDriver(cloud=args.openstack_cloud_name, )
    elif args.aws:
        logger.info("Building AWS driver")
        driver = AWSDriver()
    elif args.azure:
        logger.info("Building Azure driver")
        driver = AzureDriver(
            cluster_rg_name=args.azure_resource_group_name,
            cluster_node_rg_name=args.azure_node_resource_group_name,
        )
    elif args.gcp:
        logger.info("Building GCP driver")
        driver = GCPDriver(config=args.gcp_config_file)
    else:
        logger.info("No cloud driver - some functionality disabled")
        driver = NoCloudDriver()

    ##########################################################################
    # INVENTORY
    ##########################################################################
    if args.inventory_file:
        logger.info("Reading inventory from %s", args.inventory_file)
        groups_to_restrict_to = read_inventory_file_to_dict(
            args.inventory_file)
    else:
        logger.debug("Attempting to read the inventory from kubernetes")
        groups_to_restrict_to = k8s_client.get_nodes_groups()

    logger.debug("Restricting inventory to %s" % groups_to_restrict_to)

    inventory = NodeInventory(
        driver=driver,
        restrict_to_groups=groups_to_restrict_to,
    )
    inventory.sync()

    ##########################################################################
    # SSH EXECUTOR
    ##########################################################################
    if operation_mode == "kubernetes":
        executor = KubernetesExecutor(k8s_client=k8s_client, )
    else:
        if args.use_private_ip:
            logger.info("Using each node's private IP address")
        if args.override_ssh_host:
            logger.info("Using each overriten host: %s",
                        args.override_ssh_host)
        executor = SSHExecutor(
            user=args.remote_user,
            ssh_allow_missing_host_keys=args.ssh_allow_missing_host_keys,
            ssh_path_to_private_key=args.ssh_path_to_private_key,
            override_host=args.override_ssh_host,
            ssh_password=args.ssh_password,
            use_private_ip=args.use_private_ip,
            ssh_kill_command=args.ssh_kill_command,
        )

    ##########################################################################
    # INTERACTIVE MODE
    ##########################################################################
    if args.mode == 'interactive':
        # create a command parser
        cmd = PSCmd(
            inventory=inventory,
            driver=driver,
            executor=executor,
            k8s_inventory=k8s_inventory,
        )
        logger.info("STARTING INTERACTIVE MODE")
        while True:
            try:
                cmd.cmdloop()
            except GeneratorExit:
                print("Exiting")
                sys.exit(0)
            except KeyboardInterrupt:
                print()
                print("Ctrl-c again to quit")
            try:
                input()
            except KeyboardInterrupt:
                sys.exit(0)
        return

    ##########################################################################
    # METRICS
    ##########################################################################
    metric_collector = StdoutCollector()
    if args.prometheus_collector:
        flask_debug = os.environ.get("FLASK_DEBUG")
        flask_env = os.environ.get("FLASK_ENVIROMENT")
        if flask_debug is not None or (flask_env is not None
                                       and flask_env != "production"):
            logger.error(
                "PROMETHEUS METRICS NOT SUPPORTED WHEN USING FLASK RELOAD. NOT STARTING THE SERVER"
            )
        else:
            logger.info("Starting prometheus metrics server (%s:%s)",
                        args.prometheus_host, args.prometheus_port)
            start_http_server(args.prometheus_port, args.prometheus_host)
            metric_collector = PrometheusCollector()
    elif args.datadog_collector:
        logger.info("Starting datadog collector")
        metric_collector = DatadogCollector()
    else:
        logger.info("Using stdout metrics collector")

    ##########################################################################
    # AUTONOMOUS MODE
    ##########################################################################
    if args.mode == 'autonomous':

        # read and validate the policy
        policy = PolicyRunner.load_file(args.policy_file)
        if not PolicyRunner.is_policy_valid(policy):
            logger.error("Policy not valid. See log output above.")
            return sys.exit(1)

        # run the metrics server if requested
        if not args.headless:
            # start the server
            logger.info("Starting the UI server (%s:%s)", args.host, args.port)
            start_server(
                host=args.host,
                port=args.port,
                policy=policy,
                accept_proxy_headers=args.accept_proxy_headers,
                logger=server_log_handler,
            )
        else:
            logger.info("NOT starting the UI server")

        logger.info("STARTING AUTONOMOUS MODE")
        success = PolicyRunner.run(policy,
                                   inventory,
                                   k8s_inventory,
                                   driver,
                                   executor,
                                   metric_collector=metric_collector)
        if not success:
            logger.error("Policy runner finishes with an error")
            return sys.exit(1)
        return sys.exit(0)

    ##########################################################################
    # LABEL MODE
    ##########################################################################
    elif args.mode == 'label':
        label_runner = LabelRunner(
            inventory,
            k8s_inventory,
            driver,
            executor,
            min_seconds_between_runs=args.min_seconds_between_runs,
            max_seconds_between_runs=args.max_seconds_between_runs,
            namespace=args.kubernetes_namespace,
            metric_collector=metric_collector,
        )
        logger.info("STARTING LABEL MODE")
        label_runner.run()
Esempio n. 5
0
 def __init__(self, name, schema, logger=None, metric_collector=None):
     self.name = name
     self.schema = schema
     self.logger = logger or makeLogger(__name__, name)
     self.metric_collector = metric_collector or StdoutCollector()
     self.action_mapping = dict()
Esempio n. 6
0
 def __init__(self, config_file, k8s_client, logger=None):
     self.config_file = config_file
     self.k8s_client = k8s_client
     self.logger = logger or makeLogger(__name__)
Esempio n. 7
0
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import random
import time
import sys
import copy

import jsonschema
import yaml
import pkgutil
from powerfulseal import makeLogger
from .scenario import Scenario

logger = makeLogger(__name__)


class PolicyRunner():
    """ Reads, validates and executes a JSON schema-compliant policy
    """
    DEFAULT_POLICY = {"scenarios": []}

    def __init__(self, config_file, k8s_client, logger=None):
        self.config_file = config_file
        self.k8s_client = k8s_client
        self.logger = logger or makeLogger(__name__)

    def read_policy(self):
        """
            Read configuration
Esempio n. 8
0
 def __init__(self, driver, host, logger=None):
     self.driver = driver
     self.host = host
     self.logger = logger or makeLogger(__name__)
Esempio n. 9
0
 def __init__(self, k8s_client, logger=None):
     self.k8s_client = k8s_client
     self._cache_namespaces = []
     self._cache_last = None
     self.logger = logger or makeLogger(__name__)
     self.last_pods = []