Add connect action
This commit is contained in:
parent
1470125937
commit
8033017c23
@ -29,6 +29,7 @@ from solar import extensions
|
|||||||
from solar import utils
|
from solar import utils
|
||||||
from solar.core import data
|
from solar.core import data
|
||||||
from solar.core.resource import assign_resources_to_nodes
|
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.core.tags_set_parser import Expression
|
||||||
from solar.interfaces.db import get_db
|
from solar.interfaces.db import get_db
|
||||||
|
|
||||||
@ -88,6 +89,13 @@ class Cmd(object):
|
|||||||
parser.add_argument('-n', '--nodes')
|
parser.add_argument('-n', '--nodes')
|
||||||
parser.add_argument('-r', '--resources')
|
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):
|
def profile(self, args):
|
||||||
if args.create:
|
if args.create:
|
||||||
params = {'tags': args.tags, 'id': args.id}
|
params = {'tags': args.tags, 'id': args.id}
|
||||||
@ -108,6 +116,10 @@ class Cmd(object):
|
|||||||
def discover(self, args):
|
def discover(self, args):
|
||||||
Discovery({'id': 'discovery'}).discover()
|
Discovery({'id': 'discovery'}).discover()
|
||||||
|
|
||||||
|
def connect(self, args):
|
||||||
|
profile = self.db.get_record('profiles', args.profile)
|
||||||
|
connect_resources(profile)
|
||||||
|
|
||||||
def assign(self, args):
|
def assign(self, args):
|
||||||
nodes = filter(
|
nodes = filter(
|
||||||
lambda n: Expression(args.nodes, n.get('tags', [])).evaluate(),
|
lambda n: Expression(args.nodes, n.get('tags', [])).evaluate(),
|
||||||
|
68
solar/solar/core/connections.py
Normal file
68
solar/solar/core/connections.py
Normal 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']
|
@ -5,6 +5,7 @@ class Profile(object):
|
|||||||
self._profile = profile
|
self._profile = profile
|
||||||
self.tags = set(profile['tags'])
|
self.tags = set(profile['tags'])
|
||||||
self.extensions = profile.get('extensions', [])
|
self.extensions = profile.get('extensions', [])
|
||||||
|
self.connections = profile.get('connections', [])
|
||||||
|
|
||||||
def get(self, key):
|
def get(self, key):
|
||||||
return self._profile.get(key, None)
|
return self._profile.get(key, None)
|
||||||
|
@ -15,6 +15,8 @@ from solar.core import signals
|
|||||||
from solar.core import utils
|
from solar.core import utils
|
||||||
from solar.core import validation
|
from solar.core import validation
|
||||||
|
|
||||||
|
from solar.core.connections import ResourcesConnectionGraph
|
||||||
|
|
||||||
|
|
||||||
class Resource(object):
|
class Resource(object):
|
||||||
def __init__(self, name, metadata, args, base_dir, tags=None):
|
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.actions = metadata['actions'].keys() if metadata['actions'] else None
|
||||||
self.args = {}
|
self.args = {}
|
||||||
for arg_name, arg_value in args.items():
|
for arg_name, arg_value in args.items():
|
||||||
|
if not self.metadata['input'].get(arg_name):
|
||||||
|
continue
|
||||||
|
|
||||||
metadata_arg = self.metadata['input'][arg_name]
|
metadata_arg = self.metadata['input'][arg_name]
|
||||||
type_ = validation.schema_input_type(metadata_arg.get('schema', 'str'))
|
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')
|
meta_file = os.path.join(self.base_dir, 'meta.yaml')
|
||||||
with open(meta_file, 'w') as f:
|
with open(meta_file, 'w') as f:
|
||||||
f.write(yaml.dump(metadata))
|
|
||||||
f.write(yaml.dump(metadata, default_flow_style=False))
|
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['id'] = name
|
||||||
meta['version'] = '1.0.0'
|
meta['version'] = '1.0.0'
|
||||||
meta['actions'] = {}
|
meta['actions'] = {}
|
||||||
meta['tags'] = []
|
|
||||||
|
|
||||||
if os.path.exists(actions_path):
|
if os.path.exists(actions_path):
|
||||||
for f in os.listdir(actions_path):
|
for f in os.listdir(actions_path):
|
||||||
meta['actions'][os.path.splitext(f)[0]] = f
|
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)
|
signals.assign_connections(resource, connections)
|
||||||
|
|
||||||
# save
|
# save
|
||||||
@ -178,7 +181,6 @@ def assign_resources_to_nodes(resources, nodes, dst_dir):
|
|||||||
merged = deepcopy(resource)
|
merged = deepcopy(resource)
|
||||||
# Node specific setting should override resource's
|
# Node specific setting should override resource's
|
||||||
merged.update(deepcopy(node))
|
merged.update(deepcopy(node))
|
||||||
# Tags for specific resource is set of tags from node and from resource
|
|
||||||
merged['tags'] = list(set(node.get('tags', [])) |
|
merged['tags'] = list(set(node.get('tags', [])) |
|
||||||
set(resource.get('tags', [])))
|
set(resource.get('tags', [])))
|
||||||
|
|
||||||
@ -187,3 +189,12 @@ def assign_resources_to_nodes(resources, nodes, dst_dir):
|
|||||||
resource['dir_path'],
|
resource['dir_path'],
|
||||||
dst_dir,
|
dst_dir,
|
||||||
merged)
|
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'])
|
||||||
|
@ -40,4 +40,3 @@ def save_to_config_file(key, data):
|
|||||||
with open(fpath, 'w') as f:
|
with open(fpath, 'w') as f:
|
||||||
encoder = ext_encoder(fpath)
|
encoder = ext_encoder(fpath)
|
||||||
encoder.dump(data, f)
|
encoder.dump(data, f)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user