Skip to content

Commit

Permalink
Refactor installer [3/3] -- hardcode default
Browse files Browse the repository at this point in the history
* added comments to main installer class to describe what the
  important statements do
* ALL the relations between input parameters (their names) and
  validation classes are defined in parameters/__init__.py; no
  more looking in different places.
  Is there validation for a specific input? This file holds the anser!
  Do you want to add validation for another paramter? Do it there!
  • Loading branch information
martin-bts committed Oct 10, 2019
1 parent cd6dca4 commit d967fa5
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 43 deletions.
24 changes: 21 additions & 3 deletions askbot/deployment/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from askbot.utils.functions import generate_random_key
from askbot.deployment.template_loader import DeploymentTemplate
from askbot.deployment.parameters import ConfigManagerCollection
from askbot.deployment.common.base import ObjectWithOutput
from askbot.deployment.base import ObjectWithOutput
from askbot.deployment.deployables.components import DeployableComponent
import askbot.deployment.deployables as deployable

Expand Down Expand Up @@ -285,17 +285,30 @@ def __call__(self): # this is the main part of the original askbot_setup()
nothing = DeployableComponent()
nothing.deploy = lambda: None

# install into options['dir_name']
project = deployable.ProjectRoot(options['dir_name'])

# select where to look for source files and templates
project.src_dir = os.path.join(self.ASKBOT_ROOT, self.SOURCE_DIR)

# set log dir an log file
project.contents.update({
options['logdir_name']: {options['logfile_name']: deployable.EmptyFile}
})

# set the directory where settings.py etc. go, defaults to
site = deployable.AskbotSite(options['app_name'])
site.src_dir = os.path.join(self.ASKBOT_ROOT, self.SOURCE_DIR)

# install as a sub-directory to the intall directory
site.dst_dir = options['dir_name']

# select where to look for source files and templates
site.src_dir = os.path.join(self.ASKBOT_ROOT, self.SOURCE_DIR)

# use user provided paramters to render files
site.context.update(options)

# install container specifics, analogous to site
uwsgi = deployable.AskbotApp()
uwsgi.src_dir = os.path.join(self.ASKBOT_ROOT, self.SOURCE_DIR)
uwsgi.dst_dir = options['dir_name']
Expand All @@ -304,26 +317,31 @@ def __call__(self): # this is the main part of the original askbot_setup()
'askbot_app': uwsgi.name, # defaults to askbot_app
})

# put the path to settings.py into manage.py
project.context = {'settings_path': f'{site.name}.settings'}

todo = [ project, site ]

if options['create_project'] in ['no', 'none', 'false', '0', 'nothing']:
todo = [ nothing ]
todo = [ nothing ] # undocumented noop for the installer
elif options['create_project'] == 'container-uwsgi':
# if we install into a container we additionally want these files
project.contents.update({
'cron': {
'crontab': deployable.RenderedFile, # askbot_site, askbot_app
'cron-askbot.sh': deployable.CopiedFile,
}})
todo.append(uwsgi)

# maybe we could just use the noop nothing instead of this?
if options['dry_run']:
raise StopIteration

# install askbot
for component in todo:
component.deploy()

# the happily ever after section for successful deployments
help_file = path_utils.get_path_to_help_file()

self.print(messages.HOW_TO_DEPLOY_NEW % {'help_file': help_file})
Expand Down
109 changes: 69 additions & 40 deletions askbot/deployment/parameters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,69 @@
from askbot.deployment.parameters.base import ConfigManager
from askbot.deployment.parameters.cache import CacheConfigManager
from askbot.deployment.parameters.database import DbConfigManager
from askbot.deployment.parameters.filesystem import FilesystemConfigManager

