Initialize fuel_plugin_builder project

This commit is contained in:
Evgeniy L 2014-10-13 16:19:00 +04:00
parent 4a4b59a0b6
commit ac4a7f7a28
14 changed files with 504 additions and 0 deletions

View File

@ -0,0 +1,13 @@
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

View File

@ -0,0 +1,18 @@
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from fuel_plugin_builder.actions.base import BaseAction
from fuel_plugin_builder.actions.create import CreatePlugin
from fuel_plugin_builder.actions.build import BuildPlugin

View File

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class BaseAction(object):
@abc.abstractmethod
def check(self):
"""Check if it's possible to perform an action.
"""
@abc.abstractmethod
def run(self):
"""Run an action.
"""

View File

@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import logging
from fuel_plugin_builder import utils
from fuel_plugin_builder import errors
from fuel_plugin_builder.actions import BaseAction
logger = logging.getLogger(__name__)
class BuildPlugin(BaseAction):
requires = ['rpm', 'createrepo', 'dpkg-scanpackages']
def __init__(self, plugin_path):
self.plugin_path = plugin_path
self.pre_build_hook_path = os.path.join(plugin_path, 'pre_build_hook')
self.centos_repo_path = os.path.join(plugin_path, 'repos/centos')
self.ubuntu_repo_path = os.path.join(plugin_path, 'repos/ubuntu')
def run(self):
if utils.which(self.pre_build_hook_path):
utils.exec_cmd(self.pre_build_hook_path)
utils.exec_cmd(
'createrepo -o {0} {1}'.format(
os.path.join(self.centos_repo_path, 'x86_64'),
os.path.join(self.centos_repo_path, 'x86_64', 'Packages')))
utils.exec_cmd(
'dpkg-scanpackages {0} | gzip -c9 > {1}'.format(
self.ubuntu_repo_path,
os.path.join(self.ubuntu_repo_path, 'Packages.gz')))
def check(self):
not_found = filter(lambda r: not utils.which(r), self.requires)
if not_found:
raise errors.FuelCannotFindCommandError(
'Cannot find commands "{0}", '
'install required commands and try again'.format(
','.join(not_found)))

View File

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
from fuel_plugin_builder.actions import BaseAction
logger = logging.getLogger(__name__)
class CreatePlugin(BaseAction):
def __init__(self, plugin_name):
self.plugin_name = plugin_name
def check(self):
pass
def run(self):
pass

View File

@ -0,0 +1,83 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import sys
import argparse
from fuel_plugin_builder import actions
from fuel_plugin_builder import messages
from fuel_plugin_builder import errors
from fuel_plugin_builder.logger import configure_logger
logger = configure_logger()
def handle_exception(exc):
logger.exception(exc)
if isinstance(exc, errors.FuelCannotFindCommandError):
print(messages.header)
print(messages.install_required_packages)
sys.exit(-1)
def parse_args():
"""Parse arguments and return them
"""
parser = argparse.ArgumentParser(
description='fpb is a fuel plugin builder which '
'helps you create plugin for Fuel')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
'--create', help='create a plugin skeleton',
nargs=1, metavar='plugin_name')
group.add_argument(
'--build', help='build a plugin',
nargs=1, metavar='path_to_directory')
return parser.parse_args()
def perform_action(args):
"""Performs an action
:param args: argparse object
"""
if args.create:
plugin_name = args.create[0]
logger.debug('Start plugin creation "%s"', args.create)
action = actions.CreatePlugin(plugin_name)
elif args.build:
plugin_path = args.build[0]
logger.debug('Start plugin building "%s"', args.build)
action = actions.BuildPlugin(plugin_path)
action.check()
action.run()
def main():
"""Entry point
"""
try:
perform_action(parse_args())
except Exception as exc:
handle_exception(exc)

View File

@ -0,0 +1,25 @@
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
class FuelPluginException(Exception):
pass
class FuelCannotFindCommandError(Exception):
pass
class ExecutedErrorNonZeroExitCode(Exception):
pass

