From 583f52a3165aa3a054edc7aa9c979547d78da87e Mon Sep 17 00:00:00 2001 From: Przemyslaw Kaminski Date: Tue, 16 Jun 2015 13:35:20 +0200 Subject: [PATCH] Compiled resources showoff --- config.yaml | 1 + example.py | 15 ++++- solar/requirements.txt | 1 + solar/solar/cli.py | 16 +++++ solar/solar/core/resource/__init__.py | 20 +++++++ solar/solar/core/resource/compiler.py | 66 +++++++++++++++++++++ solar/solar/core/{ => resource}/resource.py | 31 ++++++---- 7 files changed, 137 insertions(+), 13 deletions(-) create mode 100644 solar/solar/core/resource/__init__.py create mode 100644 solar/solar/core/resource/compiler.py rename solar/solar/core/{ => resource}/resource.py (93%) diff --git a/config.yaml b/config.yaml index f202a261..e0141798 100644 --- a/config.yaml +++ b/config.yaml @@ -12,6 +12,7 @@ file-system-db: template-dir: /vagrant/templates resources-files-mask: /vagrant/resources/*/*.yaml +resources-compiled-file: /vagrant/resources_compiled.py node_resource_template: /vagrant/resources/ro_node/ state: /tmp/state/ diff --git a/example.py b/example.py index 04e7e235..93364741 100644 --- a/example.py +++ b/example.py @@ -11,6 +11,8 @@ from solar.core import validation from solar.interfaces.db import get_db +import resources_compiled + @click.group() def main(): @@ -24,10 +26,17 @@ def deploy(): signals.Connections.clear() - node1 = resource.create('node1', 'resources/ro_node/', {'ip': '10.0.0.3', 'ssh_key': '/vagrant/.vagrant/machines/solar-dev1/virtualbox/private_key', 'ssh_user': 'vagrant'}) - node2 = resource.create('node2', 'resources/ro_node/', {'ip': '10.0.0.4', 'ssh_key': '/vagrant/.vagrant/machines/solar-dev2/virtualbox/private_key', 'ssh_user': 'vagrant'}) + #node1 = resource.create('node1', 'resources/ro_node/', {'ip': '10.0.0.3', 'ssh_key': '/vagrant/.vagrant/machines/solar-dev1/virtualbox/private_key', 'ssh_user': 'vagrant'}) + #node1 = resources_compiled.RoNodeResource('node1', None, {'ip': '10.0.0.3', 'ssh_key': '/vagrant/.vagrant/machines/solar-dev1/virtualbox/private_key', 'ssh_user': 'vagrant'}) + 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 = 'vagrant' + #node2 = resource.create('node2', 'resources/ro_node/', {'ip': '10.0.0.4', 'ssh_key': '/vagrant/.vagrant/machines/solar-dev2/virtualbox/private_key', 'ssh_user': 'vagrant'}) + node2 = resources_compiled.RoNodeResource('node2', None, {'ip': '10.0.0.4', 'ssh_key': '/vagrant/.vagrant/machines/solar-dev2/virtualbox/private_key', 'ssh_user': 'vagrant'}) - rabbitmq_service1 = resource.create('rabbitmq_service1', 'resources/rabbitmq_service/', {'management_port': '15672', 'port': '5672', 'container_name': 'rabbitmq_service1', 'image': 'rabbitmq:3-management'}) + #rabbitmq_service1 = resource.create('rabbitmq_service1', 'resources/rabbitmq_service/', {'management_port': '15672', 'port': '5672', 'container_name': 'rabbitmq_service1', 'image': 'rabbitmq:3-management'}) + 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'}) openstack_rabbitmq_user = resource.create('openstack_rabbitmq_user', 'resources/rabbitmq_user/', {'user_name': 'openstack', 'password': 'openstack_password'}) diff --git a/solar/requirements.txt b/solar/requirements.txt index a3d48744..0a638392 100644 --- a/solar/requirements.txt +++ b/solar/requirements.txt @@ -12,3 +12,4 @@ enum34==1.0.4 redis==2.10.3 pytest fakeredis +inflection diff --git a/solar/solar/cli.py b/solar/solar/cli.py index adfa69c7..8777b6b1 100644 --- a/solar/solar/cli.py +++ b/solar/solar/cli.py @@ -264,6 +264,22 @@ def init_cli_resource(): r = sresource.load(resource_path) actions.resource_action(r, action_name) + @resource.command() + def compile_all(): + from solar.core.resource import compiler + + destination_path = utils.read_config()['resources-compiled-file'] + + if os.path.exists(destination_path): + os.remove(destination_path) + + for path in utils.find_by_mask(utils.read_config()['resources-files-mask']): + meta = utils.yaml_load(path) + meta['base_path'] = os.path.dirname(path) + + compiler.compile(meta) + + @resource.command() @click.argument('name') @click.argument('base_path') diff --git a/solar/solar/core/resource/__init__.py b/solar/solar/core/resource/__init__.py new file mode 100644 index 00000000..e8926f1b --- /dev/null +++ b/solar/solar/core/resource/__init__.py @@ -0,0 +1,20 @@ +__all__ = [ + 'Resource', + 'assign_resources_to_nodes', + 'connect_resources', + 'create', + 'load', + 'load_all', + 'prepare_meta', + 'wrap_resource', +] + + +from solar.core.resource.resource import Resource +from solar.core.resource.resource import assign_resources_to_nodes +from solar.core.resource.resource import connect_resources +from solar.core.resource.resource import create +from solar.core.resource.resource import load +from solar.core.resource.resource import load_all +from solar.core.resource.resource import prepare_meta +from solar.core.resource.resource import wrap_resource diff --git a/solar/solar/core/resource/compiler.py b/solar/solar/core/resource/compiler.py new file mode 100644 index 00000000..002f7cdd --- /dev/null +++ b/solar/solar/core/resource/compiler.py @@ -0,0 +1,66 @@ +import inflection +import os +import pprint + +from solar.core import resource +from solar import utils + + +RESOURCE_HEADER_TEMPLATE = """ +from solar.core.resource import Resource +""" + + +RESOURCE_CLASS_TEMPLATE = """ + + +class {class_name}(Resource): + _metadata = {{ + 'actions': {meta_actions}, + 'actions_path': '{actions_path}', + 'base_path': '{base_path}', + 'input': {meta_input}, + 'handler': '{handler}', + }} + + {input_properties} +""" + + +RESOURCE_INPUT_PROPERTY_TEMPLATE = """ + @property + def {name}(self): + return self.args['{name}'] + + @{name}.setter + def {name}(self, value): + #self.args['{name}'].value = value + #self.set_args_from_dict({{'{name}': value}}) + self.update({{'{name}': value}}) +""" + + +def compile(meta): + destination_file = utils.read_config()['resources-compiled-file'] + + resource.prepare_meta(meta) + meta['class_name'] = '{}Resource'.format( + inflection.camelize(meta['base_name']) + ) + meta['meta_actions'] = pprint.pformat(meta['actions']) + meta['meta_input'] = pprint.pformat(meta['input']) + + print meta['base_name'], meta['class_name'] + + if not os.path.exists(destination_file): + with open(destination_file, 'w') as f: + f.write(RESOURCE_HEADER_TEMPLATE.format(**meta)) + + with open(destination_file, 'a') as f: + input_properties = '\n'.join( + RESOURCE_INPUT_PROPERTY_TEMPLATE.format(name=name) + for name in meta['input'] + ) + f.write(RESOURCE_CLASS_TEMPLATE.format( + input_properties=input_properties, **meta) + ) diff --git a/solar/solar/core/resource.py b/solar/solar/core/resource/resource.py similarity index 93% rename from solar/solar/core/resource.py rename to solar/solar/core/resource/resource.py index e1e25d75..533f991e 100644 --- a/solar/solar/core/resource.py +++ b/solar/solar/core/resource/resource.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -import copy import os from copy import deepcopy @@ -19,9 +18,16 @@ db = get_db() class Resource(object): + _metadata = {} + def __init__(self, name, metadata, args, tags=None): self.name = name - self.metadata = metadata + if metadata: + self.metadata = metadata + else: + self.metadata = deepcopy(self._metadata) + + self.metadata['id'] = name self.tags = tags or [] self.set_args_from_dict(args) @@ -159,23 +165,28 @@ class Resource(object): raise Exception('Uuups, action is not available') +def prepare_meta(meta): + actions_path = os.path.join(meta['base_path'], 'actions') + meta['actions_path'] = actions_path + meta['base_name'] = os.path.split(meta['base_path'])[-1] + + meta['actions'] = {} + if os.path.exists(meta['actions_path']): + for f in os.listdir(meta['actions_path']): + meta['actions'][os.path.splitext(f)[0]] = f + + def create(name, base_path, args, tags=[], connections={}): if not os.path.exists(base_path): raise Exception('Base resource does not exist: {0}'.format(base_path)) base_meta_file = os.path.join(base_path, 'meta.yaml') - actions_path = os.path.join(base_path, 'actions') meta = utils.yaml_load(base_meta_file) - meta['id'] = name - meta['version'] = '1.0.0' - meta['actions'] = {} - meta['actions_path'] = actions_path meta['base_path'] = os.path.abspath(base_path) + meta['version'] = '1.0.0' - if os.path.exists(actions_path): - for f in os.listdir(actions_path): - meta['actions'][os.path.splitext(f)[0]] = f + prepare_meta(meta) resource = Resource(name, meta, args, tags=tags) signals.assign_connections(resource, connections)