Plugin architecture working

This commit is contained in:
Anders Ingemann 2013-05-16 08:00:28 +02:00
parent 4dbdb387cd
commit e63e2cca0c
21 changed files with 135 additions and 88 deletions

6
build-debian-cloud Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/env python
if __name__ == '__main__' and __package__ is None:
from common import main
main.main()

View file

@ -2,3 +2,4 @@ from bootstrapinfo import BootstrapInformation
from manifest import Manifest
from task import Task
from tasklist import TaskList
from plugin import Plugin

31
common/main.py Normal file
View file

@ -0,0 +1,31 @@
from providers import providers
def main():
from argparse import ArgumentParser
parser = ArgumentParser(description='Bootstrap Debian for the cloud.')
parser.add_argument('--debug', action='store_true',
help='Print debugging information')
parser.set_defaults(func=run)
subparsers = parser.add_subparsers(title='providers', description='supported providers', dest='provider')
for provider in providers.values():
provider.init_subparser(subparsers)
args = parser.parse_args()
args.func(args)
def run(args):
provider = providers[args.provider]
manifest = provider.Manifest(args.manifest)
manifest.validate()
manifest.load_plugins()
tasklist = provider.tasklist(manifest)
tasklist.plugins(manifest)
from common import BootstrapInformation
bootstrap_info = BootstrapInformation(manifest, args)
tasklist.run(bootstrap_info)

View file

@ -9,6 +9,14 @@ class Manifest(object):
def parse(self, data):
self.volume = data['volume']
self.system = data['system']
self.plugins = data['plugins']
def validate(self):
pass
def load_plugins(self):
self.loaded_plugins = []
for modname in self.plugins.keys():
if self.plugins[modname]['enabled']:
plugin = __import__('plugins.%s' % modname, fromlist=['plugins'])
self.loaded_plugins.append(plugin)

View file

@ -1,15 +1,24 @@
class TaskList(list):
def run(self, info):
def plugins(self, manifest):
for plugin in manifest.loaded_plugins:
plugin.modify_tasklist(self, manifest)
def run(self, bootstrap_info):
for task in self:
task.run(info)
task.run(bootstrap_info)
def before(self, task):
pass
def before(self, ref, task):
i = next(i for i, task in enumerate(self) if type(task) is ref)
self.insert(i, task)
def replace(self, task):
pass
def replace(self, ref, task):
i = next(i for i, task in enumerate(self) if type(task) is ref)
self.pop(i)
self.insert(i, task)
def after(self, task):
pass
def after(self, ref, task):
i = next(i for i, task in enumerate(self) if type(task) is ref)
self.insert(i+1, task)

View file

@ -1,18 +0,0 @@
#!/usr/bin/env python
def main():
from argparse import ArgumentParser
import ec2
parser = ArgumentParser(description='Bootstrap Debian for the cloud.')
parser.add_argument('--debug', action='store_true',
help='Print debugging information')
subparsers = parser.add_subparsers(title='providers', description='supported providers', dest='provider')
ec2.init_subparser(subparsers)
args = parser.parse_args()
args.func(args)
if __name__ == '__main__' and __package__ is None:
main()

View file

@ -1 +0,0 @@
from main import init_subparser

View file

@ -1,37 +0,0 @@
def init_subparser(subparsers):
cmd = subparsers.add_parser('ec2', help='Bootstrap Debian for EC2')
cmd.add_argument('--access-key', help='AWS Access Key', metavar='ID')
cmd.add_argument('--secret-key', help='AWS Secret Key', metavar='KEY')
cmd.add_argument('manifest', help='Manifest file to use for bootstrapping', metavar='MANIFEST')
cmd.set_defaults(func=run)
def run(args):
from manifest import Manifest
from common import BootstrapInformation
manifest = Manifest(args.manifest)
manifest.validate()
task_list = get_tasklist(manifest)
info = BootstrapInformation(manifest=manifest, args=args)
task_list.run(info)
def get_tasklist(manifest):
from common import TaskList
import packages
import ec2
import host
task_list = TaskList()
task_list.extend([packages.HostPackages(),
packages.ImagePackages(),
ec2.GetCredentials(),
host.GetInfo(),
ec2.Connect(),
host.InstallPackages()
])
return task_list

