Beispiel #1
0
def main():
    action, timeout, args = parse_args(sys.argv[1:])

    try:
        ret = loop.run(
            run_action(action, timeout, args)
        )
    except Exception as e:
        log_traceback(e)
        ret = 1

    sys.exit(ret)
Beispiel #2
0
def parse_args(argv):
    parser = get_parser()
    try:
        parsed = parser.parse_args(argv)
        args = vars(parsed)
        action = args.pop('action')
        timeout = args.pop('timeout')

        args = load_kv_arg(args, 'upgrade_params')
        args = load_kv_arg(args, 'origin_keys')
    except Exception as e:
        log_traceback(e)
        parser.print_help()
        sys.exit(1)
    try:
        if args.get('debug', False):
            logger.setLevel(logging.DEBUG)
            logHandler.setLevel(logging.DEBUG)
    except Exception:
        pass
    return action, timeout, args
Beispiel #3
0
async def clean(ctrl_name='',
                model_name='',
                ignore=[],
                wait=False,
                force=False,
                dry_run=False,
                endpoint='',
                username='',
                password='',
                cacert='',
                **kwargs):
    """Destroy applications present in the current or selected model.

    Connection requires juju client configs to be present locally or specification of credentialls:
    endpoint (e.g. 127.0.0.1:17070), username, password, and model uuid as model_name.

    :param ctrl_name: juju controller
    :param model_name: juju model name or uuid
    :param ignore: list of application names
    :param wait: boolean
    :param force: boolean
    :param dry_run: boolean
    :param endpoint: string
    :param username: string
    :param password: string
    :param cacert: string
    """
    controller, model = await connect_juju(ctrl_name,
                                           model_name,
                                           endpoint=endpoint,
                                           username=username,
                                           password=password,
                                           cacert=cacert)

    try:
        # Remove all the apps
        for app in model.applications:
            if app in ignore:
                log.info('Ignoring {}'.format(app))
            else:
                log.info('Remove {} from model'.format(app))
                if not dry_run:
                    try:
                        await model.applications[app].destroy()
                    except KeyError:
                        pass
                    except Exception as e:
                        log.error(str(e))
                        log_traceback(e)

        if not ignore and force:
            facade = client.ClientFacade.from_connection(model.connection())
            for machine in await model.get_machines():
                log.info('Remove machine {} from model'.format(machine))
                if not dry_run:
                    try:
                        await facade.DestroyMachines(force=force,
                                                     machine_names=[machine])
                    except Exception as e:
                        log.warn(
                            'Removing machine from model failed or already removed. {}'
                            .format(e))

        if wait and not ignore and not dry_run:
            await wait_until(
                model,
                lambda: model.applications == {} and model.machines == {},
                loop=model.loop)

    except JujuError as e:
        log.info(e.message)
    finally:
        # Disconnect from the api server and cleanup.
        await model.disconnect()
        await controller.disconnect()
Beispiel #4
0
async def deploy(
    bundle_file,
    ctrl_name='',
    model_name='',
    wait=False,
    endpoint='',
    username='',
    password='',
    cacert='',
    error_timeout=None,
    **kwargs
):
    """Deploy a local juju bundle.

    Handles deployment of a bundle file to the current or selected model.

    Connection requires juju client configs to be present locally or specification of credentialls:
    endpoint (e.g. 127.0.0.1:17070), username, password, and model uuid as model_name.

    :param bundle_file: juju bundle file
    :param ctrl_name: juju controller
    :param model_name: juju model name or uuid
    :param wait: boolean
    :param endpoint: string
    :param username: string
    :param password: string
    :param cacert: string
    """
    ret = 0
    log.info('Reading bundle: {}'.format(bundle_file.name))
    entity_url = 'local:' + bundle_file.name.replace('/bundle.yaml', '')

    controller, model = await connect_juju(
        ctrl_name,
        model_name,
        endpoint=endpoint,
        username=username,
        password=password,
        cacert=cacert
    )

    try:
        # Deploy a bundle
        log.info("Deploy: {}".format(entity_url))
        deployed_apps = await model.deploy(
            entity_url
        )
        if not isinstance(deployed_apps, list):
            deployed_apps = [deployed_apps]

        if wait:
            await wait_until(
                model,
                deployed_apps,
                log,
                loop=model.loop,
                error_timeout=error_timeout
            )
        else:
            log.info('{} - Apps: {}'.format(
                'DEPLOYED',
                len(deployed_apps)
            ))

    except ApperrorTimeout:
        ret = 124
        log.error('FAILED - Application too long in error state')
    except ConnectionClosed as e:
        ret = 1
        log.error('FAILED - Connection closed')
        log_traceback(e)
    except JujuError as e:
        ret = 1
        log.error('JujuError during deploy')
        log_traceback(e)
    finally:
        # Disconnect from the api server and cleanup.
        await model.disconnect()
        await controller.disconnect()
    return ret