# one could make a case for not deriving ConfigManagerCollection from
# ConfigManager because the collection serves a different purpose than the
# individual manager, but they are still quite similar
class ConfigManagerCollection(ConfigManager):
"""
This is the main config manager that will be used by the Askbot installer.
It is a hard coded ordered collection of all config managers the installer
shall use.
"""
def __init__(self, interactive=False, verbosity=0):
super(ConfigManagerCollection, self).__init__(interactive=interactive, verbosity=verbosity)
self.register('database', DbConfigManager(interactive=interactive, verbosity=verbosity))
self.register('cache', CacheConfigManager(interactive=interactive, verbosity=verbosity))
self.register('filesystem', FilesystemConfigManager(interactive=interactive, verbosity=verbosity))

def _order(self, keys):
full_set = ['filesystem', 'database', 'cache']
return [item for item in full_set if item in keys]

def configManager(self, name):
return super(ConfigManagerCollection, self).configField(name)

def complete(self, *args, **kwargs):
for manager in self._order(self.keys):
handler = self.configManager(manager)
handler.complete(*args, **kwargs)

# these should never be called. we keep these, just in case
def _remember(self, name, value):
raise NotImplementedError(f'Not implemented in {self.__class__.__name__}.')

def _complete(self, name, value):
raise NotImplementedError(f'Not implemented in {self.__class__.__name__}.')

__all__ = [ 'DbConfigManager', 'CacheConfigManager', 'FilesystemConfigManager', 'ConfigManagerCollection']
from askbot.deployment.base import ConfigManagerCollection, ConfigManager
from .configmanagers import CacheConfigManager, DbConfigManager

from .cache import *
from .database import *
from .filesystem import *

"""
In this module we assemble the input validation capabilities for the Askbot
installer.
The goal is to provide a single ConfigManagerCollection instance
(currently named askbotCollection), the installer will use to validate its
parameters.
The idea is askbotCollection will be able to validate just the
parameters that are register()-ed in this module/file. First we create the
collection and managers. Then we register() all the parameters for which we
want validation.
The validation implementations vary in complexity. Therefore, all
implementations are defined in derived classes in submodules, structured by
their topic, e.g. cache, database and filesystem. Here, at this level, we
import all classes and use register() as a mapping from parameter name, to
validation implementation.
The parameter names must match the argpare argument destinations, i.e. the
`dest` argument to ArgumentParser.add_argument(), do be effective.
THE ORDER IN WHICH VALIDATIONS ARE register()-ed WITH THEIR ConfigManagers
MATTERS!
"""

# use these values while inizializing this module
interactive=False
verbosity=0

# the ConfigManagerCollection the installer will use
askbotCollection = ConfigManagerCollection(interactive=interactive, verbosity=verbosity)

# the ConfigManagers the installer will use
cacheManager = CacheConfigManager(interactive=interactive, verbosity=verbosity)
databaseManager = DbConfigManager(interactive=interactive, verbosity=verbosity)
filesystemManager = ConfigManager(interactive=interactive, verbosity=verbosity)

# register the ConfigManagers with the ConfigManagerCollection
askbotCollection.register('filesystem', filesystemManager)
askbotCollection.register('database', databaseManager)
askbotCollection.register('cache', cacheManager)

# register parameters with config managers. THE ORDERING MATTERS!
cacheManager.register('cache_engine', CacheEngine())
cacheManager.register('cache_nodes', CacheNodes())
cacheManager.register('cache_db', CacheDb())
cacheManager.register('cache_password', CachePass())

databaseManager.register('database_engine', DbEngine())
databaseManager.register('database_name', DbName())
databaseManager.register('database_user', DbUser())
databaseManager.register('database_password', DbPass())
databaseManager.register('database_host', DbHost())
databaseManager.register('database_port', DbPort())

filesystemManager.register('dir_name', ProjectDirName())
filesystemManager.register('app_name', AppDirName())
filesystemManager.register('logfile_name', LogfileName())


__all__ = ['askbotCollection', 'cacheManager', 'databaseManager', 'filesystemManager']

0 comments on commit d967fa5

Please sign in to comment.