template.py - custom DSL for easier resource creation

This commit is contained in:
Przemyslaw Kaminski 2015-08-25 16:02:42 +02:00
parent 8f04b47d90
commit bc08b9b137
2 changed files with 157 additions and 8 deletions

View File

@ -1,9 +1,9 @@
from solar.core import template
from solar import template
nodes = template.nodes_from('templates/riak_nodes.yml')
riak_services = nodes.on_every(
riak_services = nodes.on_each(
'resources/riak_node',
{
'riak_self_name': 'riak{num}',
@ -11,18 +11,16 @@ riak_services = nodes.on_every(
'riak_name': 'riak{num}@riak_server{num}.solar',
})
slave_riak_services = riak_services.filter(lambda num: num > 0)
riak_services.take(0).connect_list(
riak_services.filter(
lambda num: num > 0
),
slave_riak_services,
{
'riak_name': 'join_to',
}
)
hosts_files = nodes.on_every(
'resources/hosts_file'
)
hosts_files = nodes.on_each('resources/hosts_file')
riak_services.connect_list_to_each(
hosts_files,
@ -31,3 +29,9 @@ riak_services.connect_list_to_each(
'riak_hostname': 'hosts_names',
}
)
hosts_files.add_deps('run/success', riak_services, 'run')
slave_riak_services.add_reacts('run/success', slave_riak_services, 'join')
slave_riak_services.add_reacts('leave/success', slave_riak_services, 'join')
slave_riak_services.add_react('run/success', riak_services.take(0), 'commit')

145
solar/solar/template.py Normal file
View File

@ -0,0 +1,145 @@
import os
from solar.core.resource import virtual_resource as vr
from solar.core import signals
from solar.events.api import add_event
from solar.events import controls
class BaseTemplate(object):
@staticmethod
def args_fmt(args, kwargs):
return {
k.format(**kwargs): v.format(**kwargs) for k, v in args.items()
}
@staticmethod
def action_state_parse(action_state):
action, state = action_state.split('/')
return {
'action': action,
'state': state,
}
class ResourceTemplate(BaseTemplate):
def __init__(self, resource):
self.resource = resource
def connect_list(self, resources, args={}):
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)
class ResourceListTemplate(BaseTemplate):
def __init__(self, resources):
self.resources = resources
@classmethod
def create(cls, count, resource_path, args={}):
created_resources = []
resource_path_name = os.path.split(resource_path)[-1]
for num in range(count):
kwargs = {
'num': num,
'resource_path_name': resource_path_name,
}
kwargs['name'] = '{resource_path_name}-{num}'.format(**kwargs)
args_fmt = cls.args_fmt(args, kwargs)
r = vr.create('{name}'.format(**kwargs),
resource_path,
args_fmt)[0]
created_resources.append(r)
return ResourceListTemplate(created_resources)
def add_deps(self, action_state, resources, action):
action_state = self.action_state_parse(action_state)
for r, dep_r in zip(self.resources, resources.resources):
add_event(
controls.Dep(
r.name,
action_state['action'],
action_state['state'],
dep_r.name,
action
)
)
def add_react(self, action_state, resource, action):
action_state = self.action_state_parse(action_state)
for r in self.resources:
add_event(
controls.React(
r.name,
action_state['action'],
action_state['state'],
resource.resource.name,
action
)
)
def add_reacts(self, action_state, resources, action):
action_state = self.action_state_parse(action_state)
for r, react_r in zip(self.resources, resources.resources):
add_event(
controls.React(
r.name,
action_state['action'],
action_state['state'],
react_r.name,
action
)
)
def filter(self, func):
resources = filter(func, self.resources)
return ResourceListTemplate(resources)
def connect_list_to_each(self, resources, args={}):
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, args_fmt)
def on_each(self, resource_path, args={}):
created_resources = ResourceListTemplate.create(
len(self.resources),
resource_path,
args
)
for i, resource in enumerate(self.resources):
signals.connect(resource, created_resources.resources[i])
return created_resources
def take(self, i):
return ResourceTemplate(self.resources[i])
def nodes_from(template_path):
nodes = vr.create('nodes', template_path, {})
return ResourceListTemplate(nodes)