Add connect action

This commit is contained in:
Evgeniy L 2015-05-27 15:12:03 +02:00
parent 1470125937
commit 8033017c23
5 changed files with 96 additions and 5 deletions

View File

@ -29,6 +29,7 @@ from solar import extensions
from solar import utils
from solar.core import data
from solar.core.resource import assign_resources_to_nodes
from solar.core.resource import connect_resources
from solar.core.tags_set_parser import Expression
from solar.interfaces.db import get_db
@ -88,6 +89,13 @@ class Cmd(object):
parser.add_argument('-n', '--nodes')
parser.add_argument('-r', '--resources')
# Perform resources connection
parser = self.subparser.add_parser('connect')
parser.set_defaults(func=getattr(self, 'connect'))
parser.add_argument(
'-p',
'--profile')
def profile(self, args):
if args.create:
params = {'tags': args.tags, 'id': args.id}
@ -108,6 +116,10 @@ class Cmd(object):
def discover(self, args):
Discovery({'id': 'discovery'}).discover()
def connect(self, args):
profile = self.db.get_record('profiles', args.profile)
connect_resources(profile)
def assign(self, args):
nodes = filter(
lambda n: Expression(args.nodes, n.get('tags', [])).evaluate(),

View File

@ -0,0 +1,68 @@
import copy
import json
from itertools import imap, ifilter
import networkx as nx
import jinja2
import mock
from jinja2 import Template
def depends_on(init_value, value=None, tags=None):
if tags is None:
tags = []
if value is None:
value = init_value
called_with_tags = []
if isinstance(value, dict):
if value.get('first_resource'):
called_with_tags.extend(value.get('first_resource'))
elif value.get('filter_resources'):
called_with_tags.extend(value.get('filter_resources'))
for k, v in value.items():
depends_on(init_value, value=v, tags=tags)
elif isinstance(value, list):
for e in value:
depends_on(init_value, value=e, tags=tags)
elif isinstance(value, str):
return value
tags.extend(called_with_tags)
return tags
class ResourcesConnectionGraph(object):
def __init__(self, connections, resources, *args, **kwargs):
super(ResourcesConnectionGraph, self).__init__(*args, **kwargs)
self.connections = connections
self.resources = resources
def iter_connections(self):
for connection in self.connections:
connections_from = self.resources_with_tags(depends_on(connection))
connections_to = self.resources_with_tags(connection['for_resources'])
mapping = self.make_mapping(connection)
for connection_from in connections_from:
for connection_to in connections_to:
if connection_from == connection_to:
continue
yield {'from': connection_from, 'to': connection_to, 'mapping': mapping}
def resources_with_tags(self, tags):
"""Filter all resources which have tags
"""
return filter(lambda r: set(r.tags) & set(tags), self.resources)
def make_mapping(self, connection):
return connection['mapping']

View File

@ -5,6 +5,7 @@ class Profile(object):
self._profile = profile
self.tags = set(profile['tags'])
self.extensions = profile.get('extensions', [])
self.connections = profile.get('connections', [])
def get(self, key):
return self._profile.get(key, None)

View File

@ -15,6 +15,8 @@ from solar.core import signals
from solar.core import utils
from solar.core import validation
from solar.core.connections import ResourcesConnectionGraph
class Resource(object):
def __init__(self, name, metadata, args, base_dir, tags=None):
@ -24,6 +26,9 @@ class Resource(object):
self.actions = metadata['actions'].keys() if metadata['actions'] else None
self.args = {}
for arg_name, arg_value in args.items():
if not self.metadata['input'].get(arg_name):
continue
metadata_arg = self.metadata['input'][arg_name]
type_ = validation.schema_input_type(metadata_arg.get('schema', 'str'))
@ -108,7 +113,6 @@ class Resource(object):
meta_file = os.path.join(self.base_dir, 'meta.yaml')
with open(meta_file, 'w') as f:
f.write(yaml.dump(metadata))
f.write(yaml.dump(metadata, default_flow_style=False))
@ -128,13 +132,12 @@ def create(name, base_path, dest_path, args, connections={}):
meta['id'] = name
meta['version'] = '1.0.0'
meta['actions'] = {}
meta['tags'] = []
if os.path.exists(actions_path):
for f in os.listdir(actions_path):
meta['actions'][os.path.splitext(f)[0]] = f
resource = Resource(name, meta, args, dest_path)
resource = Resource(name, meta, args, dest_path, tags=args['tags'])
signals.assign_connections(resource, connections)
# save
@ -178,7 +181,6 @@ def assign_resources_to_nodes(resources, nodes, dst_dir):
merged = deepcopy(resource)
# Node specific setting should override resource's
merged.update(deepcopy(node))
# Tags for specific resource is set of tags from node and from resource
merged['tags'] = list(set(node.get('tags', [])) |
set(resource.get('tags', [])))
@ -187,3 +189,12 @@ def assign_resources_to_nodes(resources, nodes, dst_dir):
resource['dir_path'],
dst_dir,
merged)
def connect_resources(profile):
connections = profile.get('connections', [])
resources = load_all('/vagrant/tmp/resource-instances/')
graph = ResourcesConnectionGraph(connections, resources.values())
for connection in graph.iter_connections():
signals.connect(connection['from'], connection['to'], connection['mapping'])

View File

@ -40,4 +40,3 @@ def save_to_config_file(key, data):
with open(fpath, 'w') as f:
encoder = ext_encoder(fpath)
encoder.dump(data, f)