View File

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
import sys
def configure_logger():
logger = logging.getLogger('fuel_plugin_builder')
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
'%(asctime)s %(levelname)s %(process)d (%(module)s) %(message)s',
"%Y-%m-%d %H:%M:%S")
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.DEBUG)
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
return logger

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
header = '=' * 50
install_required_packages = """
Was not able to find required packages, try to run:
# sudo apt-get install createrepo rpm dpkg-dev
"""

View File

@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import logging
import subprocess
from fuel_plugin_builder import errors
logger = logging.getLogger(__name__)
def is_executable(file_path):
"""Checks if file executable
:param str file_path: path to the file
:returns: True if file is executable, False if is not
"""
return os.path.isfile(file_path) and os.access(file_path, os.X_OK)
def which(cmd):
"""Checks if file executable
:param str cmd: the name of the command or path
:returns: None if there is no such command,
if there is such command returns
the path to the command
"""
fpath, fname = os.path.split(cmd)
if fpath:
if is_executable(cmd):
return cmd
for path in os.environ['PATH'].split(os.pathsep):
path = path.strip('"')
exe_file = os.path.join(path, cmd)
if is_executable(exe_file):
return exe_file
return None
def exec_cmd(cmd):
"""Execute command with logging.
Ouput of stdout and stderr will be written
in log.
:param cmd: shell command
"""
logger.debug(u'Execute command "{0}"'.format(cmd))
child = subprocess.Popen(
cmd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell=True)
logger.debug(u'Stdout and stderr of command "{0}":'.format(cmd))
for line in child.stdout:
logger.debug(line.rstrip())
child.wait()
exit_code = child.returncode
if exit_code != 0:
raise errors.ExecutedErrorNonZeroExitCode(
u'Shell command executed with "{0}" '
'exit code: {1} '.format(exit_code, cmd))
logger.debug(u'Command "{0}" successfully executed'.format(cmd))

View File

@ -0,0 +1,2 @@
argparse==1.2.1
six==1.5.2

View File

@ -0,0 +1,49 @@
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import re
from setuptools import find_packages
from setuptools import setup
def find_requires():
dir_path = os.path.dirname(os.path.realpath(__file__))
requirements = []
with open(u'{0}/requirements.txt'.format(dir_path), 'r') as reqs:
requirements = reqs.readlines()
return requirements
setup(
name='fuel_plugin_builder',
version='0.1.0',
description='Helps to create and build fuel plugins',
long_description="""Helps to create and build fuel plugins""",
classifiers=[
"Programming Language :: Python",
"Topic :: System :: Software Distribution"],
author='Mirantis Inc.',
author_email='product@mirantis.com',
url='http://mirantis.com',
keywords='fuel plugins plugin',
packages=find_packages(),
zip_safe=False,
install_requires=find_requires(),
include_package_data=True,
package_data={'': ['templates/*']},
entry_points={
'console_scripts': [
'fpb = fuel_plugin_builder.cli:main']})

View File

@ -0,0 +1,6 @@
-r requirements.txt
hacking==0.7
mock==1.0
nose==1.1.2
nose2==0.4.1
nose-timer==0.2.0

View File

@ -0,0 +1,38 @@
[tox]
minversion = 1.6
skipsdist = True
envlist = py26,py27,pep8
[testenv]
usedevelop = True
install_command = pip install {packages}
setenv = VIRTUAL_ENV={envdir}
deps = -r{toxinidir}/test-requirements.txt
commands =
nosetests {posargs:fuel_plugin}
[tox:jenkins]
downloadcache = ~/cache/pip
[testenv:pep8]
deps = hacking==0.7
usedevelop = False
commands =
flake8 {posargs:.}
[testenv:venv]
commands = {posargs:}
[testenv:devenv]
envdir = devenv
usedevelop = True
[flake8]
ignore = H302,H802
exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build,tools,__init__.py,docs
show-pep8 = True
show-source = True
count = True
[hacking]
import_exceptions = testtools.matchers