Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Commit

Permalink
Fixed #45 -- Added the possibility to use the lxdock command from sub…
Browse files Browse the repository at this point in the history
…folders
  • Loading branch information
ellmetha committed Mar 19, 2017
1 parent f7d3329 commit 3e1a218
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 22 deletions.
2 changes: 1 addition & 1 deletion lxdock/cli/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ def get_project(base_dir='.'):
# Initializes the client instance that will be used to orchestrate containers.
client = get_client()

return Project.from_config(project_name, os.path.abspath(base_dir), client, config)
return Project.from_config(project_name, client, config)
32 changes: 20 additions & 12 deletions lxdock/conf/config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
import os
from pathlib import Path

import yaml
from voluptuous.error import Invalid
Expand All @@ -14,8 +15,8 @@
class Config(object):
""" Holds the configuration of a LXDock project. """

def __init__(self, base_dir, filename):
self.base_dir = base_dir
def __init__(self, homedir, filename):
self.homedir = homedir
self.filename = filename
self.containers = []
self._dict = {}
Expand All @@ -29,25 +30,32 @@ def __getitem__(self, key):
@classmethod
def from_base_dir(cls, base_dir='.'):
""" Returns a Config instance using a base directory. """
existing_config_filenames = [
filename for filename in constants.ALLOWED_FILENAMES
if os.path.exists(os.path.join(base_dir, filename))]

if not existing_config_filenames:
base_dir_path = Path(os.path.abspath(base_dir))
candidate_paths = [base_dir_path, ] + list(base_dir_path.parents)
existing_config_paths = []
for candidate_path in candidate_paths:
existing_config_paths = [
os.path.join(str(candidate_path), filename)
for filename in constants.ALLOWED_FILENAMES
if os.path.exists(os.path.join(str(candidate_path), filename))]
if existing_config_paths:
break

if not existing_config_paths:
raise ConfigFileNotFoundError(
'Unable to find a suitable configuration file in this directory. '
'Are you in the right directory?\n'
'The supported filenames are: {}'.format(', '.join(constants.ALLOWED_FILENAMES))
)

config_filename = os.path.join(base_dir, existing_config_filenames[0])
if len(existing_config_filenames) > 1:
config_dirname, config_filename = os.path.split(existing_config_paths[0])
if len(existing_config_paths) > 1:
logger.warn('Multiple config files were found: {0}'.format(
', '.join(existing_config_filenames)))
', '.join([os.path.split(p)[1] for p in existing_config_paths])))
logger.warn('Using: {0}'.format(config_filename))

# Initializes the config instance.
config = cls(base_dir, config_filename)
config = cls(config_dirname, config_filename)

# Loads the YML.
config.load()
Expand Down Expand Up @@ -103,7 +111,7 @@ def _get_container_config_dict(self, container_dict):

def _load_yml(self):
""" Loads the YML configuration file. """
with open(self.filename, 'r') as fp:
with open(os.path.join(self.homedir, self.filename), 'r') as fp:
return yaml.safe_load(fp)
# TODO: handle potential errors here

Expand Down
2 changes: 1 addition & 1 deletion lxdock/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def provision(self, barebone=None):
provisioning_type = provisioning_item['type'].lower()
provisioner_class = Provisioner.provisioners.get(provisioning_type)
if provisioner_class is not None:
provisioner = provisioner_class(self._container, provisioning_item)
provisioner = provisioner_class(self.homedir, self._container, provisioning_item)
logger.info('Provisioning with {0}'.format(provisioning_item['type']))
provisioner.provision()

Expand Down
6 changes: 3 additions & 3 deletions lxdock/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ def __init__(self, name, homedir, client, containers):
self.containers = containers

@classmethod
def from_config(cls, project_name, homedir, client, config):
def from_config(cls, project_name, client, config):
""" Creates a `Project` instance from a config object. """
containers = []
for container_config in config.containers:
containers.append(Container(project_name, homedir, client, **container_config))
return cls(project_name, homedir, client, containers)
containers.append(Container(project_name, config.homedir, client, **container_config))
return cls(project_name, config.homedir, client, containers)

#####################
# CONTAINER ACTIONS #
Expand Down
3 changes: 2 additions & 1 deletion lxdock/provisioners/ansible.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import os
import subprocess
import tempfile

Expand All @@ -21,7 +22,7 @@ def provision(self):
tmpinv.write('{} ansible_user=root'.format(ip).encode('ascii'))
tmpinv.flush()
cmd = 'ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i {} {}'.format(
tmpinv.name, self.options['playbook'])
tmpinv.name, os.path.join(self.homedir, self.options['playbook']))
logger.debug(cmd)
p = subprocess.Popen(cmd, shell=True)
p.wait()
3 changes: 2 additions & 1 deletion lxdock/provisioners/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class Provisioner(with_metaclass(_ProvisionerBase)):
# subclasses.
name = None

def __init__(self, lxd_container, options):
def __init__(self, homedir, lxd_container, options):
self.homedir = homedir
self.lxd_container = lxd_container
self.options = options.copy()

Expand Down
Empty file.
12 changes: 11 additions & 1 deletion tests/unit/conf/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,17 @@ def test_can_be_initialized_from_a_base_dir(self):
def test_works_if_multiple_config_files_are_found(self):
project_dir = os.path.join(FIXTURE_ROOT, 'project_with_multiple_config_files')
config = Config.from_base_dir(project_dir)
assert config.filename == os.path.join(project_dir, 'lxdock.yml')
assert config.homedir == project_dir
assert config.filename == 'lxdock.yml'

def test_can_find_a_config_file_from_a_project_subdirectory(self):
project_dir = os.path.join(FIXTURE_ROOT, 'project01', 'subdir')
config = Config.from_base_dir(project_dir)
assert config.homedir == os.path.join(FIXTURE_ROOT, 'project01')
assert config.filename == 'lxdock.yml'
assert config['name'] == 'project01'
assert config['image'] == 'ubuntu/xenial'
assert config['mode'] == 'pull'

def test_raises_an_error_if_the_config_file_cannot_be_found(self):
project_dir = os.path.dirname(__file__)
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/provisioners/test_ansible.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def write(self, data):
lxd_state.network.__getitem__ = unittest.mock.MagicMock(
return_value={'addresses': [{'family': 'init', 'address': '0.0.0.0', }, ]})
lxd_container.state.return_value = lxd_state
provisioner = AnsibleProvisioner(lxd_container, {'playbook': 'deploy.yml'})
provisioner = AnsibleProvisioner('./', lxd_container, {'playbook': 'deploy.yml'})
provisioner.provision()
assert mock_popen.call_args[0] == (
'ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i tmpfile deploy.yml', )
'ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i tmpfile ./deploy.yml', )

0 comments on commit 3e1a218

Please sign in to comment.