Beispiel #5
0
async def test(test_suite='',
               ctrl_name='',
               model_name='',
               endpoint='',
               username='',
               password='',
               cacert='',
               **kwargs):
    """Run a test suite against applications deployed in the current or selected model.

    Applications are tested with declarative parameters specified in the test suite using the available brokers.

    Connection requires juju client configs to be present locally or specification of credentialls:
    endpoint (e.g. 127.0.0.1:17070), username, password, and model uuid as model_name.

    :param test_suite: suite file (Yaml)
    :param ctrl_name: juju controller
    :param model_name: juju model name or uuid
    :param endpoint: string
    :param username: string
    :param password: string
    :param cacert: string
    """
    log.info('Load tests')
    if test_suite:
        with open(test_suite.name, 'r') as stream:
            try:
                if hasattr(yaml, 'full_load'):
                    suite = yaml.full_load(stream)
                else:
                    suite = yaml.load(stream)
                suite_apps = suite.keys()
            except yaml.YAMLError as exc:
                log.error(exc)
                suite_apps = []

    log.info('Applications: {}'.format(', '.join(suite_apps)))

    controller, model = await connect_juju(ctrl_name,
                                           model_name,
                                           endpoint=endpoint,
                                           username=username,
                                           password=password,
                                           cacert=cacert)

    model_passed, model_failed = 0, 0
    failed_units = set()

    try:
        for app_name, app in model.applications.items():
            if suite and app_name in suite:
                app_passed, app_failed = 0, 0
                try:
                    test_cases = len([
                        key for x in suite[app_name].values()
                        for y in x.values() if isinstance(x, dict) for key in y
                    ])
                except Exception:
                    test_cases = 0
                log.info('{} - {} - {} units - {} tests - {} {}'.format(
                    "----", app_name, len(app.units), test_cases, app.status,
                    app.alive))
                for idx, unit in enumerate(app.units):
                    async with async_timeout.timeout(60):
                        passed, failed = await execute_brokers(
                            suite[app_name], unit, idx)
                        app_passed += passed
                        app_failed += failed
                        if app.status in ['error', 'maintenance', 'blocked'
                                          ] or failed:
                            failed_units.add(unit.name)
                model_passed += app_passed
                model_failed += app_failed
                log.info('{} - {}: Passed tests: {}'.format(
                    "====", app_name, app_passed))
                log.info('{} - {}: Failed tests: {}'.format(
                    "====", app_name, app_failed))

        alive = defaultdict(int)
        status = defaultdict(int)
        for app in model.applications.values():
            alive[app.alive] += 1
            status[app.status] += 1

        if (False not in alive
                and all(s in ['active', 'waiting'] for s in status.keys())):
            log.info('All juju apps state to be alive and active.')
        else:
            log.warning('Finished with errors')
            log.warning('Alive: {}'.format(dict(alive)))
            log.warning('Status: {}'.format(dict(status)))

        log.info('{}: {}'.format("Passed tests", model_passed))
        if model_failed:
            log.warning('{}: {}'.format("Failed tests", model_failed))
        else:
            log.info('{}: {}'.format("Failed tests", model_failed))

    except JujuError as e:
        log.error('JujuError during tests')
        log_traceback(e)
    finally:
        # Disconnect from the api server and cleanup.
        await model.disconnect()
        await controller.disconnect()

    if failed_units:
        log.error('Failed units: {}'.format(', '.join(sorted(failed_units))))
        return 1