Beispiel #1
0
def test_single_with_import_from():
    data = load_test_fsm('single_with_import_from.yml')
    single_ast = parser.parse_to_ast(data)
    assert len(single_ast.fsms) == 1
    assert single_ast.fsms[0].name == "FSM1"
    assert single_ast.fsms[0].gather_facts is False
    assert single_ast.fsms[0].import_from == 'tests/inputs/fsm1.yml'
Beispiel #2
0
def test_multiple():
    data = load_test_fsm('multiple.yml')
    multiple_ast = parser.parse_to_ast(data)
    assert len(multiple_ast.fsms) == 2
    assert multiple_ast.fsms[0].name == "FSM1"
    assert type(multiple_ast.fsms[0]) == ast.FSM
    assert multiple_ast.fsms[1].name == "FSM2"
    assert type(multiple_ast.fsms[1]) == ast.FSM
Beispiel #3
0
def test_single_with_states():
    data = load_test_fsm('single_with_states.yml')
    single_ast = parser.parse_to_ast(data)
    assert len(single_ast.fsms) == 1
    assert single_ast.fsms[0].name == "FSM1"
    assert single_ast.fsms[0].gather_facts is False
    assert len(single_ast.fsms[0].states) == 2
    assert type(single_ast.fsms[0].states[0]) == ast.State
    assert single_ast.fsms[0].states[0].name == "Start"
    assert single_ast.fsms[0].states[1].name == "End"
Beispiel #4
0
def test_single_with_handlers():
    data = load_test_fsm('single_with_handlers.yml')
    single_ast = parser.parse_to_ast(data)
    assert len(single_ast.fsms) == 1
    assert single_ast.fsms[0].name == "FSM1"
    assert single_ast.fsms[0].gather_facts is False
    assert len(single_ast.fsms[0].states) == 2
    assert type(single_ast.fsms[0].states[0]) == ast.State
    assert len(single_ast.fsms[0].states[0].handlers) == 2
    assert len(single_ast.fsms[0].states[1].handlers) == 1
    assert len(single_ast.fsms[0].states[0].handlers) == 2
    assert type(single_ast.fsms[0].states[0].handlers[0]) == ast.Handler
    assert type(single_ast.fsms[0].states[0].handlers[1]) == ast.Handler
    assert single_ast.fsms[0].states[0].handlers[0].name == "enter"
    assert single_ast.fsms[0].states[0].handlers[1].name == "exit"
    assert single_ast.fsms[0].states[1].handlers[0].name == "enter"
Beispiel #5
0
def ansible_fsm_run(parsed_args):

    # Set up inventories
    default_inventory = 'localhost ansible_connection=local'
    inventory = default_inventory
    if parsed_args['--inventory']:
        with open(parsed_args['--inventory']) as f:
            inventory = f.read()

    # Build the FSMs
    with open(parsed_args['<fsm.yml>']) as f:
        data = yaml.safe_load(f.read())

    fsm_registry = dict()
    connectors_registry = dict()

    ast = fsm_parser.parse_to_ast(data)

    tracer = FileSystemTraceLog('fsm.log')

    fsms = []

    fsm_id_seq = count(0)

    for fsm in ast.fsms:
        if fsm.import_from is not None:
            with open(fsm.import_from) as f:
                data = yaml.safe_load(f.read())
                imported_fsm = fsm_parser.parse_to_fsm(data)
                fsm = FSM(
                    fsm.name or imported_fsm.name, fsm.hosts
                    or imported_fsm.hosts, fsm.gather_facts if fsm.gather_facts
                    is not None else imported_fsm.gather_facts, fsm.roles
                    or imported_fsm.roles, fsm.states or imported_fsm.states,
                    fsm.outputs or imported_fsm.outputs, None)
        play_header = dict(name=fsm.name,
                           hosts=fsm.hosts,
                           gather_facts=fsm.gather_facts)
        fsm_id = next(fsm_id_seq)
        states = {}
        for state in fsm.states:
            handlers = {}
            for handler in state.handlers:
                handlers[handler.name] = handler.body
            states[state.name] = State(state.name, handlers)
        if 'Start' not in states:
            raise Exception(
                'Missing required "Start" state in FSM: "{0}"'.format(
                    fsm.name))
        fsm_controller = FSMController(fsm.name, fsm_id, states,
                                       states.get('Start'), tracer, tracer,
                                       fsm_registry, fsm_id_seq, inventory,
                                       play_header, fsm.outputs)
        fsms.append(fsm_controller)

    fsm_threads = [x.thread for x in fsms]

    # Build the FSM registry
    fsm_registry.update({x.name: x for x in fsms})

    # Wire up FSM using channels
    if parsed_args['<channels.yml>']:
        with open(parsed_args['<channels.yml>']) as f:
            data = yaml.safe_load(f.read())

        channels_ast = channels_parser.parse_to_ast(data)

        for channel in channels_ast.channels:
            from_fsm = fsm_registry.get(channel.from_fsm, None)
            if from_fsm is None:
                raise Exception(
                    'Could not find an FSM named {} for channel {}'.format(
                        channel.from_fsm, channel.name))
            to_fsm = fsm_registry.get(channel.to_fsm, None)
            if from_fsm is None:
                raise Exception(
                    'Could not find an FSM named {} for channel {}'.format(
                        channel.from_fsm, channel.name))
            if channel.from_queue is not None:
                if channel.from_queue not in from_fsm.outboxes:
                    raise Exception(
                        'On {} FSM Could not find an output named {} for channel {}'
                        .format(channel.from_fsm, channel.from_queue,
                                channel.name))
                from_fsm.outboxes[channel.from_queue] = to_fsm.name
            else:
                from_fsm.outboxes['default'] = to_fsm.name

    # Adds connectors for external events
    connectors = []
    if parsed_args['--connectors']:
        with open(parsed_args['--connectors']) as f:
            connectors_spec = connectors_parser.parse_to_ast(
                yaml.safe_load(f.read()))
            for connector_spec in connectors_spec.connectors:
                if connector_spec.type not in connectors_type_registry:
                    raise Exception('Could not find the {0} connector'.format(
                        connector_spec.type))
                connector = connectors_type_registry[connector_spec.type](
                    fsm_registry, connectors_registry, connector_spec.config)
                connectors.append(connector)
                connectors_registry[connector_spec.name] = connector

    for connector in connectors:
        if isinstance(connector, ZMQEventChannel):
            control_socket_port = connector.socket_port
            break
    else:
        connector = ZMQEventChannel(fsm_registry, connectors_registry, {})
        control_socket_port = connector.socket_port
        connectors.append(connector)
        connectors_registry['zmq'] = connector

    # Start the FSMs by calling enter on all the FSMs.
    for fsm in fsms:
        fsm.control_socket_port = control_socket_port
        fsm.enter()

    # Start all the greenlets for the FSMs
    try:
        gevent.joinall(fsm_threads)
    except KeyboardInterrupt:
        print('Caught KeyboardInterrupt')
    finally:
        print('Shutting down...')
        for fsm in fsms:
            fsm.shutdown()
        print('Successful shutdown')
    return 0
Beispiel #6
0
def test_single():
    data = load_test_fsm('single.yml')
    single_ast = parser.parse_to_ast(data)
    assert len(single_ast.fsms) == 1
    assert single_ast.fsms[0].name == "FSM1"
    assert type(single_ast.fsms[0]) == ast.FSM
Beispiel #7
0
def test_null():
    null_ast = parser.parse_to_ast(list())
    assert len(null_ast.fsms) == 0
    assert type(null_ast) == ast.AST