From 92bcc48f97de2a66d5d2f9d8e5f6ef1c75e96708 Mon Sep 17 00:00:00 2001 From: Uggla Date: Sat, 27 Feb 2016 10:21:03 +0100 Subject: [PATCH 1/8] Fix installation of data_files 1- Get target prefix 2- if prefix == '/usr' --> Force configuration file location to /etc 3- else --> set file location relative to the prefix ex : prefix/bin, prefix/share, prefix/etc 4- Update conf file content with the template path location 5- Update script file content with version and configuration file location --- redfish-client/etc/redfish-client.conf | 2 +- redfish/__init__.py | 2 +- requirements.txt | 4 +- setup.cfg | 7 +- setup.py | 203 ++++++++++++++++++++++++- 5 files changed, 204 insertions(+), 14 deletions(-) diff --git a/redfish-client/etc/redfish-client.conf b/redfish-client/etc/redfish-client.conf index 89cd47b..b00df1e 100644 --- a/redfish-client/etc/redfish-client.conf +++ b/redfish-client/etc/redfish-client.conf @@ -1,2 +1,2 @@ [redfish-client] -templates_path = /usr/share/redfish-client/templates +templates_path = PBTEMPLATEPATH diff --git a/redfish/__init__.py b/redfish/__init__.py index ce09d8f..0a6657b 100644 --- a/redfish/__init__.py +++ b/redfish/__init__.py @@ -18,7 +18,7 @@ from redfish.main import * #import redfish.types try: - __version__ = pbr.version.VersionInfo('redfish').version_string() + __version__ = pbr.version.VersionInfo('redfish').release_string() except Exception, e: if "Versioning for this project requires either an sdist tarball" in e.message: pass diff --git a/requirements.txt b/requirements.txt index 6eecbba..fec375e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,9 +2,7 @@ # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. -pbr>=0.6,!=0.7,<1.0 -#oslo.log>=1.0,<2.0 -Babel>=1.3 +pbr>=0.8 tortilla>=0.4.1 Jinja2>=2.7.3 Sphinx>=1.2.3 diff --git a/setup.cfg b/setup.cfg index 08fbfd6..3ceb164 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,10 +27,9 @@ packages = scripts = redfish-client/redfish-client -data_files = - usr/share/redfish-client/templates = redfish-client/templates/* - etc/ = redfish-client/etc/* - +[data_files_helper] +conf = 'redfish-client/etc/redfish-client.conf', 'etc' +templates = 'redfish-client/templates/*', 'share/redfish-client/templates' [build_sphinx] source-dir = doc/source diff --git a/setup.py b/setup.py index 7363757..ee366de 100755 --- a/setup.py +++ b/setup.py @@ -1,21 +1,28 @@ #!/usr/bin/env python -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); +# 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, +# 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. # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT +import os +import sys +import fileinput +import re +import pprint +import distutils +import ConfigParser import setuptools +from setuptools import Distribution +from setuptools.command.install import install # In python < 2.7.4, a lazy loading of package `pbr` will break # setuptools if some other modules registered functions in `atexit`. @@ -25,6 +32,192 @@ try: except ImportError: pass + +class OnlyGetScriptPath(install): + '''Extend setuptools install class and replace run method to go through + setuptool installation and retrieve the script path + ''' + def run(self): + # does not call install.run() by design + self.distribution.install_scripts = self.install_scripts + + +class DataFilesHelper(): + '''Class to help manage data files''' + def __init__(self): + '''Read setup.cfg and build the required data''' + self.data = {} + self.setupstruc = [] + config = ConfigParser.ConfigParser() + config.read('setup.cfg') + for datafile in config.options('data_files_helper'): + src, dst = config.get('data_files_helper', datafile).split(',') + src = self.refinesrc(src) + dst = self.refinedst(dst) + self.data[datafile] = {'src': src, + 'dst': dst, + 'fdst': self.calculatedst(src, dst)} + self.update_setupstruc(src, dst) + try: + # Create an entry for scripts if available + src = config.get('files', 'scripts').split('\n') + src = [self.refinesrc(file)[0] for file in src if file] + self.data['script'] = {'src': src, + 'dst': 'bin', + 'fdst': self.calculatedst(src, 'bin')} + except ConfigParser.NoOptionError: + pass + pp = pprint.PrettyPrinter(indent=4) + pp.pprint(self.data) + + def trim(self, string): + string = string.strip() + string = string.strip("'") + string = string.strip('"') + return(string) + + def refinesrc(self, file): + '''Refine source: + Expend source file if needed + + :param file: source files + :type file: string + :returns: source files refined + :rtype: list + ''' + file = self.trim(file) + if(file.endswith('/*')): + return(self.getfiles(file.replace('/*', ''))) + else: + return([file]) + + def refinedst(self, file): + '''Refine destination: + Check if destination needs an exception + + :param file: destination + :type path: string + :returns: destination refined + :rtype: string + ''' + file = self.trim(file) + if('etc' in file and self.getprefix() == '/usr'): + return('/etc') + else: + return(file) + + def calculatedst(self, src, dst): + '''Calculate the full destination path accordind to source and + destination + + :param src: source files + :type path: list + :param dst: destination path + :type path: string + :returns: files with full destination + :rtype: list + ''' + destination = [] + for file in src: + if(dst.startswith('/')): + destination.append(os.path.join(dst, + os.path.basename(file))) + else: + destination.append(os.path.join(self.getprefix(), + dst, + os.path.basename(file))) + return(destination) + + def getfiles(self, path): + '''Retrieve file list within a directory + + :param path: directory path + :type path: string + :returns: file list + :rtype: list + ''' + for root, dirs, files in os.walk(path): + file_list = [os.path.join(root, file) for file in files] + return(file_list) + + def getprefix(self): + '''Retrieve setup tool calculated prefix + + :returns: prefix + :rtype: string + ''' + dist = Distribution({'cmdclass': {'install': OnlyGetScriptPath}}) + dist.dry_run = True # not sure if necessary, but to be safe + dist.parse_config_files() + try: + dist.parse_command_line() + except distutils.errors.DistutilsArgError: + pass + command = dist.get_command_obj('install') + command.ensure_finalized() + command.run() + prefix = dist.install_scripts.replace('/bin', '') + return prefix + + def update_setupstruc(self, src, dst): + '''Create/update structure for setuptools.setup() + like the following example. + + [('etc/', ['redfish-client/etc/redfish-client.conf']), + ('share/redfish-client/templates', + ['redfish-client/templates/manager_info.template', + 'redfish-client/templates/bla.template'])] + ''' + self.setupstruc.append((dst, src)) + + def getsetupstruc(self): + '''Retrieve setup structure compatible with setuptools.setup() + This is only to encapsulatate setupstruc property + + :returns: datafiles source and destination + :rtype: setuptools structure + ''' + return(self.setupstruc) + + +########################################## +# Functions +########################################## +def replaceAll(file, searchExp, replaceExp): + for line in fileinput.input(file, inplace=1): + if searchExp in line: + line = line.replace(searchExp, replaceExp) + sys.stdout.write(line) + + +def getversion(): + with open("python_redfish.egg-info/PKG-INFO", "r") as f: + output = f.read() + s = re.search(r'\nVersion:\s+(\S+)', output) + return(s.group(1)) + +########################################## +# START +########################################## + +datafiles = DataFilesHelper() + +# Install software setuptools.setup( setup_requires=['pbr'], - pbr=True) + pbr=True, + data_files=datafiles.getsetupstruc()) + + +if('install' in sys.argv): + # Update conf files + for file in datafiles.data['conf']['fdst']: + print('Update : {}'.format(file)) + replaceAll(file, 'PBTEMPLATEPATH', + os.path.dirname(datafiles.data['templates']['fdst'][0])) + # Update script files + for file in datafiles.data['script']['fdst']: + print('Update : {}'.format(file)) + replaceAll(file, 'PBCONFFILE', datafiles.data['conf']['fdst'][0]) + replaceAll(file, 'PBVER', getversion()) + From 60b6a8f77c10ea0dd732461bd46e5b5c77e8cf0f Mon Sep 17 00:00:00 2001 From: Uggla Date: Sat, 27 Feb 2016 10:21:58 +0100 Subject: [PATCH 2/8] Update documentation --- doc/source/installation.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/source/installation.rst b/doc/source/installation.rst index 2418b56..f39d78b 100644 --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -10,9 +10,11 @@ Use:: Pip will install : -1. The library and all dependencies into your site-packages directory -2. Redfish client master conf file into /etc/redfish_client.conf -3. Data file (templates) into /usr/share/redfish-client/templates +1. The library and all dependencies into prefix/lib/pythonX.Y/site-packages directory +2. Redfish client master conf file into prefix/etc/redfish_client.conf + Unless if prefix = '/usr', in that case force configuration file to be in /etc + +3. Data file (templates) into prefix/share/redfish-client/templates Point 2 and 3 above need root access to your system. If you don't have root access on your system, please follow `Using pip and virtualenv`_ section. @@ -55,7 +57,7 @@ Using the sources #. Follow `get the sources `_ section to retrieve the sources. #. Install from the source using:: - python setup.py install + python setup.py install --prefix="/usr/local" Using rpm package From 68f114dc711c8ecb470cec3b6c6d4ec25e103911 Mon Sep 17 00:00:00 2001 From: Uggla Date: Sat, 27 Feb 2016 18:15:09 +0100 Subject: [PATCH 3/8] Correct link --- redfish-client/rfclient.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redfish-client/rfclient.py b/redfish-client/rfclient.py index 338810b..f76cad2 120000 --- a/redfish-client/rfclient.py +++ b/redfish-client/rfclient.py @@ -1 +1 @@ -redfish-client.py \ No newline at end of file +redfish-client \ No newline at end of file From 3404767cdcbd6b4ad17dd5484bb79636daa96c3f Mon Sep 17 00:00:00 2001 From: Uggla Date: Sat, 27 Feb 2016 21:01:43 +0100 Subject: [PATCH 4/8] Review options for configuration files - Add --config or -c to specify the configuration file location. - Change --conf_file to --inventory or -i to manage managers. - Configuration file and version are macros replaced by installation process - Fix almost all PEP8 issues --- redfish-client/redfish-client | 154 +++++++++++++++++----------------- 1 file changed, 79 insertions(+), 75 deletions(-) diff --git a/redfish-client/redfish-client b/redfish-client/redfish-client index 377758f..98e5c77 100755 --- a/redfish-client/redfish-client +++ b/redfish-client/redfish-client @@ -17,14 +17,15 @@ redfish-client :: Options: - -h --help Show this screen. - --version Show version. - --conf_file FILE Configuration file [default: ~/.redfish.conf] - --insecure Ignore SSL certificates - --debug LEVEL Run in debug mode, LEVEL from 1 to 3 increase verbosity - Security warning LEVEL > 1 could reveal password into the logs - --debugfile FILE Specify the client debugfile [default: redfish-client.log] - --libdebugfile FILE Specify python-redfish library log file [default: /var/log/python-redfish/python-redfish.log] + -h --help Show this screen. + --version Show version. + -c --config FILE Configuration file + -i --inventory FILE Configuration file [default: $HOME/.redfish.conf] + --insecure Ignore SSL certificates + --debug LEVEL Run in debug mode, LEVEL from 1 to 3 increase verbosity + Security warning LEVEL > 1 could reveal password into the logs + --debugfile FILE Specify the client debugfile [default: redfish-client.log] + --libdebugfile FILE Specify python-redfish library log file [default: /var/log/python-redfish/python-redfish.log] config commands : manage the configuration file. manager commands : manage the manager (Ligh out management). If @@ -42,24 +43,25 @@ import jinja2 import requests.packages.urllib3 import redfish -class ConfigFile(object): - '''redfisht-client configuration file management''' - def __init__(self, config_file): - '''Initialize the configuration file + +class InventoryFile(object): + '''redfisht-client inventory file management''' + def __init__(self, inventory_file): + '''Initialize the inventory file Open and load configuration file data. If the file does not exist create an empty one ready to receive data - :param config_file: File name of the configuration file + :param inventory_file: File name of the configuration file default: ~/.redfish.conf :type config-file: str :returns: Nothing ''' - self._config_file = config_file + self._inventory_file = inventory_file # read json file try: - with open(self._config_file) as json_data: + with open(self._inventory_file) as json_data: self.data = json.load(json_data) json_data.close() except (ValueError, IOError): @@ -68,7 +70,7 @@ class ConfigFile(object): def save(self): '''Save the configuration file data''' try: - with open(self._config_file, 'w') as json_data: + with open(self._inventory_file, 'w') as json_data: json.dump(self.data, json_data) json_data.close() except IOError as e: @@ -141,7 +143,8 @@ class ConfigFile(object): self.manager_incorect(e) elif parameter == 'password': try: - self.data['Managers'][manager_name]['password'] = parameter_value + self.data['Managers'][manager_name]['password'] \ + = parameter_value except KeyError as e: self.manager_incorect(e) elif parameter == 'manager_name': @@ -209,7 +212,6 @@ class RedfishClientException(Exception): if __name__ == '__main__': '''Main application redfish-client''' # Functions - def show_manager(all=False): '''Display manager info @@ -219,16 +221,19 @@ if __name__ == '__main__': ''' print('Managers configured :') - for manager in conf_file.get_managers(): - print(manager) - if all is True: - info = conf_file.get_manager_info(manager) - print('\tUrl : {}'.format(info['url'])) - print('\tLogin : {}'.format(info['login'])) - print('\tPassword : {}'.format(info['password'])) + if(not inventory.get_managers()): + print("None") + else: + for manager in inventory.get_managers(): + print(manager) + if all is True: + info = inventory.get_manager_info(manager) + print('\tUrl : {}'.format(info['url'])) + print('\tLogin : {}'.format(info['login'])) + print('\tPassword : {}'.format(info['password'])) def get_manager_info(manager_name, check_SSL): - connection_parameters = conf_file.get_manager_info(manager_name) + connection_parameters = inventory.get_manager_info(manager_name) if not connection_parameters['login']: simulator = True enforceSSL = False @@ -252,18 +257,21 @@ if __name__ == '__main__': sys.stderr.write(str(e.advices)) sys.exit(1) - # Display manager information using jinja2 template + # Display manager information using jinja2 template try: template = jinja2_env.get_template("manager_info.template") except jinja2.exceptions.TemplateNotFound as e: - print('Template "{}" not found in {}.'.format(e.message, jinja2_env.loader.searchpath[0])) - logger.debug('Template "%s" not found in %s.' % (e.message, jinja2_env.loader.searchpath[0])) + print('Template "{}" not found in {}.' + .format(e.message, jinja2_env.loader.searchpath[0])) + logger.debug('Template "%s" not found in %s.' + % (e.message, jinja2_env.loader.searchpath[0])) sys.exit(1) - + print template.render(r=remote_mgmt) - + ################################################################# # Main program + ################################################################# redfishclient_version = "redfish-client PBVER" # Parse and manage arguments @@ -320,47 +328,43 @@ if __name__ == '__main__': logger.info("Arguments parsed") logger.debug(arguments) - # Get $HOME and $VIRTUAL_ENV environment variables. + # Get $HOME environment variables. HOME = os.getenv('HOME') - VIRTUAL_ENV = os.getenv('VIRTUAL_ENV') - if not HOME: + if(not HOME): print('$HOME environment variable not set, please check your system') logger.error('$HOME environment variable not set') sys.exit(1) logger.debug("Home directory : %s" % HOME) - - if VIRTUAL_ENV: - logger.debug("Virtual env : %s" % VIRTUAL_ENV) - - # Load master conf file - config = ConfigParser.ConfigParser(allow_no_value=True) - logger.debug("Read master configuration file") - master_conf_file_path = "/etc/redfish-client.conf" - - if VIRTUAL_ENV: - logger.debug("Read master configuration file from virtual environment") - master_conf_file_path = VIRTUAL_ENV + master_conf_file_path - - if not os.path.isfile(master_conf_file_path): - print('Master configuration file not found at {}.'.format(master_conf_file_path)) - logger.error('Master configuration file not found at %s.' % master_conf_file_path) - sys.exit(1) - - config.read(master_conf_file_path) - arguments['--conf_file'] = arguments['--conf_file'].replace('~', HOME) - conf_file = ConfigFile(arguments['--conf_file']) - + # Load config + config = ConfigParser.ConfigParser(allow_no_value=True) + logger.debug("Read configuration file") + configfile = 'PBCONFFILE' + + if(arguments['--config']): + configfile = [arguments['--config']] + logger.debug("Overwrite configuration specified by user at %s" + % configfile) + + if(os.path.isfile(configfile)): + logger.debug('Configuration found at %s.' % configfile) + config.read(configfile) + else: + print('Configuration file not found at {}.'.format(configfile)) + logger.error('Configuration file not found at %s.' % configfile) + sys.exit(1) + + arguments['--inventory'] = arguments['--inventory'].replace('~', HOME) + arguments['--inventory'] = arguments['--inventory'].replace('$HOME', HOME) + inventory = InventoryFile(arguments['--inventory']) + # Initialize Template system (jinja2) - # TODO : set the template file location into cmd line default to /usr/share/python-redfish/templates ? templates_path = config.get("redfish-client", "templates_path") logger.debug("Initialize template system") - if VIRTUAL_ENV: - logger.debug("Read templates file from virtual environment") - templates_path = VIRTUAL_ENV + templates_path - jinja2_env = jinja2.Environment(loader=jinja2.FileSystemLoader(templates_path)) - + jinja2_env = jinja2.Environment( + loader=jinja2.FileSystemLoader(templates_path)) + # Check cmd line parameters if arguments['config'] is True: logger.debug("Config commands") @@ -372,37 +376,37 @@ if __name__ == '__main__': show_manager(True) elif arguments['add'] is True: logger.debug('add command') - conf_file.add_manager(arguments[''], + inventory.add_manager(arguments[''], arguments[''], arguments[''], arguments['']) - logger.debug(conf_file.data) - conf_file.save() + logger.debug(inventory.data) + inventory.save() elif arguments['del'] is True: logger.debug('del command') - conf_file.delete_manager(arguments['']) - logger.debug(conf_file.data) - conf_file.save() + inventory.delete_manager(arguments['']) + logger.debug(inventory.data) + inventory.save() elif arguments['modify'] is True: logger.debug('modify command') if arguments['url'] is not False: - conf_file.modify_manager(arguments[''], + inventory.modify_manager(arguments[''], 'url', arguments['']) elif arguments['login'] is not False: - conf_file.modify_manager(arguments[''], + inventory.modify_manager(arguments[''], 'login', arguments['']) elif arguments['password'] is not False: - conf_file.modify_manager(arguments[''], + inventory.modify_manager(arguments[''], 'password', arguments['']) elif arguments['manager_name'] is not False: - conf_file.modify_manager(arguments[''], + inventory.modify_manager(arguments[''], 'manager_name', arguments['']) - logger.debug(conf_file.data) - conf_file.save() + logger.debug(inventory.data) + inventory.save() if arguments['manager'] is True: logger.debug("Manager commands") if arguments['getinfo'] is True: @@ -413,7 +417,7 @@ if __name__ == '__main__': else: manager_name = arguments[''] # Check if the default section is available in our conf file - conf_file.check_manager(manager_name) + inventory.check_manager(manager_name) if arguments['--insecure'] is True: get_manager_info(manager_name, False) else: From 096d58f25e4ed6d1bc62c744a01ff838e1e604b1 Mon Sep 17 00:00:00 2001 From: Uggla Date: Fri, 4 Mar 2016 11:59:08 +0100 Subject: [PATCH 5/8] Introduce client testing This is a first implementation probably a bit raw. So it needs improvement. Tests require: - docker available on host. - docker credentials to the user who is running the tests. Current tests: - Check docker socket - Check docker can be used by api. - Check source installation on Ubuntu, Debian, Fedora. - Check pip installation in Fedora. - Check if client can show an empty configuration. - Check client version format (basic). --- redfish-client/tests/Dockerfile.debian | 13 ++++ redfish-client/tests/Dockerfile.fedora | 11 +++ redfish-client/tests/Dockerfile.fedorapip | 7 ++ redfish-client/tests/Dockerfile.ubuntu | 13 ++++ redfish-client/tests/test_client.py | 89 +++++++++++++++++++++++ test-requirements.txt | 14 +--- 6 files changed, 137 insertions(+), 10 deletions(-) create mode 100644 redfish-client/tests/Dockerfile.debian create mode 100644 redfish-client/tests/Dockerfile.fedora create mode 100644 redfish-client/tests/Dockerfile.fedorapip create mode 100644 redfish-client/tests/Dockerfile.ubuntu create mode 100644 redfish-client/tests/test_client.py diff --git a/redfish-client/tests/Dockerfile.debian b/redfish-client/tests/Dockerfile.debian new file mode 100644 index 0000000..bb09658 --- /dev/null +++ b/redfish-client/tests/Dockerfile.debian @@ -0,0 +1,13 @@ +FROM debian:jessie +ENV DEBIAN_FRONTEND noninteractive +RUN apt-get update && \ +apt-get install -y apt-utils && \ +apt-get install -y python-pip +COPY python-redfish.src.tar.gz /python-redfish.src.tar.gz +RUN mkdir /var/log/python-redfish +RUN tar xvvf python-redfish.src.tar.gz +RUN cd python-redfish* && \ +pip install -r requirements.txt && \ +python setup.py install +CMD ["/bin/bash"] + diff --git a/redfish-client/tests/Dockerfile.fedora b/redfish-client/tests/Dockerfile.fedora new file mode 100644 index 0000000..4770d9f --- /dev/null +++ b/redfish-client/tests/Dockerfile.fedora @@ -0,0 +1,11 @@ +FROM fedora:23 +RUN dnf install -y python-pip && \ +dnf install -y git && \ +dnf install -y tar +COPY python-redfish.src.tar.gz /python-redfish.src.tar.gz +RUN mkdir /var/log/python-redfish +RUN tar xvvf python-redfish.src.tar.gz +RUN cd python-redfish* && \ +pip install -r requirements.txt && \ +python setup.py install +CMD ["/bin/bash"] diff --git a/redfish-client/tests/Dockerfile.fedorapip b/redfish-client/tests/Dockerfile.fedorapip new file mode 100644 index 0000000..dfb0cad --- /dev/null +++ b/redfish-client/tests/Dockerfile.fedorapip @@ -0,0 +1,7 @@ +FROM fedora:23 +RUN dnf install -y python-pip && \ +dnf install -y git +RUN mkdir /var/log/python-redfish +RUN pip install python-redfish +CMD ["/bin/bash"] + diff --git a/redfish-client/tests/Dockerfile.ubuntu b/redfish-client/tests/Dockerfile.ubuntu new file mode 100644 index 0000000..c77091c --- /dev/null +++ b/redfish-client/tests/Dockerfile.ubuntu @@ -0,0 +1,13 @@ +FROM ubuntu:wily +ENV DEBIAN_FRONTEND noninteractive +RUN apt-get update && \ +apt-get install -y apt-utils && \ +apt-get install -y python-pip +COPY python-redfish.src.tar.gz /python-redfish.src.tar.gz +RUN mkdir /var/log/python-redfish +RUN tar xvvf python-redfish.src.tar.gz +RUN cd python-redfish* && \ +pip install -r requirements.txt && \ +python setup.py install +CMD ["/bin/bash"] + diff --git a/redfish-client/tests/test_client.py b/redfish-client/tests/test_client.py new file mode 100644 index 0000000..7cd157d --- /dev/null +++ b/redfish-client/tests/test_client.py @@ -0,0 +1,89 @@ +# coding=utf-8 +import os +import stat +import subprocess +import re +from docker import Client +from path import Path + + +class DockerTest(): + def __init__(self): + self.cli = Client(base_url='unix://var/run/docker.sock') + + def build(self, dockerfile): + dockerfile = Path(dockerfile) + tag = 'rf' + dockerfile.basename().replace('Dockerfile.', '') + dockerfile.copy('redfish-client/tests/Dockerfile') + response = [line for line in self.cli.build( + path='redfish-client/tests', + tag=tag, + rm=True)] + return(response) + + def run(self, image, command): + container = self.cli.create_container(image=image, + command=command, + tty=True, + stdin_open=True) + self.cli.start(container=container.get('Id')) + self.cli.wait(container=container.get('Id')) + response = self.cli.logs(container=container.get('Id'), + stdout=True) + return(response) + + +def test_dockersocket(): + mode = os.stat('/var/run/docker.sock').st_mode + isSocket = stat.S_ISSOCK(mode) + assert isSocket, 'Make sure docker services are running' + + +def test_docker(): + cli = Client(base_url='unix://var/run/docker.sock') + response = cli.containers() + assert isinstance(response, list), 'Ensure you have sufficiant' + \ + 'credentials to use docker with' + \ + 'your current user' + + +def test_sources(): + output = subprocess.check_output(["python", "setup.py", "sdist"]) + search = re.search(r"removing '(\S+)'", output) + filename = Path('dist/' + search.group(1) + '.tar.gz') + filename.copy('redfish-client/tests/python-redfish.src.tar.gz') + assert Path('redfish-client/tests/python-redfish.src.tar.gz').isfile() + + +def test_dockerbuild(): + docker = DockerTest() + dockerfiles = ('redfish-client/tests/Dockerfile.ubuntu', + 'redfish-client/tests/Dockerfile.debian', + 'redfish-client/tests/Dockerfile.fedora', + 'redfish-client/tests/Dockerfile.fedorapip') + for dockerfile in dockerfiles: + print('Testing : {}'.format(dockerfile)) + response = docker.build(dockerfile) + status = response.pop() + assert 'Successfully built' in status + + +def test_install(): + docker = DockerTest() + images = ('rfubuntu', 'rfdebian', 'rffedora', 'rffedorapip') + for img in images: + print('Testing : {}'.format(img)) + response = docker.run(img, 'redfish-client config showall') + print(response) + assert ('Managers configured' in response and 'None' in response) + + +def test_versionformat(): + docker = DockerTest() + images = ('rfubuntu', 'rfdebian', 'rffedora', 'rffedorapip') + for img in images: + print('Testing : {}'.format(img)) + response = docker.run(img, 'redfish-client --version') + print(response) + assert (re.match('redfish-client \d+\.\d+', response)) + diff --git a/test-requirements.txt b/test-requirements.txt index 1da9f7e..2dd9159 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -2,14 +2,8 @@ # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. -hacking<0.11,>=0.10.0 - +pytest>=2.6.4 coverage>=3.6 -discover -python-subunit>=0.0.18 -sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3 -#oslosphinx>=2.2.0 # Apache-2.0 -#oslotest>=1.2.0 # Apache-2.0 -testrepository>=0.0.18 -testscenarios>=0.4 -testtools>=0.9.36,!=1.2.0 +mock>=1.0.1 +docker-py>=1.1.0 +path.py>=5.2 From bf69f3b642d06e55d21ac6cb5809a808136041d4 Mon Sep 17 00:00:00 2001 From: Uggla Date: Fri, 4 Mar 2016 12:00:36 +0100 Subject: [PATCH 6/8] Ignore files produced by tests --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 9c93129..6ec79a6 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,8 @@ htmlcov/ .cache nosetests.xml coverage.xml +redfish-client/tests/Dockerfile +redfish-client/tests/python-redfish.src.tar.gz # Translations *.mo From 23d2b0956213cdeb72f653398d053d12175e8e80 Mon Sep 17 00:00:00 2001 From: Uggla Date: Fri, 4 Mar 2016 14:21:12 +0100 Subject: [PATCH 7/8] Add documentation about tests --- doc/source/index.rst | 1 + doc/source/installation.rst | 2 +- doc/source/testing.rst | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 doc/source/testing.rst diff --git a/doc/source/index.rst b/doc/source/index.rst index 3897497..15abfa7 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -15,6 +15,7 @@ Contents: installation usage develsetup + testing classesdoc contributing help diff --git a/doc/source/installation.rst b/doc/source/installation.rst index f39d78b..2698e3f 100644 --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -47,7 +47,7 @@ Using pip and virtualenv 4. Install using pip:: - pip install python-virtualenv + pip install python-redfish All files are installed under your virtualenv. diff --git a/doc/source/testing.rst b/doc/source/testing.rst new file mode 100644 index 0000000..ac94b45 --- /dev/null +++ b/doc/source/testing.rst @@ -0,0 +1,25 @@ +============= +Running tests +============= + + +redfish module tests +-------------------- + +Tests are not functional for the redfish module yet. + +refish-client tests +------------------- + +#. Create your development environment following `Developer setup `_. +#. Install docker using the `procedure `_. +#. Ensure you can use docker with your current user. +#. Jump into redfish-python directory containing the sources. +#. Install required modules for testings:: + + pip install -t test-requirements.txt + +#. Run the test:: + + py.test redfish-client + From 6d3beeb823a8e78871789f412c96f28d220fcf3e Mon Sep 17 00:00:00 2001 From: Uggla Date: Fri, 4 Mar 2016 14:39:05 +0100 Subject: [PATCH 8/8] Avoid command line parsing error in getprefix() Several setup command line options like --help, raise an AttributeError exception --> just pass as in that case command line options are not useful to determine prefix. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ee366de..cc591e5 100755 --- a/setup.py +++ b/setup.py @@ -151,7 +151,7 @@ class DataFilesHelper(): dist.parse_config_files() try: dist.parse_command_line() - except distutils.errors.DistutilsArgError: + except (distutils.errors.DistutilsArgError, AttributeError): pass command = dist.get_command_obj('install') command.ensure_finalized()