mirror of
https://github.com/kevingruesser/bootstrap-vz.git
synced 2025-08-22 09:50:37 +00:00
Manifest validation, simplified main run fn
This commit is contained in:
parent
a8364fe04d
commit
5689b77011
11 changed files with 113 additions and 46 deletions
|
@ -44,13 +44,7 @@ def setup_logger(args):
|
|||
|
||||
def run(args):
|
||||
from manifest import load_manifest
|
||||
from manifest import get_provider
|
||||
data = load_manifest(args.manifest)
|
||||
provider = get_provider(data)
|
||||
manifest = provider.Manifest(args.manifest, data)
|
||||
|
||||
manifest.validate()
|
||||
manifest.load_plugins()
|
||||
(provider, manifest) = load_manifest(args.manifest)
|
||||
|
||||
from tasklist import TaskList
|
||||
tasklist = TaskList()
|
||||
|
|
|
@ -3,19 +3,33 @@ log = logging.getLogger(__name__)
|
|||
|
||||
|
||||
def load_manifest(path):
|
||||
import json
|
||||
return json.load(open(path))
|
||||
from json import load
|
||||
data = load(open(path))
|
||||
|
||||
|
||||
def get_provider(data):
|
||||
provider = __import__('providers.{module}'.format(module=data['provider']), fromlist=['providers'])
|
||||
return provider
|
||||
manifest = provider.Manifest(path)
|
||||
|
||||
manifest.validate(data)
|
||||
manifest.parse(data)
|
||||
manifest.load_plugins()
|
||||
return (provider, manifest)
|
||||
|
||||
class Manifest(object):
|
||||
def __init__(self, path, data):
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
self.parse(data)
|
||||
|
||||
def validate(self, data, schema_path=None):
|
||||
if schema_path is not None:
|
||||
from json import load
|
||||
from json_schema_validator.validator import Validator
|
||||
from json_schema_validator.schema import Schema
|
||||
from json_schema_validator.errors import ValidationError
|
||||
schema = Schema(load(open(schema_path)))
|
||||
try:
|
||||
Validator.validate(schema, data)
|
||||
except ValidationError as e:
|
||||
from common.exceptions import ManifestError
|
||||
raise ManifestError(e.message, self)
|
||||
|
||||
def parse(self, data):
|
||||
self.provider = data['provider']
|
||||
|
@ -23,9 +37,6 @@ class Manifest(object):
|
|||
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():
|
||||
|
|
1
common/__init__.py
Normal file
1
common/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
from exceptions import *
|
9
common/exceptions.py
Normal file
9
common/exceptions.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
__all__ = ['ManifestError']
|
||||
|
||||
|
||||
class ManifestError(Exception):
|
||||
def __init__(self, message, manifest):
|
||||
self.message = message
|
||||
self.manifest = manifest
|
||||
def __str__(self):
|
||||
return "Error in `manifest' {0}: {1}".format(self.manifest.path, self.message)
|
|
@ -22,7 +22,7 @@
|
|||
"volume": {
|
||||
"backing" : "ebs",
|
||||
"filesystem": "ext4",
|
||||
"size" : "1G"
|
||||
"size" : 1
|
||||
},
|
||||
"plugins": {
|
||||
"admin_user": {
|
||||
|
|
|
@ -5,10 +5,12 @@ def modify_tasklist(tasklist, manifest):
|
|||
from tasks import packages
|
||||
from tasks import ec2
|
||||
from tasks import host
|
||||
from tasks import ebs
|
||||
tasklist.extend([packages.HostPackages(),
|
||||
packages.ImagePackages(),
|
||||
host.CheckPackages(),
|
||||
ec2.GetCredentials(),
|
||||
host.GetInfo(),
|
||||
ec2.Connect(),
|
||||
host.InstallPackages()
|
||||
ebs.CreateVolume(),
|
||||
])
|
||||
|
|
20
providers/ec2/manifest-schema.json
Normal file
20
providers/ec2/manifest-schema.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"title": "EC2 manifest",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bootstrapdir": {
|
||||
"type": "string"
|
||||
},
|
||||
"volume": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"backing": {
|
||||
"type": "string",
|
||||
"enum": ["ebs", "s3"]
|
||||
}
|
||||
},
|
||||
"required": ["backing"]
|
||||
}
|
||||
},
|
||||
"required": ["bootstrapdir", "volume"]
|
||||
}
|
|
@ -2,10 +2,13 @@ import base
|
|||
|
||||
|
||||
class Manifest(base.Manifest):
|
||||
def validate(self, data):
|
||||
from os import path
|
||||
schema_path = path.normpath(path.join(path.dirname(__file__), 'manifest-schema.json'))
|
||||
super(Manifest, self).validate(data, schema_path)
|
||||
|
||||
def parse(self, data):
|
||||
super(Manifest, self).parse(data)
|
||||
self.credentials = data["credentials"]
|
||||
self.virtualization = data["virtualization"]
|
||||
|
||||
def validate(self):
|
||||
super(Manifest, self).validate()
|
||||
self.credentials = data['credentials']
|
||||
self.virtualization = data['virtualization']
|
||||
self.volume = data['volume']
|
||||
|
|
21
providers/ec2/tasks/ebs.py
Normal file
21
providers/ec2/tasks/ebs.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from base import Task
|
||||
|
||||
|
||||
class CreateVolume(Task):
|
||||
description = 'Creating an EBS volume for bootstrapping'
|
||||
|
||||
def run(self, info):
|
||||
# info.conn.create_volume(50, "us-west-2")
|
||||
# volume_id=`euca-create-volume --size $volume_size --zone "$availability_zone" | awk '{print $2}'`
|
||||
# [ -z "$volume_id" ] && die "Unable to create volume."
|
||||
# log "The EBS volume id is $volume_id"
|
||||
|
||||
# for package in info.host_packages:
|
||||
# try:
|
||||
# with open(devnull, 'w') as dev_null:
|
||||
# subprocess.check_call(['/usr/bin/dpkg', '-s', package], stdout=dev_null, stderr=dev_null)
|
||||
# except subprocess.CalledProcessError:
|
||||
# msg = "The package ``{0}\'\' is not installed".format(package)
|
||||
# raise RuntimeError(msg)
|
||||
pass
|
||||
|
|
@ -6,9 +6,9 @@ class GetCredentials(Task):
|
|||
|
||||
def run(self, info):
|
||||
super(GetCredentials, self).run(info)
|
||||
info.ec2_credentials = self.get_ec2_credentials(info.manifest)
|
||||
info.credentials = self.get_credentials(info.manifest)
|
||||
|
||||
def get_ec2_credentials(self, manifest):
|
||||
def get_credentials(self, manifest):
|
||||
from os import getenv
|
||||
# manifest overrides environment
|
||||
if(manifest.credentials['access-key'] and manifest.credentials['secret-key']):
|
||||
|
@ -31,8 +31,7 @@ class Connect(Task):
|
|||
|
||||
def run(self, info):
|
||||
super(Connect, self).run(info)
|
||||
# import boto.ec2
|
||||
# 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 'ec2_connection', ec2_connection
|
||||
from boto.ec2 import connect_to_region
|
||||
info.connection = connect_to_region(info.host['region'],
|
||||
aws_access_key_id=info.credentials['access_key'],
|
||||
aws_secret_access_key=info.credentials['secret_key'])
|
||||
|
|
|
@ -1,22 +1,29 @@
|
|||
from base import Task
|
||||
|
||||
|
||||
class CheckPackages(Task):
|
||||
description = 'Checking installed host packages'
|
||||
|
||||
def run(self, info):
|
||||
import subprocess
|
||||
from os import devnull
|
||||
for package in info.host_packages:
|
||||
try:
|
||||
with open(devnull, 'w') as dev_null:
|
||||
subprocess.check_call(['/usr/bin/dpkg', '-s', package], stdout=dev_null, stderr=dev_null)
|
||||
except subprocess.CalledProcessError:
|
||||
msg = "The package ``{0}\'\' is not installed".format(package)
|
||||
raise RuntimeError(msg)
|
||||
|
||||
|
||||
class GetInfo(Task):
|
||||
description = 'Retrieving host information'
|
||||
description = 'Retrieving instance metadata'
|
||||
|
||||
def run(self, info):
|
||||
super(GetInfo, self).run(info)
|
||||
# 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
|
||||
|
||||
|
||||
class InstallPackages(Task):
|
||||
description = 'Installing host packages'
|
||||
|
||||
def run(self, info):
|
||||
# Check if packages are installed with
|
||||
# /usr/bin/dpkg -s ${name} | grep -q 'Status: install'
|
||||
pass
|
||||
import urllib2
|
||||
import json
|
||||
metadata_url = 'http://169.254.169.254/latest/dynamic/instance-identity/document'
|
||||
response = urllib2.urlopen(url=metadata_url, timeout=5)
|
||||
info.host = json.load(response)
|
||||
return info
|
||||
|
|
Loading…
Add table
Reference in a new issue