Merge branch 'master' into cgenie/solar-bootstrap
This commit is contained in:
commit
0c3f3208b6
37
README.md
37
README.md
@ -157,6 +157,43 @@ from x import resource
|
||||
all_resources = resource.load_all('rs')
|
||||
```
|
||||
|
||||
## Dry run
|
||||
|
||||
Solar CLI has possibility to show dry run of actions to be performed.
|
||||
To see what will happen when you run Puppet action, for example, try this:
|
||||
|
||||
```
|
||||
solar resource action keystone_puppet run -d
|
||||
```
|
||||
|
||||
This should print out something like this:
|
||||
|
||||
```
|
||||
EXECUTED:
|
||||
73c6cb1cf7f6cdd38d04dd2d0a0729f8: (0, 'SSH RUN', ('sudo cat /tmp/puppet-modules/Puppetfile',), {})
|
||||
3dd4d7773ce74187d5108ace0717ef29: (1, 'SSH SUDO', ('mv "1038cb062449340bdc4832138dca18cba75caaf8" "/tmp/puppet-modules/Puppetfile"',), {})
|
||||
ae5ad2455fe2b02ba46b4b7727eff01a: (2, 'SSH RUN', ('sudo librarian-puppet install',), {})
|
||||
208764fa257ed3159d1788f73c755f44: (3, 'SSH SUDO', ('puppet apply -vd /tmp/action.pp',), {})
|
||||
```
|
||||
|
||||
By default every mocked command returns an empty string. If you want it to return
|
||||
something else (to check how would dry run behave in different situation) you provide
|
||||
a mapping (in JSON format), something along the lines of:
|
||||
|
||||
```
|
||||
solar resource action keystone_puppet run -d -m "{\"73c\": \"mod 'openstack-keystone'\n\"}"
|
||||
```
|
||||
|
||||
The above means the return string of first command (with hash `73c6c...`) will be
|
||||
as specified in the mapping. Notice that in mapping you don't have to specify the
|
||||
whole hash, just it's unique beginning. Also, you don't have to specify the whole
|
||||
return string in mapping. Dry run executor can read file and return it's contents
|
||||
instead, just use the `>` operator when specifying hash:
|
||||
|
||||
```
|
||||
solar resource action keystone_puppet run -d -m "{\"73c>\": \"./Puppetlabs-file\"}"
|
||||
```
|
||||
|
||||
## Resource compiling
|
||||
|
||||
You can compile all `meta.yaml` definitions into Python code with classes that
|
||||
|
1
main.yml
1
main.yml
@ -9,6 +9,7 @@
|
||||
|
||||
# PIP
|
||||
- apt: name=python-pip state=absent
|
||||
- apt: name=python-six state=absent
|
||||
- shell: easy_install pip
|
||||
- shell: pip install -U pip
|
||||
- shell: pip install -U setuptools
|
||||
|
@ -17,7 +17,7 @@ input:
|
||||
value: false
|
||||
glance_request_timeout:
|
||||
schema: str
|
||||
value: ''
|
||||
value:
|
||||
|
||||
git:
|
||||
schema: {repository: str!, branch: str!}
|
||||
|
55
solar/solar/cli/executors.py
Normal file
55
solar/solar/cli/executors.py
Normal file
@ -0,0 +1,55 @@
|
||||
from hashlib import md5
|
||||
|
||||
|
||||
class DryRunExecutor(object):
|
||||
def __init__(self, mapping=None):
|
||||
from fabric import api as fabric_api
|
||||
from fabric.contrib import project as fabric_project
|
||||
import mock
|
||||
|
||||
from solar.core.handlers import puppet
|
||||
|
||||
self.executed = []
|
||||
|
||||
self.mapping = mapping or {}
|
||||
|
||||
def dry_run_executor(command_name):
|
||||
def wrapper(*args, **kwargs):
|
||||
key = (len(self.executed), command_name, args, kwargs)
|
||||
|
||||
self.executed.append(key)
|
||||
|
||||
return self.find_hash(self.compute_hash(key))
|
||||
|
||||
return wrapper
|
||||
|
||||
# Add your own mocks here, IO, whatever
|
||||
fabric_api.local = mock.Mock(side_effect=dry_run_executor('LOCAL RUN'))
|
||||
fabric_api.put = mock.Mock(side_effect=dry_run_executor('PUT'))
|
||||
fabric_api.run = mock.Mock(side_effect=dry_run_executor('SSH RUN'))
|
||||
fabric_api.sudo = mock.Mock(side_effect=dry_run_executor('SSH SUDO'))
|
||||
fabric_project.rsync_project = mock.Mock(side_effect=dry_run_executor('RSYNC PROJECT'))
|
||||
|
||||
def compute_hash(self, key):
|
||||
return md5(str(key)).hexdigest()
|
||||
|
||||
def find_hash(self, hash):
|
||||
stripped_hashes = {k.replace('>', ''): k for k in self.mapping}
|
||||
|
||||
hashes = [k for k in stripped_hashes if hash.startswith(k)]
|
||||
|
||||
if len(hashes) == 0:
|
||||
#raise Exception('Hash {} not found'.format(hash))
|
||||
return ''
|
||||
elif len(hashes) > 1:
|
||||
raise Exception('Hash {} not unique in {}'.format(
|
||||
hash, hashes
|
||||
))
|
||||
|
||||
hash = stripped_hashes[hashes[0]]
|
||||
|
||||
if hash.endswith('>'):
|
||||
with open(self.mapping[hash]) as f:
|
||||
return f.read()
|
||||
|
||||
return self.mapping[hash]
|
@ -33,12 +33,12 @@ from solar.core import resource as sresource
|
||||
from solar.core.resource import assign_resources_to_nodes
|
||||
from solar.core import signals
|
||||
from solar.core.tags_set_parser import Expression
|
||||
from solar.core import testing
|
||||
from solar.core.resource import virtual_resource as vr
|
||||
from solar.interfaces.db import get_db
|
||||
from solar import errors
|
||||
from solar.core.log import log
|
||||
|
||||
from solar.cli import executors
|
||||
from solar.cli.orch import orchestration
|
||||
from solar.cli.system_log import changes
|
||||
|
||||
@ -134,10 +134,15 @@ def init_actions():
|
||||
@main.command()
|
||||
@click.option('-t', '--tags')
|
||||
@click.option('-a', '--action')
|
||||
def run(action, tags):
|
||||
@click.option('-d', '--dry-run', default=False, is_flag=True)
|
||||
@click.option('-m', '--dry-run-mapping', default='{}')
|
||||
def run(dry_run_mapping, dry_run, action, tags):
|
||||
from solar.core import actions
|
||||
from solar.core import resource
|
||||
|
||||
if dry_run:
|
||||
dry_run_executor = executors.DryRunExecutor(mapping=json.loads(dry_run_mapping))
|
||||
|
||||
resources = filter(
|
||||
lambda r: Expression(tags, r.get('tags', [])).evaluate(),
|
||||
db.get_list('resource'))
|
||||
@ -146,6 +151,14 @@ def init_actions():
|
||||
resource_obj = sresource.load(resource['id'])
|
||||
actions.resource_action(resource_obj, action)
|
||||
|
||||
if dry_run:
|
||||
click.echo('EXECUTED:')
|
||||
for key in dry_run_executor.executed:
|
||||
click.echo('{}: {}'.format(
|
||||
click.style(dry_run_executor.compute_hash(key), fg='green'),
|
||||
str(key)
|
||||
))
|
||||
|
||||
|
||||
def init_cli_connect():
|
||||
@main.command()
|
||||
@ -238,7 +251,12 @@ def init_cli_resource():
|
||||
@resource.command()
|
||||
@click.argument('action')
|
||||
@click.argument('resource')
|
||||
def action(action, resource):
|
||||
@click.option('-d', '--dry-run', default=False, is_flag=True)
|
||||
@click.option('-m', '--dry-run-mapping', default='{}')
|
||||
def action(dry_run_mapping, dry_run, action, resource):
|
||||
if dry_run:
|
||||
dry_run_executor = executors.DryRunExecutor(mapping=json.loads(dry_run_mapping))
|
||||
|
||||
click.echo(
|
||||
'action {} for resource {}'.format(action, resource)
|
||||
)
|
||||
@ -250,6 +268,14 @@ def init_cli_resource():
|
||||
log.debug(e)
|
||||
sys.exit(1)
|
||||
|
||||
if dry_run:
|
||||
click.echo('EXECUTED:')
|
||||
for key in dry_run_executor.executed:
|
||||
click.echo('{}: {}'.format(
|
||||
click.style(dry_run_executor.compute_hash(key), fg='green'),
|
||||
str(key)
|
||||
))
|
||||
|
||||
@resource.command()
|
||||
def compile_all():
|
||||
from solar.core.resource import compiler
|
||||
|
@ -91,6 +91,7 @@ class LibrarianPuppet(ResourceSSHMixin):
|
||||
self.resource,
|
||||
'sudo', 'cat', '/var/tmp/puppet/Puppetfile'
|
||||
)
|
||||
log.debug('Puppetlabs file is: \n%s\n', puppetlabs)
|
||||
|
||||
git = self.resource.args['git'].value
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user