def test_input_dict_type(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: values: schema: {a: int, b: int} value: {} """) sample1 = self.create_resource('sample1', sample_meta_dir, {'values': {'a': 1, 'b': 2}}) sample2 = self.create_resource('sample2', sample_meta_dir) xs.connect(sample1, sample2) self.assertEqual(sample1.args['values'], sample2.args['values']) # Check update sample1.update({'values': {'a': 2}}) self.assertEqual(sample1.args['values'], {'a': 2}) self.assertEqual(sample1.args['values'], sample2.args['values'], ) # Check disconnect # TODO: should sample2.value be reverted to original value? sample1.disconnect(sample2) sample1.update({'values': {'a': 3}}) self.assertEqual(sample1.args['values'], {'a': 3})
def test_hash_input_with_multiple_connections(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: ip: schema: str! value: """) receiver_meta_dir = self.make_resource_meta(""" id: receiver handler: ansible version: 1.0.0 input: ip: schema: str! value: server: schema: {ip: str!} """) sample = self.create_resource('sample', sample_meta_dir, args={'ip': '10.0.0.1'}) receiver = self.create_resource('receiver', receiver_meta_dir) xs.connect(sample, receiver, mapping={'ip': ['ip', 'server:ip']}) self.assertEqual(sample.args['ip'], receiver.args['ip']) self.assertDictEqual( {'ip': sample.args['ip']}, receiver.args['server'], )
def setup_resources(): ModelMeta.remove_all() node2 = vr.create('node2', 'resources/ro_node/', { 'ip': '10.0.0.4', 'ssh_key': '/vagrant/.vagrant/machines/solar-dev2/virtualbox/private_key', 'ssh_user': '******' })[0] solar_bootstrap2 = vr.create('solar_bootstrap2', 'resources/solar_bootstrap', {'master_ip': '10.0.0.2'})[0] signals.connect(node2, solar_bootstrap2) has_errors = False for r in locals().values(): if not isinstance(r, resource.Resource): continue print 'Validating {}'.format(r.name) errors = validation.validate_resource(r) if errors: has_errors = True print 'ERROR: %s: %s' % (r.name, errors) if has_errors: sys.exit(1)
def deploy(filename): with open(filename) as f: config = yaml.load(f) workdir = config['workdir'] resource_save_path = os.path.join(workdir, config['resource-save-path']) # Clean stuff first db.clear() xs.Connections.clear() shutil.rmtree(resource_save_path, ignore_errors=True) os.makedirs(resource_save_path) # Create resources first for resource_definition in config['resources']: name = resource_definition['name'] model = os.path.join(workdir, resource_definition['model']) args = resource_definition.get('args', {}) log.debug('Creating %s %s %s %s', name, model, resource_save_path, args) xr.create(name, model, resource_save_path, args=args) # Create resource connections for connection in config['connections']: emitter = db.get_resource(connection['emitter']) receiver = db.get_resource(connection['receiver']) mapping = connection.get('mapping') log.debug('Connecting %s %s %s', emitter.name, receiver.name, mapping) xs.connect(emitter, receiver, mapping=mapping) # Run all tests if 'test-suite' in config: log.debug('Running tests from %s', config['test-suite']) test_suite = __import__(config['test-suite'], {}, {}, ['main']) test_suite.main()
def create_virtual_resource(vr_name, template): resources = template["resources"] connections = [] created_resources = [] cwd = os.getcwd() for resource in resources: name = resource["id"] base_path = os.path.join(cwd, resource["from"]) args = resource["values"] new_resources = create(name, base_path, args, vr_name) created_resources += new_resources if not is_virtual(base_path): for key, arg in args.items(): if isinstance(arg, basestring) and "::" in arg: emitter, src = arg.split("::") connections.append((emitter, name, {src: key})) db = load_all() for emitter, reciver, mapping in connections: emitter = db[emitter] reciver = db[reciver] signals.connect(emitter, reciver, mapping) return created_resources
def setup_resources(): ModelMeta.remove_all() node2 = vr.create( 'node2', 'resources/ro_node/', { 'ip': '10.0.0.4', 'ssh_key': '/vagrant/.vagrant/machines/solar-dev2/virtualbox/private_key', 'ssh_user': '******' })[0] solar_bootstrap2 = vr.create('solar_bootstrap2', 'resources/solar_bootstrap', {'master_ip': '10.0.0.2'})[0] signals.connect(node2, solar_bootstrap2) has_errors = False for r in locals().values(): if not isinstance(r, resource.Resource): continue print 'Validating {}'.format(r.name) errors = validation.validate_resource(r) if errors: has_errors = True print 'ERROR: %s: %s' % (r.name, errors) if has_errors: sys.exit(1)
def test_revert_removed_child(): res1 = orm.DBResource(id='test1', name='test1', base_path='x') res1.save() res1.add_input('a', 'str', '9') res2 = orm.DBResource(id='test2', name='test2', base_path='x') res2.save() res2.add_input('a', 'str', 0) res1 = resource.load('test1') res2 = resource.load('test2') signals.connect(res1, res2) staged_log = change.stage_changes() assert len(staged_log) == 2 for item in staged_log: operations.move_to_commited(item.log_action) res2.remove() staged_log = change.stage_changes() assert len(staged_log) == 1 logitem = next(staged_log.collection()) operations.move_to_commited(logitem.log_action) with mock.patch.object(resource, 'read_meta') as mread: mread.return_value = {'input': {'a': {'schema': 'str!'}}} change.revert(logitem.uid) res2 = resource.load('test2') assert res2.args == {'a': '9'}
def test_simple_observer_unsubscription(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: ip: schema: str value: """) sample = self.create_resource('sample', sample_meta_dir, {'ip': None}) sample1 = self.create_resource('sample1', sample_meta_dir, {'ip': '10.0.0.1'}) sample2 = self.create_resource('sample2', sample_meta_dir, {'ip': '10.0.0.2'}) xs.connect(sample1, sample) self.assertEqual(sample1.args['ip'], sample.args['ip']) #self.assertEqual(len(list(sample1.args['ip'].receivers)), 1) #self.assertEqual( # sample.args['ip'].emitter, # sample1.args['ip'] #) xs.connect(sample2, sample) self.assertEqual(sample2.args['ip'], sample.args['ip']) # sample should be unsubscribed from sample1 and subscribed to sample2 #self.assertEqual(len(list(sample1.args['ip'].receivers)), 0) #self.assertEqual(sample.args['ip'].emitter, sample2.args['ip']) sample2.update({'ip': '10.0.0.3'}) self.assertEqual(sample2.args['ip'], sample.args['ip'])
def connect_with_events(self, receiver, mapping=None, events=None, use_defaults=False): signals.connect(self, receiver, mapping=mapping) if use_defaults: api.add_default_events(self, receiver) if events: api.add_events(self.name, events)
def prepare_nodes(nodes_count): resources = vr.create("nodes", "templates/nodes_with_transports.yaml", {"count": nodes_count}) nodes = [x for x in resources if x.name.startswith("node")] resources = vr.create("nodes_network", "templates/nodes_network.yaml", {"count": nodes_count}) nodes_sdn = [x for x in resources if x.name.startswith("node")] r = {} for node, node_sdn in zip(nodes, nodes_sdn): r[node.name] = node r[node_sdn.name] = node_sdn # LIBRARIAN librarian = vr.create("librarian_{}".format(node.name), "resources/librarian", {})[0] r[librarian.name] = librarian node.connect(librarian, {}) # NETWORKING # TODO(bogdando) node's IPs should be populated as br-mgmt IPs, but now are hardcoded in templates signals.connect(node, node_sdn) node_sdn.connect_with_events(librarian, {"module": "modules"}, {}) evapi.add_dep(librarian.name, node_sdn.name, actions=("run", "update")) signals.connect(node, node_sdn) node_sdn.connect_with_events(librarian, {"module": "modules"}, {}) evapi.add_dep(librarian.name, node_sdn.name, actions=("run", "update")) return r
def test_hash_input_with_multiple_connections(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: ip: schema: str! value: """) receiver_meta_dir = self.make_resource_meta(""" id: receiver handler: ansible version: 1.0.0 input: ip: schema: str! value: server: schema: {ip: str!} """) sample = self.create_resource('sample', sample_meta_dir, args={'ip': '10.0.0.1'}) receiver = self.create_resource('receiver', receiver_meta_dir) xs.connect(sample, receiver, mapping={'ip': ['ip', 'server:ip']}) self.assertEqual(sample.args['ip'], receiver.args['ip']) self.assertDictEqual({'ip': sample.args['ip']}, receiver.args['server'], )
def test_removal(self): """Test that connection removed with resource.""" sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: value: schema: int value: 0 """) sample1 = self.create_resource( 'sample1', sample_meta_dir, {'value': 1} ) sample2 = self.create_resource( 'sample2', sample_meta_dir, {} ) signals.connect(sample1, sample2) self.assertEqual(sample1.args['value'], sample2.args['value']) sample1 = resource.load('sample1') sample2 = resource.load('sample2') sample1.delete() self.assertEqual(sample2.args['value'], 0)
def test_revert_removed_child(): res1 = orm.DBResource(id="test1", name="test1", base_path="x") # NOQA res1.save() res1.add_input("a", "str", "9") res2 = orm.DBResource(id="test2", name="test2", base_path="x") # NOQA res2.save() res2.add_input("a", "str", 0) res1 = resource.load("test1") res2 = resource.load("test2") signals.connect(res1, res2) staged_log = change.stage_changes() assert len(staged_log) == 2 for item in staged_log: operations.move_to_commited(item.log_action) res2.remove() staged_log = change.stage_changes() assert len(staged_log) == 1 logitem = next(staged_log.collection()) operations.move_to_commited(logitem.log_action) with mock.patch.object(resource, "read_meta") as mread: mread.return_value = {"input": {"a": {"schema": "str!"}}} change.revert(logitem.uid) res2 = resource.load("test2") assert res2.args == {"a": "9"}
def connect_list_to_each(self, resources, mapping=None, events=None): """Connect each resource in self.resources to each resource in resources. mapping -- optional mapping "{emitter_num}" -- substitutes for emitter's index in mapping (from self.resources) "{receiver_num}" -- substitutes for receiver's index in mapping (from resources argument) """ mapping = mapping or {} for emitter_num, emitter in enumerate(self.resources): for receiver_num, receiver in enumerate(resources.resources): kwargs = { 'emitter_num': emitter_num, 'receiver_num': receiver_num, } mapping_fmt = self.args_fmt(mapping, kwargs) signals.connect( emitter, receiver, mapping=mapping_fmt, events=events )
def prepare_nodes(nodes_count): resources = vr.create('nodes', 'templates/nodes_with_transports.yaml', {"count": nodes_count}) nodes = [x for x in resources if x.name.startswith('node')] resources = vr.create('nodes_network', 'templates/nodes_network.yaml', {"count": nodes_count}) nodes_sdn = [x for x in resources if x.name.startswith('node')] r = {} for node, node_sdn in zip(nodes, nodes_sdn): r[node.name] = node r[node_sdn.name] = node_sdn # LIBRARIAN librarian = vr.create('librarian_{}'.format(node.name), 'resources/librarian', {})[0] r[librarian.name] = librarian node.connect(librarian, {}) # NETWORKING # TODO(bogdando) node's IPs should be populated as br-mgmt IPs, but now are hardcoded in templates signals.connect(node, node_sdn) node_sdn.connect_with_events(librarian, {'module': 'modules'}, {}) evapi.add_dep(librarian.name, node_sdn.name, actions=('run', 'update')) signals.connect(node, node_sdn) node_sdn.connect_with_events(librarian, {'module': 'modules'}, {}) evapi.add_dep(librarian.name, node_sdn.name, actions=('run', 'update')) return r
def prepare_nodes(nodes_count): resources = cr.create('nodes', 'templates/nodes', {"count": nodes_count}) nodes = resources.like('node') resources = cr.create('nodes_network', 'templates/nodes_network', {"count": nodes_count}) nodes_sdn = resources.like('node') r = {} for node, node_sdn in zip(nodes, nodes_sdn): r[node.name] = node r[node_sdn.name] = node_sdn # LIBRARIAN librarian = cr.create('librarian_{}'.format(node.name), 'resources/librarian', {})[0] r[librarian.name] = librarian node.connect(librarian, {}) # NETWORKING # TODO(bogdando) node's IPs should be populated as br-mgmt IPs, but now are hardcoded in templates signals.connect(node, node_sdn) node_sdn.connect_with_events(librarian, {'module': 'modules'}, {}) evapi.add_dep(librarian.name, node_sdn.name, actions=('run', 'update')) signals.connect(node, node_sdn) node_sdn.connect_with_events(librarian, {'module': 'modules'}, {}) evapi.add_dep(librarian.name, node_sdn.name, actions=('run', 'update')) return r
def connect_list_to_each(self, resources, mapping=None, events=None): """Connect resources Connect each resource in self.resources to each resource in resources. mapping -- optional mapping "{emitter_num}" -- substitutes for emitter's index in mapping (from self.resources) "{receiver_num}" -- substitutes for receiver's index in mapping (from resources argument) """ mapping = mapping or {} for emitter_num, emitter in enumerate(self.resources): for receiver_num, receiver in enumerate(resources.resources): kwargs = { 'emitter_num': emitter_num, 'receiver_num': receiver_num, } mapping_fmt = self.args_fmt(mapping, kwargs) signals.connect(emitter, receiver, mapping=mapping_fmt, events=events)
def test_no_cycles(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: value: schema: str! value: """) sample1 = self.create_resource( 'sample1', sample_meta_dir, {'value': 'x'} ) sample2 = self.create_resource( 'sample2', sample_meta_dir, {'value': 'y'} ) xs.connect(sample1, sample2) with self.assertRaisesRegexp( Exception, 'Prevented creating a cycle'): xs.connect(sample2, sample1)
def connect_list_to_each(self, resources, args={}, events=None): """Connect each resource in self.resources to each resource in resources. args -- optional list of arguments "{emitter_num}" -- substitutes for emitter's index in args (from self.resources) "{receiver_num}" -- substitutes for receiver's index in args (from resources argument) """ for emitter_num, emitter in enumerate(self.resources): for receiver_num, receiver in enumerate(resources.resources): kwargs = { 'emitter_num': emitter_num, 'receiver_num': receiver_num, } args_fmt = self.args_fmt(args, kwargs) signals.connect( emitter, receiver, mapping=args_fmt, events=events )
def test_revert_removed_child(): res1 = orm.DBResource(id='test1', name='test1', base_path='x') # NOQA res1.save() res1.add_input('a', 'str', '9') res2 = orm.DBResource(id='test2', name='test2', base_path='x') # NOQA res2.save() res2.add_input('a', 'str', 0) res1 = resource.load('test1') res2 = resource.load('test2') signals.connect(res1, res2) staged_log = change.stage_changes() assert len(staged_log) == 2 for item in staged_log: operations.move_to_commited(item.log_action) res2.remove() staged_log = change.stage_changes() assert len(staged_log) == 1 logitem = next(staged_log.collection()) operations.move_to_commited(logitem.log_action) with mock.patch.object(resource, 'read_meta') as mread: mread.return_value = {'input': {'a': {'schema': 'str!'}}} change.revert(logitem.uid) res2 = resource.load('test2') assert res2.args == {'a': '9'}
def test_input_dict_type(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: values: schema: {a: int, b: int} value: {} """) sample1 = self.create_resource('sample1', sample_meta_dir, {'values': { 'a': 1, 'b': 2 }}) sample2 = self.create_resource('sample2', sample_meta_dir) xs.connect(sample1, sample2) self.assertEqual(sample1.args['values'], sample2.args['values']) # Check update sample1.update({'values': {'a': 2}}) self.assertEqual(sample1.args['values'], {'a': 2}) self.assertEqual( sample1.args['values'], sample2.args['values'], ) # Check disconnect # TODO: should sample2.value be reverted to original value? xs.disconnect(sample1, sample2) sample1.update({'values': {'a': 3}}) self.assertEqual(sample1.args['values'], {'a': 3})
def test_simple_observer_unsubscription(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: ip: schema: str value: """) sample = self.create_resource('sample', sample_meta_dir, {'ip': None}) sample1 = self.create_resource('sample1', sample_meta_dir, {'ip': '10.0.0.1'}) sample2 = self.create_resource('sample2', sample_meta_dir, {'ip': '10.0.0.2'}) xs.connect(sample1, sample) self.assertEqual(sample1.args['ip'], sample.args['ip']) xs.connect(sample2, sample) self.assertEqual(sample2.args['ip'], sample.args['ip']) # sample should be unsubscribed from sample1 and subscribed to sample2 sample2.update({'ip': '10.0.0.3'}) self.assertEqual(sample2.args['ip'], sample.args['ip'])
def test_hash_input_with_list(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: ip: schema: str! value: port: schema: int! value: """) receiver_meta_dir = self.make_resource_meta(""" id: receiver handler: ansible version: 1.0.0 input: server: schema: [{ip: str!, port: int!}] """) sample1 = self.create_resource('sample1', sample_meta_dir, args={'ip': '10.0.0.1', 'port': 5000}) receiver = self.create_resource('receiver', receiver_meta_dir) xs.connect(sample1, receiver, mapping={ 'ip': 'server:ip', 'port': 'server:port' }) self.assertItemsEqual( [{'ip': sample1.args['ip'], 'port': sample1.args['port']}], receiver.args['server'], ) sample2 = self.create_resource('sample2', sample_meta_dir, args={'ip': '10.0.0.2', 'port': 5001}) xs.connect(sample2, receiver, mapping={ 'ip': 'server:ip', 'port': 'server:port' }) self.assertItemsEqual( [{'ip': sample1.args['ip'], 'port': sample1.args['port']}, {'ip': sample2.args['ip'], 'port': sample2.args['port']}], receiver.args['server'], ) sample1.disconnect(receiver) self.assertItemsEqual( [{'ip': sample2.args['ip'], 'port': sample2.args['port']}], receiver.args['server'], )
def creating_process(): sample1 = self.create_resource('sample1', sample_meta_dir, {'value': 1}) sample2 = self.create_resource( 'sample2', sample_meta_dir, ) signals.connect(sample1, sample2) self.assertEqual(sample1.args['value'], sample2.args['value'])
def creating_process(): sample1 = self.create_resource( 'sample1', sample_meta_dir, {'value': 1} ) sample2 = self.create_resource( 'sample2', sample_meta_dir, {} ) signals.connect(sample1, sample2) self.assertEqual(sample1.args['value'], sample2.args['value'])
def _revert_remove(logitem): """Resource should be created with all previous connections """ commited = orm.DBCommitedState.load(logitem.res) args = dictdiffer.revert(logitem.diff, commited.inputs) connections = dictdiffer.revert(logitem.signals_diff, sorted(commited.connections)) resource.Resource(logitem.res, logitem.base_path, args=args, tags=commited.tags) for emitter, emitter_input, receiver, receiver_input in connections: emmiter_obj = resource.load(emitter) receiver_obj = resource.load(receiver) signals.connect(emmiter_obj, receiver_obj, {emitter_input: receiver_input})
def update_inputs(child, args): child = load_resource(child) connections, assignments = parse_inputs(args) for c in connections: mapping = {} parent = load_resource(c['parent']) events = c['events'] mapping[c['parent_input']] = c['child_input'] signals.connect(parent, child, mapping, events) child.update(assignments)
def on_each(self, resource_path, args=None): """Create resource form resource_path on each resource.""" args = args or {} created_resources = ResourceListTemplate.create(len(self.resources), resource_path, args=args) for i, resource in enumerate(self.resources): signals.connect(resource, created_resources.resources[i]) return created_resources
def test_multiple_resource_disjoint_connect(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: ip: schema: string value: port: schema: int value: """) sample_ip_meta_dir = self.make_resource_meta(""" id: sample-ip handler: ansible version: 1.0.0 input: ip: schema: string value: """) sample_port_meta_dir = self.make_resource_meta(""" id: sample-port handler: ansible version: 1.0.0 input: port: schema: int value: """) sample = self.create_resource( 'sample', sample_meta_dir, {'ip': None, 'port': None} ) sample_ip = self.create_resource( 'sample-ip', sample_ip_meta_dir, {'ip': '10.0.0.1'} ) sample_port = self.create_resource( 'sample-port', sample_port_meta_dir, {'port': '8000'} ) xs.connect(sample_ip, sample) xs.connect(sample_port, sample) self.assertEqual(sample.args['ip'], sample_ip.args['ip']) self.assertEqual(sample.args['port'], sample_port.args['port']) self.assertEqual( sample.args['ip'].emitter, sample_ip.args['ip'] ) self.assertEqual( sample.args['port'].emitter, sample_port.args['port'] )
def test_backtrack_list(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: value: schema: str! value: """) sample_list_meta_dir = self.make_resource_meta(""" id: sample_list handler: ansible version: 1.0.0 input: values: schema: [str!] value: """) sample_list = self.create_resource( 'sample_list', sample_list_meta_dir ) vi = sample_list.resource_inputs()['values'] sample1 = self.create_resource( 'sample1', sample_meta_dir, {'value': 'x'} ) sample2 = self.create_resource( 'sample2', sample_meta_dir, {'value': 'y'} ) sample3 = self.create_resource( 'sample3', sample_meta_dir, {'value': 'z'} ) self.assertEqual(vi.backtrack_value_emitter(), vi) # [sample1] -> sample_list signals.connect(sample1, sample_list, {'value': 'values'}) self.assertEqual(vi.backtrack_value_emitter(), [sample1.resource_inputs()['value']]) # [sample3, sample1] -> sample_list signals.connect(sample3, sample_list, {'value': 'values'}) self.assertSetEqual(set(vi.backtrack_value_emitter()), set([sample1.resource_inputs()['value'], sample3.resource_inputs()['value']])) # sample2 disconnected signals.disconnect(sample1, sample_list) self.assertEqual(vi.backtrack_value_emitter(), [sample3.resource_inputs()['value']])
def run(): db.clear() resources = vr.create('nodes', 'templates/nodes_with_transports.yaml', {'count': 2}) nodes = [x for x in resources if x.name.startswith('node')] node1, node2 = nodes hosts1 = vr.create('hosts_file1', 'resources/hosts_file', {})[0] hosts2 = vr.create('hosts_file2', 'resources/hosts_file', {})[0] signals.connect(node1, hosts1, { 'name': 'hosts:name', 'ip': 'hosts:ip', }) signals.connect(node2, hosts2, { 'name': 'hosts:name', 'ip': 'hosts:ip', }) signals.connect(node1, hosts2, { 'name': 'hosts:name', 'ip': 'hosts:ip', }) signals.connect(node2, hosts1, { 'name': 'hosts:name', 'ip': 'hosts:ip', })
def on_each(self, resource_path, args=None): """Create resource form resource_path on each resource.""" args = args or {} created_resources = ResourceListTemplate.create( len(self.resources), resource_path, args=args ) for i, resource in enumerate(self.resources): signals.connect(resource, created_resources.resources[i]) return created_resources
def test_hash_input_mixed(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: ip: schema: str! value: port: schema: int! value: """) receiver_meta_dir = self.make_resource_meta(""" id: receiver handler: ansible version: 1.0.0 input: server: schema: {ip: str!, port: int!} """) sample = self.create_resource('sample', sample_meta_dir, args={ 'ip': '10.0.0.1', 'port': 5000 }) receiver = self.create_resource('receiver', receiver_meta_dir, args={'server': { 'port': 5001 }}) xs.connect(sample, receiver, mapping={'ip': 'server:ip'}) self.assertDictEqual( { 'ip': sample.args['ip'], 'port': 5001 }, receiver.args['server'], ) sample.update({'ip': '10.0.0.2'}) self.assertDictEqual( { 'ip': sample.args['ip'], 'port': 5001 }, receiver.args['server'], )
def connect(mapping, receiver, emitter): mapping_parsed = {} click.echo('Connect {} to {}'.format(emitter, receiver)) emitter = sresource.load(emitter) receiver = sresource.load(receiver) try: mapping_parsed.update(json.loads(mapping)) except ValueError: for m in mapping.split(): k, v = m.split('->') mapping_parsed.update({k: v}) signals.connect(emitter, receiver, mapping=mapping_parsed) show_emitter_connections(emitter)
def _revert_remove(logitem): """Resource should be created with all previous connections""" commited = CommitedResource.get(logitem.resource) args = dictdiffer.revert(logitem.diff, commited.inputs) connections = dictdiffer.revert( logitem.connections_diff, sorted(commited.connections)) resource.Resource(logitem.resource, logitem.base_path, args=_get_args_to_update(args, connections), tags=commited.tags) for emitter, emitter_input, receiver, receiver_input in connections: emmiter_obj = resource.load(emitter) receiver_obj = resource.load(receiver) signals.connect(emmiter_obj, receiver_obj, { emitter_input: receiver_input})
def test_multiple_resource_disjoint_connect(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: ip: schema: str value: port: schema: int value: """) sample_ip_meta_dir = self.make_resource_meta(""" id: sample-ip handler: ansible version: 1.0.0 input: ip: schema: str value: """) sample_port_meta_dir = self.make_resource_meta(""" id: sample-port handler: ansible version: 1.0.0 input: port: schema: int value: """) sample = self.create_resource('sample', sample_meta_dir, { 'ip': None, 'port': None }) sample_ip = self.create_resource('sample-ip', sample_ip_meta_dir, {'ip': '10.0.0.1'}) sample_port = self.create_resource('sample-port', sample_port_meta_dir, {'port': 8000}) self.assertNotEqual( sample.resource_inputs()['ip'], sample_ip.resource_inputs()['ip'], ) xs.connect(sample_ip, sample) xs.connect(sample_port, sample) self.assertEqual(sample.args['ip'], sample_ip.args['ip']) self.assertEqual(sample.args['port'], sample_port.args['port'])
def connect_list(self, resources, args={}): """Connect this resource to a ResourceListTemplate object. args - optional connect mapping. This mapping can have the "{receiver_num}" string which enumerates each resrouce in resources list. """ for receiver_num, resource in enumerate(resources.resources): kwargs = { 'receiver_num': receiver_num, } args_fmt = self.args_fmt(args, kwargs) signals.connect(self.resource, resource, args_fmt)
def connect(mapping, receiver, emitter): mapping_parsed = None emitter = sresource.load(emitter) receiver = sresource.load(receiver) click.echo('Connect {} to {}'.format(emitter, receiver)) if mapping: mapping_parsed = {} try: mapping_parsed.update(json.loads(mapping)) except ValueError: for m in mapping.split(): k, v = m.split('->') mapping_parsed.update({k: v}) signals.connect(emitter, receiver, mapping=mapping_parsed) show_emitter_connections(emitter)
def test_no_self_connection(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: value: schema: str! value: """) sample = self.create_resource('sample', sample_meta_dir, {'value': 'x'}) with self.assertRaisesRegexp(Exception, 'Trying to connect value-.* to itself'): xs.connect(sample, sample, {'value'})
def connect_list(self, resources, mapping=None): """Connect this resource to a ResourceListTemplate object. mapping - optional connect mapping. This mapping can have the "{receiver_num}" string which enumerates each resrouce in resources list. """ mapping = mapping or {} for receiver_num, resource in enumerate(resources.resources): kwargs = { 'receiver_num': receiver_num, } mapping_fmt = self.args_fmt(mapping, kwargs) signals.connect(self.resource, resource, mapping_fmt)
def test_backtrack_dict(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: value: schema: str! value: """) sample_dict_meta_dir = self.make_resource_meta(""" id: sample_dict handler: ansible version: 1.0.0 input: value: schema: {a: str!} value: """) sample_dict = self.create_resource( 'sample_dict', sample_dict_meta_dir ) vi = sample_dict.resource_inputs()['value'] sample1 = self.create_resource( 'sample1', sample_meta_dir, {'value': 'x'} ) sample2 = self.create_resource( 'sample2', sample_meta_dir, {'value': 'z'} ) self.assertEqual(vi.backtrack_value_emitter(), vi) # {a: sample1} -> sample_dict signals.connect(sample1, sample_dict, {'value': 'value:a'}) self.assertDictEqual(vi.backtrack_value_emitter(), {'a': sample1.resource_inputs()['value']}) # {a: sample2} -> sample_dict signals.connect(sample2, sample_dict, {'value': 'value:a'}) self.assertDictEqual(vi.backtrack_value_emitter(), {'a': sample2.resource_inputs()['value']}) # sample2 disconnected signals.disconnect(sample2, sample_dict) self.assertEqual(vi.backtrack_value_emitter(), vi)
def assign_resources_to_nodes(resources, nodes): for node in nodes: for resource in resources: res = deepcopy(resource) res['tags'] = list(set(node.get('tags', [])) | set(resource.get('tags', []))) resource_uuid = '{0}-{1}'.format(res['id'], solar.utils.generate_uuid()) # We should not generate here any uuid's, because # a single node should be represented with a single # resource node_uuid = node['id'] node_resource_template = solar.utils.read_config()['node_resource_template'] args = {k: v['value'] for k, v in res['input'].items()} created_resource = create(resource_uuid, resource['dir_path'], args, tags=res['tags']) created_node = create(node_uuid, node_resource_template, node, tags=node.get('tags', [])) signals.connect(created_node, created_resource)
def add_connections(resource_name, args): connections = [] for receiver_input, arg in args.items(): if isinstance(arg, list): for item in arg: c = parse_connection(resource_name, receiver_input, item) connections.append(c) else: c = parse_connection(resource_name, receiver_input, arg) connections.append(c) connections = [c for c in connections if c is not None] for c in connections: parent = resource.load(c['parent']) child = resource.load(c['child']) events = c['events'] mapping = {c['parent_input'] : c['child_input']} signals.connect(parent, child, mapping, events)
def test_circular_connection_prevention(self): # TODO: more complex cases sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: ip: schema: str value: """) sample1 = self.create_resource('sample1', sample_meta_dir, {'ip': '10.0.0.1'}) sample2 = self.create_resource('sample2', sample_meta_dir, {'ip': '10.0.0.2'}) xs.connect(sample1, sample2) with self.assertRaises(Exception): xs.connect(sample2, sample1)
def create_resources(resources, tags=None): created_resources = [] cwd = os.getcwd() for r in resources: resource_name = r['id'] args = r.get('values', {}) node = r.get('location', None) from_path = r.get('from', None) tags = r.get('tags', []) base_path = os.path.join(cwd, from_path) new_resources = create(resource_name, base_path, args=args, tags=tags) created_resources += new_resources if not is_virtual(base_path): if node: node = load_resource(node) r = new_resources[0] signals.connect(node, r, {}) r.add_tags('location={}'.format(node.name)) update_inputs(resource_name, args) return created_resources
def test_no_cycles(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: value: schema: str! value: """) sample1 = self.create_resource('sample1', sample_meta_dir, {'value': 'x'}) sample2 = self.create_resource('sample2', sample_meta_dir, {'value': 'y'}) xs.connect(sample1, sample2) with self.assertRaisesRegexp(Exception, 'Prevented creating a cycle'): xs.connect(sample2, sample1)
def add_solard(i): solard_transport = vr.create('solard_transport%s' % i, 'resources/transport_solard', { 'solard_user': '******', 'solard_password': '******' })[0] transports = resource.load('transports%s' % i) ssh_transport = resource.load('ssh_transport%s' % i) transports_for_solard = vr.create('transports_for_solard%s' % i, 'resources/transports')[0] # install solard with ssh signals.connect(transports_for_solard, solard_transport, {}) signals.connect( ssh_transport, transports_for_solard, { 'ssh_key': 'transports:key', 'ssh_user': '******', 'ssh_port': 'transports:port', 'name': 'transports:name' }) # add solard to transports on this node signals.connect( solard_transport, transports, { 'solard_user': '******', 'solard_port': 'transports:port', 'solard_password': '******', 'name': 'transports:name' })
def deploy(): db = get_db() db.clear() signals.Connections.clear() node1 = resources_compiled.RoNodeResource('node1', None, {}) node1.ip = '10.0.0.3' node1.ssh_key = '/vagrant/.vagrant/machines/solar-dev1/virtualbox/private_key' node1.ssh_user = '******' rabbitmq_service1 = resources_compiled.RabbitmqServiceResource( 'rabbitmq_service1', None, { 'management_port': 15672, 'port': 5672, 'container_name': 'rabbitmq_service1', 'image': 'rabbitmq:3-management' }) openstack_vhost = resource.create('openstack_vhost', 'resources/rabbitmq_vhost/', {'vhost_name': 'openstack'})[0] openstack_rabbitmq_user = resource.create( 'openstack_rabbitmq_user', 'resources/rabbitmq_user/', { 'user_name': 'openstack', 'password': '******' })[0] #### # connections #### # rabbitmq signals.connect(node1, rabbitmq_service1) signals.connect(rabbitmq_service1, openstack_vhost) signals.connect(rabbitmq_service1, openstack_rabbitmq_user) signals.connect(openstack_vhost, openstack_rabbitmq_user, {'vhost_name': 'vhost_name'}) errors = vr.validate_resources() if errors: for r, error in errors: print 'ERROR: %s: %s' % (r.name, error) sys.exit(1) # run actions.resource_action(rabbitmq_service1, 'run') actions.resource_action(openstack_vhost, 'run') actions.resource_action(openstack_rabbitmq_user, 'run') time.sleep(10)
def test_discard_connection(): res1 = orm.DBResource(id='test1', name='test1', base_path='x') res1.save() res1.add_input('a', 'str', '9') res2 = orm.DBResource(id='test2', name='test2', base_path='x') res2.save() res2.add_input('a', 'str', '0') staged_log = change.stage_changes() for item in staged_log: operations.move_to_commited(item.log_action) res1 = resource.load('test1') res2 = resource.load('test2') signals.connect(res1, res2) staged_log = change.stage_changes() assert len(staged_log) == 1 assert res2.args == {'a': '9'} change.discard_all() assert res2.args == {'a': '0'} assert len(change.stage_changes()) == 0
def test_revert_update_connected(): res1 = orm.DBResource(id='test1', name='test1', base_path='x') res1.save() res1.add_input('a', 'str', '9') res2 = orm.DBResource(id='test2', name='test2', base_path='x') res2.save() res2.add_input('a', 'str', 0) res3 = orm.DBResource(id='test3', name='test3', base_path='x') res3.save() res3.add_input('a', 'str', 0) res1 = resource.load('test1') res2 = resource.load('test2') res3 = resource.load('test3') signals.connect(res1, res2) signals.connect(res2, res3) staged_log = change.stage_changes() assert len(staged_log) == 3 for item in staged_log: operations.move_to_commited(item.log_action) assert len(staged_log) == 0 signals.disconnect(res1, res2) staged_log = change.stage_changes() assert len(staged_log) == 2 to_revert = [] for item in staged_log: operations.move_to_commited(item.log_action) to_revert.append(item.uid) change.revert_uids(sorted(to_revert, reverse=True)) staged_log = change.stage_changes() assert len(staged_log) == 2 for item in staged_log: assert item.diff == [['change', 'a', [0, '9']]]
def _update_inputs_connections(res_obj, args, old_connections, new_connections): res_obj.update(args) removed = [] for item in old_connections: if item not in new_connections: removed.append(item) added = [] for item in new_connections: if item not in old_connections: added.append(item) for emitter, _, receiver, _ in removed: emmiter_obj = resource.load(emitter) receiver_obj = resource.load(receiver) signals.disconnect(emmiter_obj, receiver_obj) for emitter, emitter_input, receiver, receiver_input in added: emmiter_obj = resource.load(emitter) receiver_obj = resource.load(receiver) signals.connect(emmiter_obj, receiver_obj, {emitter_input: receiver_input})
def test_backtrack_dict_list(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: value: schema: str! value: """) sample_dict_list_meta_dir = self.make_resource_meta(""" id: sample_dict_list handler: ansible version: 1.0.0 input: value: schema: [{a: str!}] value: """) sample_dict_list = self.create_resource( 'sample_dict', sample_dict_list_meta_dir ) vi = sample_dict_list.resource_inputs()['value'] sample1 = self.create_resource( 'sample1', sample_meta_dir, {'value': 'x'} ) sample2 = self.create_resource( 'sample2', sample_meta_dir, {'value': 'y'} ) sample3 = self.create_resource( 'sample3', sample_meta_dir, {'value': 'z'} ) self.assertEqual(vi.backtrack_value_emitter(), vi) # [{a: sample1}] -> sample_dict_list signals.connect(sample1, sample_dict_list, {'value': 'value:a'}) self.assertListEqual(vi.backtrack_value_emitter(), [{'a': sample1.resource_inputs()['value']}]) # [{a: sample1}, {a: sample3}] -> sample_dict_list signals.connect(sample3, sample_dict_list, {'value': 'value:a'}) self.assertItemsEqual(vi.backtrack_value_emitter(), [{'a': sample1.resource_inputs()['value']}, {'a': sample3.resource_inputs()['value']}]) # [{a: sample1}, {a: sample2}] -> sample_dict_list signals.connect(sample2, sample_dict_list, {'value': 'value:a|sample3'}) self.assertItemsEqual(vi.backtrack_value_emitter(), [{'a': sample1.resource_inputs()['value']}, {'a': sample2.resource_inputs()['value']}]) # sample2 disconnected signals.disconnect(sample2, sample_dict_list) self.assertEqual(vi.backtrack_value_emitter(), [{'a': sample1.resource_inputs()['value']}])
def test_backtrack_simple(self): sample_meta_dir = self.make_resource_meta(""" id: sample handler: ansible version: 1.0.0 input: value: schema: str! value: """) sample1 = self.create_resource( 'sample1', sample_meta_dir, {'value': 'x'} ) sample2 = self.create_resource( 'sample2', sample_meta_dir, {'value': 'y'} ) sample3 = self.create_resource( 'sample3', sample_meta_dir, {'value': 'z'} ) vi = sample2.resource_inputs()['value'] self.assertEqual(vi.backtrack_value_emitter(), vi) # sample1 -> sample2 signals.connect(sample1, sample2) self.assertEqual(vi.backtrack_value_emitter(), sample1.resource_inputs()['value']) # sample3 -> sample1 -> sample2 signals.connect(sample3, sample1) self.assertEqual(vi.backtrack_value_emitter(), sample3.resource_inputs()['value']) # sample2 disconnected signals.disconnect(sample1, sample2) self.assertEqual(vi.backtrack_value_emitter(), vi)
def connect_list(self, resources, mapping=None, events=None): """Connect self.resources to given resources in a 1-1 fashion. First resource in self.resources is connected to first resource in resources, second to second, etc. mapping -- optional mapping "{num}" -- substitutes for resource's index in args """ mapping = mapping or {} for num, er in enumerate(zip(self.resources, resources.resources)): emitter, receiver = er kwargs = { 'num': num, } mapping_fmt = self.args_fmt(mapping, kwargs) signals.connect(emitter, receiver, mapping=mapping_fmt, events=events)