View file

@ -25,11 +25,11 @@
"size" : "1G"
},
"plugins": {
"admin-user": {
"admin_user": {
"enabled": true
},
"build-metadata": {
"enabled": false,
"build_metadata": {
"enabled": true,
"path" : "/root/build-metadata-{ami_name}"
}
}

0
plugins/__init__.py Normal file
View file

View file

@ -0,0 +1,6 @@
def modify_tasklist(tasklist, manifest):
from providers.ec2.packages import ImagePackages
from adminuser import AddSudoPackage
tasklist.after(ImagePackages, AddSudoPackage())

View file

@ -0,0 +1,7 @@
from common import Task
class AddSudoPackage(Task):
def run(self, info):
super(AddSudoPackage, self).run(info)
info.img_packages[0].add('sudo')

View file

@ -0,0 +1,5 @@
def modify_tasklist(tasklist, manifest):
from buildmetadata import PrintInfo
tasklist.append(PrintInfo())

View file

@ -0,0 +1,7 @@
from common import Task
class PrintInfo(Task):
def run(self, info):
super(PrintInfo, self).run(info)
print('info')

4
providers/__init__.py Normal file
View file

@ -0,0 +1,4 @@
import ec2
providers = {'ec2': ec2}

25
providers/ec2/__init__.py Normal file
View file

@ -0,0 +1,25 @@
from manifest import Manifest
def init_subparser(subparsers):
sub = subparsers.add_parser('ec2', help='Bootstrap Debian for EC2')
sub.add_argument('--access-key', help='AWS Access Key', metavar='ID')
sub.add_argument('--secret-key', help='AWS Secret Key', metavar='KEY')
sub.add_argument('manifest', help='Manifest file to use for bootstrapping', metavar='MANIFEST')
def tasklist(manifest):
from common import TaskList
import packages
import ec2
import host
task_list = TaskList()
task_list.extend([packages.HostPackages(),
packages.ImagePackages(),
ec2.GetCredentials(),
host.GetInfo(),
ec2.Connect(),
host.InstallPackages()
])
return task_list

View file

@ -5,7 +5,6 @@ class GetCredentials(Task):
def run(self, info):
super(GetCredentials, self).run(info)
info.ec2_credentials = self.get_ec2_credentials(info.args, info.manifest)
return info
def get_ec2_credentials(self, args, manifest):
from os import getenv
@ -37,4 +36,4 @@ class Connect(Task):
# info.ec2_connection = boto.ec2.connect_to_region(info.host['region'],
# aws_access_key_id=info.ec2_credentials['access_key'],
# aws_secret_access_key=info.ec2_credentials['secret_key'])
return info
# return 'ec2_connection', ec2_connection

View file

@ -4,13 +4,15 @@ from common import Task
class GetInfo(Task):
def run(self, info):
super(GetInfo, self).run(info)
import urllib2
import json
# import urllib2
# import json
# response = urllib2.urlopen('http://169.254.169.254/latest/dynamic/instance-identity/document')
# info.host = json.load(response.read())
return info
# return info
class InstallPackages(Task):
def run(self, info):
# Check if packages are installed with
# /usr/bin/dpkg -s ${name} | grep -q 'Status: install'
pass

View file

@ -4,27 +4,20 @@ from common import Task
class HostPackages(Task):
def run(self, info):
super(HostPackages, self).run(info)
info.host_pkg = self.get_host_packages(info.manifest)
return info
def get_host_packages(self, manifest):
packages = set(['debootstrap',
# To make sure a volume is not busy before unmounting we need lsof
'lsof',
])
if manifest.volume['filesystem'] == 'xfs':
if info.manifest.volume['filesystem'] == 'xfs':
packages.add('xfsprogs')
return packages
info.host_packages = packages
class ImagePackages(Task):
def run(self, info):
super(ImagePackages, self).run(info)
info.image_pkg_include, info.image_pkg_exclude = self.get_image_packages(info.manifest)
return info
def get_image_packages(self, manifest):
manifest = info.manifest
# Add some basic packages we are going to need
include = set(['udev',
'openssh-server',
@ -52,4 +45,4 @@ class ImagePackages(Task):
include = include.union(manifest.system['packages'])
return include, exclude
info.img_packages = include, exclude