Remove lorax-composer tests

The lorax-composer package handles running tests for itself, lorax should
only be running the lorax tests.

Resolves: rhbz#1679798
This commit is contained in:
Brian C. Lane 2019-02-26 11:26:13 -08:00
parent 3a1d7da06e
commit 4f373dcc10
38 changed files with 1 additions and 2962 deletions

View File

@ -36,15 +36,13 @@ test: docs
sudo mkdir -p $(USER_SITE_PACKAGES)
sudo cp ./tests/usercustomize.py $(USER_SITE_PACKAGES)
sudo COVERAGE_PROCESS_START=$(PW_DIR)/.coveragerc PYTHONPATH=$(PYTHONPATH):./src/ \
$(PYTHON) -m nose -v ./src/pylorax/ ./src/composer/ ./tests/pylorax/ ./tests/composer/
$(PYTHON) -m nose -v ./src/pylorax/ ./tests/pylorax/
sudo rm -rf $(USER_SITE_PACKAGES)
coverage combine
coverage report -m
[ -f "/usr/bin/coveralls" ] && [ -n "$(COVERALLS_REPO_TOKEN)" ] && coveralls || echo
./tests/test_cli.sh
check:
@echo "*** Running pylint ***"

View File

@ -1,45 +0,0 @@
#!/bin/bash
# Note: execute this file from the project root directory
. /usr/share/beakerlib/beakerlib.sh
CLI="./src/bin/composer-cli"
rlJournalStart
rlPhaseStartTest "blueprints list"
for bp in http-server development atlas; do
rlRun -t -c "$CLI blueprints list | grep $bp"
done
rlPhaseEnd
rlPhaseStartTest "blueprints save"
rlRun -t -c "$CLI blueprints save http-server"
rlAssertExists "http-server.toml"
rlAssertGrep "http-server" "http-server.toml"
rlAssertGrep "httpd" "http-server.toml"
# non-existing blueprint
# enable test for https://github.com/weldr/lorax/issues/460
# rlRun -t -c "$CLI blueprints save non-existing-bp" 1
# rlAssertNotExists "non-existing-bp.toml"
rlPhaseEnd
rlPhaseStartTest "blueprints push"
cat > beakerlib.toml << __EOF__
name = "beakerlib"
description = "Start building tests with beakerlib."
version = "0.0.1"
[[modules]]
name = "beakerlib"
version = "*"
__EOF__
rlRun -t -c "$CLI blueprints push beakerlib.toml"
rlRun -t -c "$CLI blueprints list | grep beakerlib"
rlPhaseEnd
rlJournalEnd
rlJournalPrintText

View File

@ -1,45 +0,0 @@
#!/bin/bash
# Note: execute this file from the project root directory
. /usr/share/beakerlib/beakerlib.sh
CLI="./src/bin/composer-cli"
rlJournalStart
rlPhaseStartTest "compose types"
rlAssertEquals "lists all supported types" \
"`$CLI compose types`" "Compose Types: ext4-filesystem, live-iso, partitioned-disk, qcow2, tar"
rlPhaseEnd
rlPhaseStartTest "compose start"
UUID=`$CLI --test=2 compose start http-server tar`
rlAssertEquals "exit code should be zero" $? 0
UUID=`echo $UUID | cut -f 2 -d' '`
rlPhaseEnd
rlPhaseStartTest "compose info"
if [ -n "$UUID" ]; then
rlRun -t -c "$CLI compose details $UUID | egrep 'RUNNING|WAITING'"
else
rlFail "Compose UUID is empty!"
fi
rlPhaseEnd
rlPhaseStartTest "compose image"
if [ -n "$UUID" ]; then
until $CLI compose details $UUID | grep FINISHED; do
sleep 5
rlLogInfo "Waiting for compose to finish ..."
done;
rlRun -t -c "$CLI compose image $UUID"
rlAssertExists "$UUID-root.tar.xz"
else
rlFail "Compose UUID is empty!"
fi
rlPhaseEnd
rlJournalEnd
rlJournalPrintText

View File

@ -1,40 +0,0 @@
#
# Copyright (C) 2018 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import unittest
from composer.cli.blueprints import prettyDiffEntry
diff_entries = [{'new': {'Description': 'Shiny new description'}, 'old': {'Description': 'Old reliable description'}},
{'new': {'Version': '0.3.1'}, 'old': {'Version': '0.1.1'}},
{'new': {'Module': {'name': 'openssh', 'version': '2.8.1'}}, 'old': None},
{'new': None, 'old': {'Module': {'name': 'bash', 'version': '4.*'}}},
{'new': {'Module': {'name': 'httpd', 'version': '3.8.*'}},
'old': {'Module': {'name': 'httpd', 'version': '3.7.*'}}},
{'new': {'Package': {'name': 'git', 'version': '2.13.*'}}, 'old': None}]
diff_result = [
'Changed Description "Old reliable description" -> "Shiny new description"',
'Changed Version 0.1.1 -> 0.3.1',
'Added Module openssh 2.8.1',
'Removed Module bash 4.*',
'Changed Module httpd 3.7.* -> 3.8.*',
'Added Package git 2.13.*']
class BlueprintsTest(unittest.TestCase):
def test_prettyDiffEntry(self):
"""Return a nice representation of a diff entry"""
self.assertEqual([prettyDiffEntry(entry) for entry in diff_entries], diff_result)

View File

@ -1,36 +0,0 @@
#
# Copyright (C) 2018 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import unittest
from composer.http_client import api_url, get_filename
headers = {'content-disposition': 'attachment; filename=e7b9b9b0-5867-493d-89c3-115cfe9227d7-metadata.tar;',
'access-control-max-age': '21600',
'transfer-encoding': 'chunked',
'date': 'Tue, 13 Mar 2018 17:37:18 GMT',
'access-control-allow-origin': '*',
'access-control-allow-methods': 'HEAD, OPTIONS, GET',
'content-type': 'application/x-tar'}
class HttpClientTest(unittest.TestCase):
def test_api_url(self):
"""Return the API url including the API version"""
self.assertEqual(api_url("0", "/path/to/enlightenment"), "/api/v0/path/to/enlightenment")
def test_get_filename(self):
"""Return the filename from a content-disposition header"""
self.assertEqual(get_filename(headers), "e7b9b9b0-5867-493d-89c3-115cfe9227d7-metadata.tar")

View File

@ -1,47 +0,0 @@
#
# Copyright (C) 2018 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import unittest
from composer.cli.utilities import argify, toml_filename, frozen_toml_filename, packageNEVRA
class CliUtilitiesTest(unittest.TestCase):
def test_argify(self):
"""Convert an optionally comma-separated cmdline into a list of args"""
self.assertEqual(argify(["one,two", "three", ",four", ",five,"]), ["one", "two", "three", "four", "five"])
def test_toml_filename(self):
"""Return the recipe's toml filename"""
self.assertEqual(toml_filename("http server"), "http-server.toml")
def test_frozen_toml_filename(self):
"""Return the recipe's frozen toml filename"""
self.assertEqual(frozen_toml_filename("http server"), "http-server.frozen.toml")
def test_packageNEVRA(self):
"""Return a string with the NVRA or NEVRA"""
epoch_0 = {"arch": "noarch",
"epoch": 0,
"name": "basesystem",
"release": "7.el7",
"version": "10.0"}
epoch_3 = {"arch": "noarch",
"epoch": 3,
"name": "basesystem",
"release": "7.el7",
"version": "10.0"}
self.assertEqual(packageNEVRA(epoch_0), "basesystem-10.0-7.el7.noarch")
self.assertEqual(packageNEVRA(epoch_3), "basesystem-3:10.0-7.el7.noarch")

View File

@ -1,10 +0,0 @@
name = "atlas"
description = "Automatically Tuned Linear Algebra Software"
[[modules]]
name = "atlas"
version = "3.10.*"
[[modules]]
name = "numpy"
version = "1.7.*"

View File

@ -1,45 +0,0 @@
name = "custom-base"
description = "A base system with customizations"
version = "0.0.1"
[[packages]]
name = "bash"
version = "4.2.*"
[customizations]
hostname = "custombase"
[[customizations.sshkey]]
user = "root"
key = "A SSH KEY FOR ROOT"
[[customizations.user]]
name = "widget"
description = "Widget process user account"
home = "/srv/widget/"
shell = "/usr/bin/false"
groups = ["dialout", "users"]
[[customizations.user]]
name = "admin"
description = "Widget admin account"
password = "$6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31LeOUleVK/R/aeWVHVZDi26zAH.o0ywBKH9Tc0/wm7sW/q39uyd1"
home = "/srv/widget/"
shell = "/usr/bin/bash"
groups = ["widget", "users", "students"]
uid = 1200
[[customizations.user]]
name = "plain"
password = "simple plain password"
[[customizations.user]]
name = "bart"
key = "SSH KEY FOR BART"
groups = ["students"]
[[customizations.group]]
name = "widget"
[[customizations.group]]
name = "students"

View File

@ -1,82 +0,0 @@
name = "development"
description = "A general purpose development image"
[[packages]]
name = "cmake"
version = "*"
[[packages]]
name = "curl"
version = "*"
[[packages]]
name = "file"
version = "*"
[[packages]]
name = "gcc"
version = "*"
[[packages]]
name = "gcc-c++"
version = "*"
[[packages]]
name = "gdb"
version = "*"
[[packages]]
name = "git"
version = "*"
[[packages]]
name = "glibc-devel"
version = "*"
[[packages]]
name = "gnupg2"
version = "*"
[[packages]]
name = "libcurl-devel"
version = "*"
[[packages]]
name = "make"
version = "*"
[[packages]]
name = "openssl-devel"
version = "*"
[[packages]]
name = "openssl-devel"
version = "*"
[[packages]]
name = "sqlite"
version = "*"
[[packages]]
name = "sqlite-devel"
version = "*"
[[packages]]
name = "sudo"
version = "*"
[[packages]]
name = "tar"
version = "*"
[[packages]]
name = "xz"
version = "*"
[[packages]]
name = "xz-devel"
version = "*"
[[packages]]
name = "zlib-devel"
version = "*"

View File

@ -1,14 +0,0 @@
name = "glusterfs"
description = "An example GlusterFS server with samba"
[[modules]]
name = "glusterfs"
version = "3.8.*"
[[modules]]
name = "glusterfs-cli"
version = "3.8.*"
[[packages]]
name = "samba"
version = "4.7.*"

View File

@ -1,35 +0,0 @@
name = "http-server"
description = "An example http server with PHP and MySQL support."
version = "0.0.1"
[[modules]]
name = "httpd"
version = "2.4.*"
[[modules]]
name = "mod_auth_kerb"
version = "5.4"
[[modules]]
name = "mod_ssl"
version = "2.4.*"
[[modules]]
name = "php"
version = "5.4.*"
[[modules]]
name = "php-mysql"
version = "5.4.*"
[[packages]]
name = "tmux"
version = "1.8"
[[packages]]
name = "openssh-server"
version = "7.*"
[[packages]]
name = "rsync"
version = "3.1.*"

View File

@ -1,14 +0,0 @@
name = "jboss"
description = "An example jboss server"
[[modules]]
name = "jboss-servlet-3.0-api"
version = "1.0.*"
[[modules]]
name = "jboss-interceptors-1.1-api"
version = "1.0.*"
[[modules]]
name = "java-1.8.0-openjdk"
version = "1.8.0.*"

View File

@ -1,26 +0,0 @@
name = "kubernetes"
description = "An example kubernetes master"
[[modules]]
name = "kubernetes"
version = "1.5.2"
[[modules]]
name = "docker"
version = "1.13.*"
[[modules]]
name = "docker-lvm-plugin"
version = "1.13.*"
[[modules]]
name = "etcd"
version = "3.2.*"
[[modules]]
name = "flannel"
version = "0.7.*"
[[packages]]
name = "oci-systemd-hook"
version = "0.1.*"

View File

@ -1,47 +0,0 @@
[lorax-1]
name=Lorax test repo 1
failovermethod=priority
baseurl=file:///tmp/lorax-empty-repo/
enabled=1
metadata_expire=7d
repo_gpgcheck=0
type=rpm
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch
skip_if_unavailable=False
[lorax-2]
name=Lorax test repo 2
failovermethod=priority
baseurl=file:///tmp/lorax-empty-repo/
enabled=1
metadata_expire=7d
repo_gpgcheck=0
type=rpm
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch
skip_if_unavailable=False
[lorax-3]
name=Lorax test repo 3
failovermethod=priority
baseurl=file:///tmp/lorax-empty-repo/
enabled=1
metadata_expire=7d
repo_gpgcheck=0
type=rpm
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch
skip_if_unavailable=False
[lorax-4]
name=Lorax test repo 4
failovermethod=priority
baseurl=file:///tmp/lorax-empty-repo/
enabled=1
metadata_expire=7d
repo_gpgcheck=0
type=rpm
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch
skip_if_unavailable=False

View File

@ -1,11 +0,0 @@
[other-repo]
name=Other repo
failovermethod=priority
baseurl=file:///tmp/lorax-empty-repo/
enabled=1
metadata_expire=7d
repo_gpgcheck=0
type=rpm
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch
skip_if_unavailable=False

View File

@ -1,11 +0,0 @@
[single-repo]
name=One repo in the file
failovermethod=priority
baseurl=file:///tmp/lorax-empty-repo/
enabled=1
metadata_expire=7d
repo_gpgcheck=0
type=rpm
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch
skip_if_unavailable=False

View File

@ -1 +0,0 @@
{'name': 'custom-base', 'description': 'A base system with customizations', 'version': '0.0.1', 'modules': [], 'packages': [{'name': 'bash', 'version': '4.4.*'}], 'customizations': {'hostname': 'custombase', 'sshkey': [{'user': 'root', 'key': 'A SSH KEY FOR ROOT'}]}}

View File

@ -1,14 +0,0 @@
name = "custom-base"
description = "A base system with customizations"
version = "0.0.1"
[[packages]]
name = "bash"
version = "4.4.*"
[customizations]
hostname = "custombase"
[[customizations.sshkey]]
user = "root"
key = "A SSH KEY FOR ROOT"

View File

@ -1 +0,0 @@
{'description': u'An example http server with PHP and MySQL support.', 'packages': [{'version': u'6.6.*', 'name': u'openssh-server'}, {'version': u'3.0.*', 'name': u'rsync'}, {'version': u'2.2', 'name': u'tmux'}], 'modules': [{'version': u'2.4.*', 'name': u'httpd'}, {'version': u'5.4', 'name': u'mod_auth_kerb'}, {'version': u'2.4.*', 'name': u'mod_ssl'}, {'version': u'5.4.*', 'name': u'php'}, {'version': u'5.4.*', 'name': u'php-mysql'}], 'version': u'0.0.1', 'name': u'http-server'}

View File

@ -1,35 +0,0 @@
name = "http-server"
description = "An example http server with PHP and MySQL support."
version = "0.0.1"
[[modules]]
name = "httpd"
version = "2.4.*"
[[modules]]
name = "mod_auth_kerb"
version = "5.4"
[[modules]]
name = "mod_ssl"
version = "2.4.*"
[[modules]]
name = "php"
version = "5.4.*"
[[modules]]
name = "php-mysql"
version = "5.4.*"
[[packages]]
name = "tmux"
version = "2.2"
[[packages]]
name = "openssh-server"
version = "6.6.*"
[[packages]]
name = "rsync"
version = "3.0.*"

View File

@ -1 +0,0 @@
{'description': u'An example http server with PHP and MySQL support.', 'packages': [], 'modules': [], 'version': u'0.0.1', 'name': u'http-server'}

View File

@ -1,3 +0,0 @@
name = "http-server"
description = "An example http server with PHP and MySQL support."
version = "0.0.1"

View File

@ -1 +0,0 @@
{'description': u'An example http server with PHP and MySQL support.', 'packages': [], 'modules': [{'version': u'2.4.*', 'name': u'httpd'}, {'version': u'5.4', 'name': u'mod_auth_kerb'}, {'version': u'2.4.*', 'name': u'mod_ssl'}, {'version': u'5.4.*', 'name': u'php'}, {'version': u'5.4.*', 'name': u'php-mysql'}], 'version': u'0.0.1', 'name': u'http-server'}

View File

@ -1,23 +0,0 @@
name = "http-server"
description = "An example http server with PHP and MySQL support."
version = "0.0.1"
[[modules]]
name = "httpd"
version = "2.4.*"
[[modules]]
name = "mod_auth_kerb"
version = "5.4"
[[modules]]
name = "mod_ssl"
version = "2.4.*"
[[modules]]
name = "php"
version = "5.4.*"
[[modules]]
name = "php-mysql"
version = "5.4.*"

View File

@ -1 +0,0 @@
{'description': u'An example http server with PHP and MySQL support.', 'packages': [{'version': u'6.6.*', 'name': u'openssh-server'}, {'version': u'3.0.*', 'name': u'rsync'}, {'version': u'2.2', 'name': u'tmux'}], 'modules': [], 'version': u'0.0.1', 'name': u'http-server'}

View File

@ -1,15 +0,0 @@
name = "http-server"
description = "An example http server with PHP and MySQL support."
version = "0.0.1"
[[packages]]
name = "tmux"
version = "2.2"
[[packages]]
name = "openssh-server"
version = "6.6.*"
[[packages]]
name = "rsync"
version = "3.0.*"

View File

@ -1,6 +0,0 @@
name = "bad-repo-1"
url = "file:///tmp/not-a-repo/"
type = "yum-baseurl"
check_ssl = true
check_gpg = true
gpgkey_urls = ["file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch"]

View File

@ -1,6 +0,0 @@
name = "single-repo"
url = "file:///tmp/lorax-empty-repo/"
type = "yum-baseurl"
check_ssl = false
check_gpg = true
gpgkey_urls = []

View File

@ -1 +0,0 @@
{"name": "new-repo-1", "url": "file:///tmp/lorax-empty-repo/", "type": "yum-baseurl", "check_ssl": true, "check_gpg": true, "gpgkey_urls": ["file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch"]}

View File

@ -1,6 +0,0 @@
name = "new-repo-2"
url = "file:///tmp/lorax-empty-repo/"
type = "yum-baseurl"
check_ssl = true
check_gpg = true
gpgkey_urls = ["file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch"]

View File

@ -1,178 +0,0 @@
#
# Copyright (C) 2018 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from StringIO import StringIO
import unittest
from pylorax.api.compose import add_customizations
from pylorax.api.recipes import recipe_from_toml
BASE_RECIPE = """name = "test-cases"
description = "Used for testing"
version = "0.0.1"
"""
HOSTNAME = BASE_RECIPE + """[customizations]
hostname = "testhostname"
"""
SSHKEY = BASE_RECIPE + """[[customizations.sshkey]]
user = "root"
key = "ROOT SSH KEY"
"""
USER = BASE_RECIPE + """[[customizations.user]]
name = "tester"
"""
USER_KEY = """
key = "A SSH KEY FOR TESTER"
"""
USER_DESC = """
description = "a test user account"
"""
USER_CRYPT = """
password = "$6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31LeOUleVK/R/aeWVHVZDi26zAH.o0ywBKH9Tc0/wm7sW/q39uyd1"
"""
USER_PLAIN = """
password = "plainpassword"
"""
USER_HOME = """
home = "/opt/users/tester/"
"""
USER_SHELL = """
shell = "/usr/bin/zsh"
"""
USER_UID = """
uid = 1013
"""
USER_GID = """
gid = 4242
"""
USER_GROUPS = """
groups = ["wheel", "users"]
"""
USER_ALL = USER + USER_KEY + USER_DESC + USER_CRYPT + USER_HOME + USER_SHELL + USER_UID + USER_GID
GROUP = BASE_RECIPE + """[[customizations.group]]
name = "testgroup"
"""
GROUP_GID = GROUP + """
gid = 1011
"""
USER_GROUP = USER + """[[customizations.group]]
name = "tester"
"""
KS_USER_ALL = '''sshkey --user tester "A SSH KEY FOR TESTER"
user --name tester --homedir /opt/users/tester/ --iscrypted --password "$6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31LeOUleVK/R/aeWVHVZDi26zAH.o0ywBKH9Tc0/wm7sW/q39uyd1" --shell /usr/bin/zsh --uid 1013 --gid 4242 --gecos "a test user account"
'''
class CustomizationsTestCase(unittest.TestCase):
def assertCustomization(self, test, result):
r = recipe_from_toml(test)
f = StringIO()
add_customizations(f, r)
self.assertTrue(result in f.getvalue(), f.getvalue())
def assertNotCustomization(self, test, result):
r = recipe_from_toml(test)
f = StringIO()
add_customizations(f, r)
self.assertTrue(result not in f.getvalue(), f.getvalue())
def test_set_hostname(self):
"""Test setting the hostname"""
self.assertCustomization(HOSTNAME, "network --hostname=testhostname")
def test_set_sshkey(self):
"""Test setting sshkey without user"""
self.assertCustomization(SSHKEY, 'sshkey --user root "ROOT SSH KEY"')
def test_sshkey_only(self):
"""Test adding a sshkey to an existing user account"""
self.assertCustomization(USER + USER_KEY, 'sshkey --user tester "A SSH KEY FOR TESTER"')
def test_create_user(self):
"""Test creating a user with no options"""
self.assertCustomization(USER, "user --name tester")
def test_create_user_desc(self):
"""Test creating a user with a description"""
self.assertCustomization(USER + USER_DESC, '--gecos "a test user account"')
def test_create_user_crypt(self):
"""Test creating a user with a pre-crypted password"""
self.assertCustomization(USER + USER_CRYPT, '--password "$6$CHO2$3r')
def test_create_user_plain(self):
"""Test creating a user with a plaintext password"""
self.assertCustomization(USER + USER_PLAIN, '--password "plainpassword"')
def test_create_user_home(self):
"""Test creating user with a home directory"""
self.assertCustomization(USER + USER_HOME, "--homedir /opt/users/tester/")
def test_create_user_shell(self):
"""Test creating user with shell set"""
self.assertCustomization(USER + USER_SHELL, "--shell /usr/bin/zsh")
def test_create_user_uid(self):
"""Test creating user with uid set"""
self.assertCustomization(USER + USER_UID, "--uid 1013")
def test_create_user_gid(self):
"""Test creating user with gid set"""
self.assertCustomization(USER + USER_GID, "--gid 4242")
def test_create_user_groups(self):
"""Test creating user with group membership"""
self.assertCustomization(USER + USER_GROUPS, "--groups wheel,users")
def test_user_same_group(self):
"""Test creating a group with the same name as a user"""
# Creating a group with the same name should skip the group creation
self.assertCustomization(USER_GROUP, "user --name tester")
self.assertNotCustomization(USER_GROUP, "group --name tester")
def test_create_user_all(self):
"""Test creating user with all settings"""
r = recipe_from_toml(USER_ALL)
f = StringIO()
add_customizations(f, r)
self.assertEqual(KS_USER_ALL, f.getvalue())
def test_create_group(self):
"""Test creating group without gid set"""
self.assertCustomization(GROUP, "group --name testgroup")
def test_create_group_gid(self):
"""Test creating group with gid set"""
self.assertCustomization(GROUP_GID, "group --name testgroup --gid 1011")

View File

@ -1,118 +0,0 @@
#
# Copyright (C) 2018 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import unittest
from flask import Flask
from datetime import timedelta
from pylorax.api.crossdomain import crossdomain
server = Flask(__name__)
@server.route('/01')
@crossdomain(origin='*', methods=['GET'])
def hello_world_01():
return 'Hello, World!'
@server.route('/02')
@crossdomain(origin='*', headers=['TESTING'])
def hello_world_02():
return 'Hello, World!'
@server.route('/03')
@crossdomain(origin='*', max_age=timedelta(days=7))
def hello_world_03():
return 'Hello, World!'
@server.route('/04')
@crossdomain(origin='*', attach_to_all=False)
def hello_world_04():
return 'Hello, World!'
@server.route('/05')
@crossdomain(origin='*', automatic_options=False)
def hello_world_05():
return 'Hello, World!'
@server.route('/06')
@crossdomain(origin=['https://redhat.com', 'http://weldr.io'])
def hello_world_06():
return 'Hello, World!'
class CrossdomainTest(unittest.TestCase):
@classmethod
def setUpClass(self):
self.server = server.test_client()
def test_01_with_methods_specified(self):
# first send a preflight request to check what methods are allowed
response = self.server.options("/01")
self.assertEqual(200, response.status_code)
self.assertIn('GET', response.headers['Access-Control-Allow-Methods'])
# then try to issue a POST request which isn't allowed
response = self.server.post("/01")
self.assertEqual(405, response.status_code)
def test_02_with_headers_specified(self):
response = self.server.get("/02")
self.assertEqual(200, response.status_code)
self.assertEqual('Hello, World!', response.data)
self.assertEqual('TESTING', response.headers['Access-Control-Allow-Headers'])
def test_03_with_max_age_as_timedelta(self):
response = self.server.get("/03")
self.assertEqual(200, response.status_code)
self.assertEqual('Hello, World!', response.data)
expected_max_age = int(timedelta(days=7).total_seconds())
actual_max_age = int(response.headers['Access-Control-Max-Age'])
self.assertEqual(expected_max_age, actual_max_age)
def test_04_attach_to_all_false(self):
response = self.server.get("/04")
self.assertEqual(200, response.status_code)
self.assertEqual('Hello, World!', response.data)
# when attach_to_all is False the decorator will not assign
# the Access-Control-* headers to the response
for header, _ in response.headers:
self.assertFalse(header.startswith('Access-Control-'))
def test_05_options_request(self):
response = self.server.options("/05")
self.assertEqual(200, response.status_code)
self.assertEqual('Hello, World!', response.data)
self.assertEqual(response.headers['Access-Control-Allow-Methods'], 'HEAD, OPTIONS, GET')
def test_06_with_origin_as_list(self):
response = self.server.get("/06")
self.assertEqual(200, response.status_code)
self.assertEqual('Hello, World!', response.data)
for header, value in response.headers:
if header == 'Access-Control-Allow-Origin':
self.assertIn(value, ['https://redhat.com', 'http://weldr.io'])

View File

@ -1,526 +0,0 @@
#
# Copyright (C) 2017 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from glob import glob
import os
import mock
import time
import shutil
import tempfile
import unittest
from yum.Errors import YumBaseError
from pylorax.sysutils import joinpaths
from pylorax.api.config import configure, make_yum_dirs
from pylorax.api.projects import api_time, api_changelog, yaps_to_project, yaps_to_project_info
from pylorax.api.projects import tm_to_dep, yaps_to_module, projects_list, projects_info, projects_depsolve
from pylorax.api.projects import modules_list, modules_info, ProjectsError, dep_evra, dep_nevra
from pylorax.api.projects import repo_to_source, get_repo_sources, delete_repo_source, source_to_repo
from pylorax.api.projects import yum_repo_to_file_repo
from pylorax.api.yumbase import get_base_object
class Yaps(object):
"""Test class for yaps tests"""
name = "name"
summary = "summary"
description = "description"
url = "url"
epoch = 1
release = "release"
arch = "arch"
buildtime = 499222800
license = "license"
version = "version"
def returnChangelog(self):
return [[0,1,"Heavy!"]]
class TM(object):
"""Test class for tm test"""
name = "name"
epoch = 1
version = "version"
release = "release"
arch = "arch"
class ProjectsTest(unittest.TestCase):
@classmethod
def setUpClass(self):
self.tmp_dir = tempfile.mkdtemp(prefix="lorax.test.repo.")
self.config = configure(root_dir=self.tmp_dir, test_config=True)
make_yum_dirs(self.config)
self.yb = get_base_object(self.config)
os.environ["TZ"] = "UTC"
time.tzset()
@classmethod
def tearDownClass(self):
shutil.rmtree(self.tmp_dir)
def test_api_time(self):
self.assertEqual(api_time(499222800), "1985-10-27T01:00:00")
def test_api_changelog(self):
self.assertEqual(api_changelog([[0,1,"Heavy!"], [0, 1, "Light!"]]), "Heavy!")
def test_api_changelog_empty_list(self):
self.assertEqual(api_changelog([]), '')
def test_api_changelog_missing_text_entry(self):
self.assertEqual(api_changelog([('now', 'atodorov')]), '')
def test_yaps_to_project(self):
result = {"name":"name",
"summary":"summary",
"description":"description",
"homepage":"url",
"upstream_vcs":"UPSTREAM_VCS"}
y = Yaps()
self.assertEqual(yaps_to_project(y), result)
def test_yaps_to_project_info(self):
build = {"epoch":1,
"release":"release",
"arch":"arch",
"build_time":"1985-10-27T01:00:00",
"changelog":"Heavy!",
"build_config_ref": "BUILD_CONFIG_REF",
"build_env_ref": "BUILD_ENV_REF",
"metadata": {},
"source": {"license":"license",
"version":"version",
"source_ref": "SOURCE_REF",
"metadata": {}}}
result = {"name":"name",
"summary":"summary",
"description":"description",
"homepage":"url",
"upstream_vcs":"UPSTREAM_VCS",
"builds": [build]}
y = Yaps()
self.assertEqual(yaps_to_project_info(y), result)
def test_tm_to_dep(self):
result = {"name":"name",
"epoch":1,
"version":"version",
"release":"release",
"arch":"arch"}
tm = TM()
self.assertEqual(tm_to_dep(tm), result)
def test_yaps_to_module(self):
result = {"name":"name",
"group_type":"rpm"}
y = Yaps()
self.assertEqual(yaps_to_module(y), result)
def test_dep_evra(self):
dep = {"arch": "noarch",
"epoch": 0,
"name": "basesystem",
"release": "7.el7",
"version": "10.0"}
self.assertEqual(dep_evra(dep), "10.0-7.el7.noarch")
def test_dep_evra_with_epoch_not_zero(self):
dep = {"arch": "x86_64",
"epoch": 2,
"name": "tog-pegasus-libs",
"release": "3.el7",
"version": "2.14.1"}
self.assertEqual(dep_evra(dep), "2:2.14.1-3.el7.x86_64")
def test_dep_nevra(self):
dep = {"arch": "noarch",
"epoch": 0,
"name": "basesystem",
"release": "7.el7",
"version": "10.0"}
self.assertEqual(dep_nevra(dep), "basesystem-10.0-7.el7.noarch")
def test_projects_list(self):
projects = projects_list(self.yb)
self.assertEqual(len(projects) > 10, True)
def test_projects_list_yum_raises_exception(self):
with self.assertRaises(ProjectsError):
with mock.patch.object(self.yb, 'doPackageLists', side_effect=YumBaseError('TESTING')):
projects_list(self.yb)
def test_projects_info(self):
projects = projects_info(self.yb, ["bash"])
self.assertEqual(projects[0]["name"], "bash")
self.assertEqual(projects[0]["builds"][0]["source"]["license"], "GPLv3+")
def test_projects_info_yum_raises_exception(self):
with self.assertRaises(ProjectsError):
with mock.patch.object(self.yb, 'doPackageLists', side_effect=YumBaseError('TESTING')):
projects_info(self.yb, ["bash"])
def test_projects_depsolve(self):
deps = projects_depsolve(self.yb, [("bash", "*.*")])
self.assertTrue(len(deps) > 3)
self.assertEqual(deps[2]["name"], "basesystem")
def test_projects_depsolve_version(self):
"""Test that depsolving with a partial wildcard version works"""
deps = projects_depsolve(self.yb, [("bash", "4.*")])
self.assertEqual(deps[1]["name"], "bash")
deps = projects_depsolve(self.yb, [("bash", "4.2.*")])
self.assertEqual(deps[1]["name"], "bash")
def test_projects_depsolve_oldversion(self):
"""Test that depsolving a specific non-existant version fails"""
with self.assertRaises(ProjectsError):
deps = projects_depsolve(self.yb, [("bash", "1.0.0")])
self.assertEqual(deps[1]["name"], "bash")
def test_projects_depsolve_fail(self):
with self.assertRaises(ProjectsError):
projects_depsolve(self.yb, [("nada-package", "*.*")])
def test_modules_list(self):
modules = modules_list(self.yb, None)
self.assertEqual(len(modules) > 10, True)
self.assertEqual(modules[0]["group_type"], "rpm")
modules = modules_list(self.yb, ["g*"])
self.assertEqual(modules[0]["name"].startswith("g"), True)
def test_modules_list_yum_raises_exception(self):
with self.assertRaises(ProjectsError):
with mock.patch.object(self.yb, 'doPackageLists', side_effect=YumBaseError('TESTING')):
modules_list(self.yb, None)
def test_modules_info(self):
modules = modules_info(self.yb, ["bash"])
print(modules)
self.assertTrue(len(modules) > 0)
self.assertTrue(len(modules[0]["dependencies"]) > 3)
self.assertEqual(modules[0]["name"], "bash")
self.assertEqual(modules[0]["dependencies"][2]["name"], "basesystem")
def test_modules_info_yum_raises_exception(self):
with self.assertRaises(ProjectsError):
with mock.patch.object(self.yb, 'doPackageLists', side_effect=YumBaseError('TESTING')):
modules_info(self.yb, ["bash"])
class ConfigureTest(unittest.TestCase):
@classmethod
def setUpClass(self):
self.tmp_dir = tempfile.mkdtemp(prefix="lorax.test.configure.")
self.conf_file = os.path.join(self.tmp_dir, 'test.conf')
open(self.conf_file, 'w').write("[composer]\ncache_dir = /tmp/cache-test")
@classmethod
def tearDownClass(self):
shutil.rmtree(self.tmp_dir)
def test_configure_reads_existing_file(self):
config = configure(conf_file=self.conf_file)
self.assertEqual(config.get('composer', 'cache_dir'), '/tmp/cache-test')
def test_configure_reads_non_existing_file(self):
config = configure(conf_file=self.conf_file + '.non-existing')
self.assertEqual(config.get('composer', 'cache_dir'), '/var/tmp/composer/cache')
class FakeRepoBaseUrl(object):
id = "fake-repo-baseurl"
baseurl = ["https://fake-repo.base.url"]
metalink = ""
mirrorlist = ""
proxy = ""
sslverify = True
gpgcheck = True
gpgkey = []
def fakerepo_baseurl():
return {
"check_gpg": True,
"check_ssl": True,
"name": "fake-repo-baseurl",
"system": False,
"type": "yum-baseurl",
"url": "https://fake-repo.base.url"
}
def fakerepo_baseurl_str():
return """[fake-repo-baseurl]
baseurl = https://fake-repo.base.url
sslverify = True
gpgcheck = True
"""
class FakeSystemRepo(object):
id = "fake-system-repo"
baseurl = ["https://fake-repo.base.url"]
metalink = ""
mirrorlist = ""
proxy = ""
sslverify = True
gpgcheck = True
gpgkey = []
def fakesystem_repo():
return {
"check_gpg": True,
"check_ssl": True,
"name": "fake-system-repo",
"system": True,
"type": "yum-baseurl",
"url": "https://fake-repo.base.url"
}
class FakeRepoMetalink(object):
id = "fake-repo-metalink"
baseurl = []
metalink = "https://fake-repo.metalink"
proxy = ""
sslverify = True
gpgcheck = True
gpgkey = []
def fakerepo_metalink():
return {
"check_gpg": True,
"check_ssl": True,
"name": "fake-repo-metalink",
"system": False,
"type": "yum-metalink",
"url": "https://fake-repo.metalink"
}
def fakerepo_metalink_str():
return """[fake-repo-metalink]
metalink = https://fake-repo.metalink
sslverify = True
gpgcheck = True
"""
class FakeRepoMirrorlist(object):
id = "fake-repo-mirrorlist"
baseurl = []
metalink = ""
mirrorlist = "https://fake-repo.mirrorlist"
proxy = ""
sslverify = True
gpgcheck = True
gpgkey = []
def fakerepo_mirrorlist():
return {
"check_gpg": True,
"check_ssl": True,
"name": "fake-repo-mirrorlist",
"system": False,
"type": "yum-mirrorlist",
"url": "https://fake-repo.mirrorlist"
}
def fakerepo_mirrorlist_str():
return """[fake-repo-mirrorlist]
mirrorlist = https://fake-repo.mirrorlist
sslverify = True
gpgcheck = True
"""
class FakeRepoProxy(object):
id = "fake-repo-proxy"
baseurl = ["https://fake-repo.base.url"]
metalink = ""
mirrorlist = ""
proxy = "https://fake-repo.proxy"
sslverify = True
gpgcheck = True
gpgkey = []
def fakerepo_proxy():
return {
"check_gpg": True,
"check_ssl": True,
"name": "fake-repo-proxy",
"proxy": "https://fake-repo.proxy",
"system": False,
"type": "yum-baseurl",
"url": "https://fake-repo.base.url"
}
def fakerepo_proxy_str():
return """[fake-repo-proxy]
baseurl = https://fake-repo.base.url
proxy = https://fake-repo.proxy
sslverify = True
gpgcheck = True
"""
class FakeRepoGPGKey(object):
id = "fake-repo-gpgkey"
baseurl = ["https://fake-repo.base.url"]
metalink = ""
mirrorlist = ""
proxy = ""
sslverify = True
gpgcheck = True
gpgkey = ["https://fake-repo.gpgkey"]
def fakerepo_gpgkey():
return {
"check_gpg": True,
"check_ssl": True,
"gpgkey_urls": [
"https://fake-repo.gpgkey"
],
"name": "fake-repo-gpgkey",
"system": False,
"type": "yum-baseurl",
"url": "https://fake-repo.base.url"
}
def fakerepo_gpgkey_str():
return """[fake-repo-gpgkey]
baseurl = https://fake-repo.base.url
sslverify = True
gpgcheck = True
gpgkey = https://fake-repo.gpgkey
"""
def yum_to_file(d):
"""Test function to convert a source to a dict and then to a yum repo string"""
return yum_repo_to_file_repo(source_to_repo(d))
class SourceTest(unittest.TestCase):
@classmethod
def setUpClass(self):
self.tmp_dir = tempfile.mkdtemp(prefix="lorax.test.repo.")
for f in glob("./tests/pylorax/repos/*.repo"):
shutil.copy2(f, self.tmp_dir)
@classmethod
def tearDownClass(self):
shutil.rmtree(self.tmp_dir)
def test_repo_to_source_baseurl(self):
"""Test a repo with a baseurl"""
self.assertEqual(repo_to_source(FakeRepoBaseUrl(), False), fakerepo_baseurl())
def test_system_repo(self):
"""Test a system repo with a baseurl"""
self.assertEqual(repo_to_source(FakeSystemRepo(), True), fakesystem_repo())
def test_repo_to_source_metalink(self):
"""Test a repo with a metalink"""
self.assertEqual(repo_to_source(FakeRepoMetalink(), False), fakerepo_metalink())
def test_repo_to_source_mirrorlist(self):
"""Test a repo with a mirrorlist"""
self.assertEqual(repo_to_source(FakeRepoMirrorlist(), False), fakerepo_mirrorlist())
def test_repo_to_source_proxy(self):
"""Test a repo with a proxy"""
self.assertEqual(repo_to_source(FakeRepoProxy(), False), fakerepo_proxy())
def test_repo_to_source_gpgkey(self):
"""Test a repo with a GPG key"""
self.assertEqual(repo_to_source(FakeRepoGPGKey(), False), fakerepo_gpgkey())
def test_get_repo_sources(self):
"""Test getting a list of sources from a repo directory"""
sources = get_repo_sources(joinpaths(self.tmp_dir, "*.repo"))
self.assertTrue("lorax-1" in sources)
self.assertTrue("lorax-2" in sources)
def test_delete_source_multiple(self):
"""Test deleting a source from a repo file with multiple entries"""
delete_repo_source(joinpaths(self.tmp_dir, "*.repo"), "lorax-3")
sources = get_repo_sources(joinpaths(self.tmp_dir, "*.repo"))
self.assertTrue("lorax-3" not in sources)
def test_delete_source_single(self):
"""Test deleting a source from a repo with only 1 entry"""
delete_repo_source(joinpaths(self.tmp_dir, "*.repo"), "single-repo")
sources = get_repo_sources(joinpaths(self.tmp_dir, "*.repo"))
self.assertTrue("single-repo" not in sources)
self.assertTrue(not os.path.exists(joinpaths(self.tmp_dir, "single.repo")))
def test_delete_source_other(self):
"""Test deleting a source from a repo that doesn't match the source name"""
with self.assertRaises(ProjectsError):
delete_repo_source(joinpaths(self.tmp_dir, "*.repo"), "unknown-source")
sources = get_repo_sources(joinpaths(self.tmp_dir, "*.repo"))
self.assertTrue("lorax-1" in sources)
self.assertTrue("lorax-2" in sources)
self.assertTrue("lorax-4" in sources)
self.assertTrue("other-repo" in sources)
def test_source_to_repo_baseurl(self):
"""Test creating a yum.yumRepo.YumRepository with a baseurl"""
repo = source_to_repo(fakerepo_baseurl())
self.assertEqual(repo["baseurl"][0], fakerepo_baseurl()["url"])
def test_source_to_repo_metalink(self):
"""Test creating a yum.yumRepo.YumRepository with a metalink"""
repo = source_to_repo(fakerepo_metalink())
self.assertEqual(repo["metalink"], fakerepo_metalink()["url"])
def test_source_to_repo_mirrorlist(self):
"""Test creating a yum.yumRepo.YumRepository with a mirrorlist"""
repo = source_to_repo(fakerepo_mirrorlist())
self.assertEqual(repo["mirrorlist"], fakerepo_mirrorlist()["url"])
def test_source_to_repo_proxy(self):
"""Test creating a yum.yumRepo.YumRepository with a proxy"""
repo = source_to_repo(fakerepo_proxy())
self.assertEqual(repo["proxy"], fakerepo_proxy()["proxy"])
def test_source_to_repo_gpgkey(self):
"""Test creating a yum.yumRepo.YumRepository with a proxy"""
repo = source_to_repo(fakerepo_gpgkey())
self.assertEqual(repo["gpgkey"], fakerepo_gpgkey()["gpgkey_urls"])
def test_drtfr_baseurl(self):
"""Test creating a yum .repo file from a baseurl Repo object"""
self.assertEqual(yum_to_file(fakerepo_baseurl()), fakerepo_baseurl_str())
def test_drtfr_metalink(self):
"""Test creating a yum .repo file from a metalink Repo object"""
self.assertEqual(yum_to_file(fakerepo_metalink()), fakerepo_metalink_str())
def test_drtfr_mirrorlist(self):
"""Test creating a yum .repo file from a mirrorlist Repo object"""
self.assertEqual(yum_to_file(fakerepo_mirrorlist()), fakerepo_mirrorlist_str())
def test_drtfr_proxy(self):
"""Test creating a yum .repo file from a baseurl Repo object with proxy"""
self.assertEqual(yum_to_file(fakerepo_proxy()), fakerepo_proxy_str())
def test_drtfr_gpgkey(self):
"""Test creating a yum .repo file from a baseurl Repo object with gpgkey"""
self.assertEqual(yum_to_file(fakerepo_gpgkey()), fakerepo_gpgkey_str())

View File

@ -1,344 +0,0 @@
#
# Copyright (C) 2017 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import os
import mock
from pytoml import TomlError
import shutil
import tempfile
import unittest
import pylorax.api.recipes as recipes
from pylorax.sysutils import joinpaths
class BasicRecipeTest(unittest.TestCase):
@classmethod
def setUpClass(self):
# Input toml is in .toml and python dict string is in .dict
input_recipes = [("full-recipe.toml", "full-recipe.dict"),
("minimal.toml", "minimal.dict"),
("modules-only.toml", "modules-only.dict"),
("packages-only.toml", "packages-only.dict"),
("custom-base.toml", "custom-base.dict")]
results_path = "./tests/pylorax/results/"
self.input_toml = []
for (recipe_toml, recipe_dict) in input_recipes:
with open(joinpaths(results_path, recipe_toml)) as f_toml:
with open(joinpaths(results_path, recipe_dict)) as f_dict:
# XXX Warning, can run arbitrary code
result_dict = eval(f_dict.read())
self.input_toml.append((f_toml.read(), result_dict))
self.old_modules = [recipes.RecipeModule("toml", "2.1"),
recipes.RecipeModule("bash", "4.*"),
recipes.RecipeModule("httpd", "3.7.*")]
self.old_packages = [recipes.RecipePackage("python", "2.7.*"),
recipes.RecipePackage("parted", "3.2")]
self.new_modules = [recipes.RecipeModule("toml", "2.1"),
recipes.RecipeModule("httpd", "3.8.*"),
recipes.RecipeModule("openssh", "2.8.1")]
self.new_packages = [recipes.RecipePackage("python", "2.7.*"),
recipes.RecipePackage("parted", "3.2"),
recipes.RecipePackage("git", "2.13.*")]
self.modules_result = [{"new": {"Modules": {"version": "2.8.1", "name": "openssh"}},
"old": None},
{"new": None,
"old": {"Modules": {"name": "bash", "version": "4.*"}}},
{"new": {"Modules": {"version": "3.8.*", "name": "httpd"}},
"old": {"Modules": {"version": "3.7.*", "name": "httpd"}}}]
self.packages_result = [{"new": {"Packages": {"name": "git", "version": "2.13.*"}}, "old": None}]
@classmethod
def tearDownClass(self):
pass
def toml_to_recipe_test(self):
"""Test converting the TOML string to a Recipe object"""
for (toml_str, recipe_dict) in self.input_toml:
result = recipes.recipe_from_toml(toml_str)
self.assertEqual(result, recipe_dict)
def toml_to_recipe_fail_test(self):
"""Test trying to convert a non-TOML string to a Recipe"""
with self.assertRaises(TomlError):
recipes.recipe_from_toml("This is not a TOML string\n")
with self.assertRaises(recipes.RecipeError):
recipes.recipe_from_toml('name = "a failed toml string"\n')
def recipe_to_toml_test(self):
"""Test converting a Recipe object to a TOML string"""
# In order to avoid problems from matching strings we convert to TOML and
# then back so compare the Recipes.
for (toml_str, _recipe_dict) in self.input_toml:
# This is tested in toml_to_recipe
recipe_1 = recipes.recipe_from_toml(toml_str)
# Convert the Recipe to TOML and then back to a Recipe
toml_2 = recipe_1.toml()
recipe_2 = recipes.recipe_from_toml(toml_2)
self.assertEqual(recipe_1, recipe_2)
def recipe_bump_version_test(self):
"""Test the Recipe's version bump function"""
# Neither have a version
recipe = recipes.Recipe("test-recipe", "A recipe used for testing", None, None, None)
new_version = recipe.bump_version(None)
self.assertEqual(new_version, "0.0.1")
# Original has a version, new does not
recipe = recipes.Recipe("test-recipe", "A recipe used for testing", None, None, None)
new_version = recipe.bump_version("0.0.1")
self.assertEqual(new_version, "0.0.2")
# Original has no version, new does
recipe = recipes.Recipe("test-recipe", "A recipe used for testing", "0.1.0", None, None)
new_version = recipe.bump_version(None)
self.assertEqual(new_version, "0.1.0")
# New and Original are the same
recipe = recipes.Recipe("test-recipe", "A recipe used for testing", "0.0.1", None, None)
new_version = recipe.bump_version("0.0.1")
self.assertEqual(new_version, "0.0.2")
# New is different from Original
recipe = recipes.Recipe("test-recipe", "A recipe used for testing", "0.1.1", None, None)
new_version = recipe.bump_version("0.0.1")
self.assertEqual(new_version, "0.1.1")
def find_name_test(self):
"""Test the find_name function"""
test_list = [{"name":"dog"}, {"name":"cat"}, {"name":"squirrel"}]
self.assertEqual(recipes.find_name("dog", test_list), {"name":"dog"})
self.assertEqual(recipes.find_name("cat", test_list), {"name":"cat"})
self.assertEqual(recipes.find_name("squirrel", test_list), {"name":"squirrel"})
self.assertIsNone(recipes.find_name("alien", test_list))
def diff_items_test(self):
"""Test the diff_items function"""
self.assertEqual(recipes.diff_items("Modules", self.old_modules, self.new_modules), self.modules_result)
self.assertEqual(recipes.diff_items("Packages", self.old_packages, self.new_packages), self.packages_result)
def recipe_diff_test(self):
"""Test the recipe_diff function"""
old_recipe = recipes.Recipe("test-recipe", "A recipe used for testing", "0.1.1", self.old_modules, self.old_packages)
new_recipe = recipes.Recipe("test-recipe", "A recipe used for testing", "0.3.1", self.new_modules, self.new_packages)
result = [{'new': {'Version': '0.3.1'}, 'old': {'Version': '0.1.1'}},
{'new': {'Module': {'name': 'openssh', 'version': '2.8.1'}}, 'old': None},
{'new': None, 'old': {'Module': {'name': 'bash', 'version': '4.*'}}},
{'new': {'Module': {'name': 'httpd', 'version': '3.8.*'}},
'old': {'Module': {'name': 'httpd', 'version': '3.7.*'}}},
{'new': {'Package': {'name': 'git', 'version': '2.13.*'}}, 'old': None}]
self.assertEqual(recipes.recipe_diff(old_recipe, new_recipe), result)
class GitRecipesTest(unittest.TestCase):
@classmethod
def setUpClass(self):
self.repo_dir = tempfile.mkdtemp(prefix="lorax.test.repo.")
self.repo = recipes.open_or_create_repo(self.repo_dir)
self.results_path = "./tests/pylorax/results/"
self.examples_path = "./tests/pylorax/blueprints/"
self.new_recipe = os.path.join(self.examples_path, 'python-testing.toml')
@classmethod
def tearDownClass(self):
if self.repo is not None:
del self.repo
shutil.rmtree(self.repo_dir)
def tearDown(self):
if os.path.exists(self.new_recipe):
os.remove(self.new_recipe)
def _create_another_recipe(self):
open(self.new_recipe, 'w').write("""name = "python-testing"
description = "A recipe used during testing."
version = "0.0.1"
[[packages]]
name = "python"
version = "2.7.*"
""")
def test_01_repo_creation(self):
"""Test that creating the repository succeeded"""
self.assertNotEqual(self.repo, None)
def test_02_commit_recipe(self):
"""Test committing a Recipe object"""
recipe = recipes.Recipe("test-recipe", "A recipe used for testing", None, None, None)
oid = recipes.commit_recipe(self.repo, "master", recipe)
self.assertNotEqual(oid, None)
def test_03_list_recipe(self):
"""Test listing recipe commits"""
commits = recipes.list_commits(self.repo, "master", "test-recipe.toml")
self.assertEqual(len(commits), 1, "Wrong number of commits.")
self.assertEqual(commits[0].message, "Recipe test-recipe, version 0.0.1 saved.")
self.assertNotEqual(commits[0].timestamp, None, "Timestamp is None")
self.assertEqual(len(commits[0].commit), 40, "Commit hash isn't 40 characters")
self.assertEqual(commits[0].revision, None, "revision is not None")
def test_03_list_commits_commit_time_val_error(self):
"""Test listing recipe commits which raise CommitTimeValError"""
with mock.patch('pylorax.api.recipes.GLib.DateTime.to_timeval', return_value=False):
commits = recipes.list_commits(self.repo, "master", "test-recipe.toml")
self.assertEqual(len(commits), 0, "Wrong number of commits.")
def test_04_commit_recipe_file(self):
"""Test committing a TOML file"""
recipe_path = joinpaths(self.results_path, "full-recipe.toml")
oid = recipes.commit_recipe_file(self.repo, "master", recipe_path)
self.assertNotEqual(oid, None)
commits = recipes.list_commits(self.repo, "master", "http-server.toml")
self.assertEqual(len(commits), 1, "Wrong number of commits: %s" % commits)
def test_04_commit_recipe_file_handles_internal_ioerror(self):
"""Test committing a TOML raises RecipeFileError on internal IOError"""
recipe_path = joinpaths(self.results_path, "non-existing-file.toml")
with self.assertRaises(recipes.RecipeFileError):
recipes.commit_recipe_file(self.repo, "master", recipe_path)
def test_05_commit_toml_dir(self):
"""Test committing a directory of TOML files"""
# first verify that the newly created file isn't present
old_commits = recipes.list_commits(self.repo, "master", "python-testing.toml")
self.assertEqual(len(old_commits), 0, "Wrong number of commits: %s" % old_commits)
# then create it and commit the entire directory
self._create_another_recipe()
recipes.commit_recipe_directory(self.repo, "master", self.examples_path)
# verify that the newly created file is already in the repository
new_commits = recipes.list_commits(self.repo, "master", "python-testing.toml")
self.assertEqual(len(new_commits), 1, "Wrong number of commits: %s" % new_commits)
# again make sure new_commits != old_commits
self.assertGreater(len(new_commits), len(old_commits),
"New commits shoud differ from old commits")
def test_05_commit_recipe_directory_handling_internal_exceptions(self):
"""Test committing a directory of TOML files while handling internal exceptions"""
# first verify that the newly created file isn't present
old_commits = recipes.list_commits(self.repo, "master", "python-testing.toml")
self.assertEqual(len(old_commits), 0, "Wrong number of commits: %s" % old_commits)
# then create it and commit the entire directory
self._create_another_recipe()
# try to commit while raising RecipeFileError
with mock.patch('pylorax.api.recipes.commit_recipe_file', side_effect=recipes.RecipeFileError('TESTING')):
recipes.commit_recipe_directory(self.repo, "master", self.examples_path)
# try to commit while raising TomlError
with mock.patch('pylorax.api.recipes.commit_recipe_file', side_effect=TomlError('TESTING', 0, 0, '__test__')):
recipes.commit_recipe_directory(self.repo, "master", self.examples_path)
# verify again that the newly created file isn't present b/c we raised an exception
new_commits = recipes.list_commits(self.repo, "master", "python-testing.toml")
self.assertEqual(len(new_commits), 0, "Wrong number of commits: %s" % new_commits)
def test_06_read_recipe(self):
"""Test reading a recipe from a commit"""
commits = recipes.list_commits(self.repo, "master", "http-server.toml")
self.assertEqual(len(commits), 1, "Wrong number of commits: %s" % commits)
recipe = recipes.read_recipe_commit(self.repo, "master", "http-server")
self.assertNotEqual(recipe, None)
self.assertEqual(recipe["name"], "http-server")
# Read by commit id
recipe = recipes.read_recipe_commit(self.repo, "master", "http-server", commits[0].commit)
self.assertNotEqual(recipe, None)
self.assertEqual(recipe["name"], "http-server")
# Read the recipe and its commit id
(commit_id, recipe) = recipes.read_recipe_and_id(self.repo, "master", "http-server", commits[0].commit)
self.assertEqual(commit_id, commits[0].commit)
def test_07_tag_commit(self):
"""Test tagging the most recent commit of a recipe"""
result = recipes.tag_file_commit(self.repo, "master", "not-a-file")
self.assertEqual(result, None)
result = recipes.tag_recipe_commit(self.repo, "master", "http-server")
self.assertNotEqual(result, None)
commits = recipes.list_commits(self.repo, "master", "http-server.toml")
self.assertEqual(len(commits), 1, "Wrong number of commits: %s" % commits)
self.assertEqual(commits[0].revision, 1)
def test_08_delete_recipe(self):
"""Test deleting a file from a branch"""
oid = recipes.delete_recipe(self.repo, "master", "http-server")
self.assertNotEqual(oid, None)
master_files = recipes.list_branch_files(self.repo, "master")
self.assertEqual("http-server.toml" in master_files, False)
def test_09_revert_commit(self):
"""Test reverting a file on a branch"""
commits = recipes.list_commits(self.repo, "master", "http-server.toml")
revert_to = commits[0].commit
oid = recipes.revert_recipe(self.repo, "master", "http-server", revert_to)
self.assertNotEqual(oid, None)
commits = recipes.list_commits(self.repo, "master", "http-server.toml")
self.assertEqual(len(commits), 2, "Wrong number of commits: %s" % commits)
self.assertEqual(commits[0].message, "http-server.toml reverted to commit %s" % revert_to)
def test_10_tag_new_commit(self):
"""Test tagging a newer commit of a recipe"""
recipe = recipes.read_recipe_commit(self.repo, "master", "http-server")
recipe["description"] = "A modified description"
oid = recipes.commit_recipe(self.repo, "master", recipe)
self.assertNotEqual(oid, None)
# Tag the new commit
result = recipes.tag_recipe_commit(self.repo, "master", "http-server")
self.assertNotEqual(result, None)
commits = recipes.list_commits(self.repo, "master", "http-server.toml")
self.assertEqual(len(commits), 3, "Wrong number of commits: %s" % commits)
self.assertEqual(commits[0].revision, 2)
class ExistingGitRepoRecipesTest(GitRecipesTest):
@classmethod
def setUpClass(self):
# will initialize the git repository in the parent class
super(ExistingGitRepoRecipesTest, self).setUpClass()
# reopen the repository again so that tests are executed
# against the existing repo one more time.
self.repo = recipes.open_or_create_repo(self.repo_dir)
class GetRevisionFromTagTests(unittest.TestCase):
def test_01_valid_tag(self):
revision = recipes.get_revision_from_tag('branch/filename/r123')
self.assertEqual(123, revision)
def test_02_invalid_tag_not_a_number(self):
revision = recipes.get_revision_from_tag('branch/filename/rABC')
self.assertIsNone(revision)
def test_02_invalid_tag_missing_revision_string(self):
revision = recipes.get_revision_from_tag('branch/filename/mybranch')
self.assertIsNone(revision)

View File

@ -1,962 +0,0 @@
#
# Copyright (C) 2017 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import os
from glob import glob
import shutil
import tempfile
import time
from threading import Lock
import unittest
from flask import json
import pytoml as toml
from pylorax.api.config import configure, make_yum_dirs, make_queue_dirs
from pylorax.api.queue import start_queue_monitor
from pylorax.api.recipes import open_or_create_repo, commit_recipe_directory
from pylorax.api.server import server, GitLock, YumLock
from pylorax.api.yumbase import get_base_object
from pylorax.sysutils import joinpaths
class ServerTestCase(unittest.TestCase):
@classmethod
def setUpClass(self):
repo_dir = tempfile.mkdtemp(prefix="lorax.test.repo.")
server.config["REPO_DIR"] = repo_dir
repo = open_or_create_repo(server.config["REPO_DIR"])
server.config["GITLOCK"] = GitLock(repo=repo, lock=Lock(), dir=repo_dir)
server.config["COMPOSER_CFG"] = configure(root_dir=repo_dir, test_config=True)
os.makedirs(joinpaths(server.config["COMPOSER_CFG"].get("composer", "share_dir"), "composer"))
errors = make_queue_dirs(server.config["COMPOSER_CFG"], 0)
if errors:
raise RuntimeError("\n".join(errors))
make_yum_dirs(server.config["COMPOSER_CFG"])
# copy over the test yum repositories
yum_repo_dir = server.config["COMPOSER_CFG"].get("composer", "repo_dir")
for f in glob("./tests/pylorax/repos/*.repo"):
shutil.copy2(f, yum_repo_dir)
# yum repo baseurl has to point to an absolute directory, so we use /tmp/lorax-empty-repo/ in the files
# and create an empty repository
os.makedirs("/tmp/lorax-empty-repo/")
os.system("createrepo_c /tmp/lorax-empty-repo/")
yb = get_base_object(server.config["COMPOSER_CFG"])
server.config["YUMLOCK"] = YumLock(yb=yb, lock=Lock())
server.config['TESTING'] = True
self.server = server.test_client()
self.repo_dir = repo_dir
self.examples_path = "./tests/pylorax/blueprints/"
# Copy the shared files over to the directory tree we are using
share_path = "./share/composer/"
for f in glob(joinpaths(share_path, "*")):
shutil.copy(f, joinpaths(server.config["COMPOSER_CFG"].get("composer", "share_dir"), "composer"))
# Import the example blueprints
commit_recipe_directory(server.config["GITLOCK"].repo, "master", self.examples_path)
start_queue_monitor(server.config["COMPOSER_CFG"], 0, 0)
@classmethod
def tearDownClass(self):
shutil.rmtree(server.config["REPO_DIR"])
shutil.rmtree("/tmp/lorax-empty-repo/")
def test_01_status(self):
"""Test the /api/status route"""
status_fields = ["build", "api", "db_version", "schema_version", "db_supported", "backend"]
resp = self.server.get("/api/status")
data = json.loads(resp.data)
# Just make sure the fields are present
self.assertEqual(sorted(data.keys()), sorted(status_fields))
def test_02_blueprints_list(self):
"""Test the /api/v0/blueprints/list route"""
list_dict = {"blueprints":["atlas", "custom-base", "development", "glusterfs", "http-server",
"jboss", "kubernetes"], "limit":20, "offset":0, "total":7}
resp = self.server.get("/api/v0/blueprints/list")
data = json.loads(resp.data)
self.assertEqual(data, list_dict)
def test_03_blueprints_info(self):
"""Test the /api/v0/blueprints/info route"""
info_dict_1 = {"changes":[{"changed":False, "name":"http-server"}],
"errors":[],
"blueprints":[{"description":"An example http server with PHP and MySQL support.",
"modules":[{"name":"httpd", "version":"2.4.*"},
{"name":"mod_auth_kerb", "version":"5.4"},
{"name":"mod_ssl", "version":"2.4.*"},
{"name":"php", "version":"5.4.*"},
{"name": "php-mysql", "version":"5.4.*"}],
"name":"http-server",
"packages": [{"name":"openssh-server", "version": "7.*"},
{"name": "rsync", "version": "3.1.*"},
{"name": "tmux", "version": "1.8"}],
"version": "0.0.1"}]}
resp = self.server.get("/api/v0/blueprints/info/http-server")
data = json.loads(resp.data)
self.assertEqual(data, info_dict_1)
info_dict_2 = {"changes":[{"changed":False, "name":"glusterfs"},
{"changed":False, "name":"http-server"}],
"errors":[],
"blueprints":[{"description": "An example GlusterFS server with samba",
"modules":[{"name":"glusterfs", "version":"3.8.*"},
{"name":"glusterfs-cli", "version":"3.8.*"}],
"name":"glusterfs",
"packages":[{"name":"samba", "version":"4.7.*"}],
"version": "0.0.1"},
{"description":"An example http server with PHP and MySQL support.",
"modules":[{"name":"httpd", "version":"2.4.*"},
{"name":"mod_auth_kerb", "version":"5.4"},
{"name":"mod_ssl", "version":"2.4.*"},
{"name":"php", "version":"5.4.*"},
{"name": "php-mysql", "version":"5.4.*"}],
"name":"http-server",
"packages": [{"name":"openssh-server", "version": "7.*"},
{"name": "rsync", "version": "3.1.*"},
{"name": "tmux", "version": "1.8"}],
"version": "0.0.1"},
]}
resp = self.server.get("/api/v0/blueprints/info/http-server,glusterfs")
data = json.loads(resp.data)
self.assertEqual(data, info_dict_2)
info_dict_3 = {"changes":[],
"errors":["missing-blueprint: No commits for missing-blueprint.toml on the master branch."],
"blueprints":[]
}
resp = self.server.get("/api/v0/blueprints/info/missing-blueprint")
data = json.loads(resp.data)
self.assertEqual(data, info_dict_3)
def test_04_blueprints_changes(self):
"""Test the /api/v0/blueprints/changes route"""
resp = self.server.get("/api/v0/blueprints/changes/http-server")
data = json.loads(resp.data)
# Can't compare a whole dict since commit hash and timestamps will change.
# Should have 1 commit (for now), with a matching message.
self.assertEqual(data["limit"], 20)
self.assertEqual(data["offset"], 0)
self.assertEqual(len(data["errors"]), 0)
self.assertEqual(len(data["blueprints"]), 1)
self.assertEqual(data["blueprints"][0]["name"], "http-server")
self.assertEqual(len(data["blueprints"][0]["changes"]), 1)
def test_04a_blueprints_diff_empty_ws(self):
"""Test the /api/v0/diff/NEWEST/WORKSPACE with empty workspace"""
resp = self.server.get("/api/v0/blueprints/diff/glusterfs/NEWEST/WORKSPACE")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data, {"diff": []})
def test_05_blueprints_new_json(self):
"""Test the /api/v0/blueprints/new route with json blueprint"""
test_blueprint = {"description": "An example GlusterFS server with samba",
"name":"glusterfs",
"version": "0.2.0",
"modules":[{"name":"glusterfs", "version":"3.8.*"},
{"name":"glusterfs-cli", "version":"3.8.*"}],
"packages":[{"name":"samba", "version":"4.7.*"},
{"name":"tmux", "version":"1.8"}]}
resp = self.server.post("/api/v0/blueprints/new",
data=json.dumps(test_blueprint),
content_type="application/json")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
resp = self.server.get("/api/v0/blueprints/info/glusterfs")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
blueprints = data.get("blueprints")
self.assertEqual(len(blueprints), 1)
self.assertEqual(blueprints[0], test_blueprint)
def test_06_blueprints_new_toml(self):
"""Test the /api/v0/blueprints/new route with toml blueprint"""
test_blueprint = open(joinpaths(self.examples_path, "glusterfs.toml"), "rb").read()
resp = self.server.post("/api/v0/blueprints/new",
data=test_blueprint,
content_type="text/x-toml")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
resp = self.server.get("/api/v0/blueprints/info/glusterfs")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
blueprints = data.get("blueprints")
self.assertEqual(len(blueprints), 1)
# Returned blueprint has had its version bumped to 0.2.1
test_blueprint = toml.loads(test_blueprint)
test_blueprint["version"] = "0.2.1"
self.assertEqual(blueprints[0], test_blueprint)
def test_07_blueprints_ws_json(self):
"""Test the /api/v0/blueprints/workspace route with json blueprint"""
test_blueprint = {"description": "An example GlusterFS server with samba, ws version",
"name":"glusterfs",
"version": "0.3.0",
"modules":[{"name":"glusterfs", "version":"3.8.*"},
{"name":"glusterfs-cli", "version":"3.8.*"}],
"packages":[{"name":"samba", "version":"4.7.*"},
{"name":"tmux", "version":"1.8"}]}
resp = self.server.post("/api/v0/blueprints/workspace",
data=json.dumps(test_blueprint),
content_type="application/json")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
resp = self.server.get("/api/v0/blueprints/info/glusterfs")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
blueprints = data.get("blueprints")
self.assertEqual(len(blueprints), 1)
self.assertEqual(blueprints[0], test_blueprint)
changes = data.get("changes")
self.assertEqual(len(changes), 1)
self.assertEqual(changes[0], {"name":"glusterfs", "changed":True})
def test_08_blueprints_ws_toml(self):
"""Test the /api/v0/blueprints/workspace route with toml blueprint"""
test_blueprint = {"description": "An example GlusterFS server with samba, ws version",
"name":"glusterfs",
"version": "0.4.0",
"modules":[{"name":"glusterfs", "version":"3.8.*"},
{"name":"glusterfs-cli", "version":"3.8.*"}],
"packages":[{"name":"samba", "version":"4.7.*"},
{"name":"tmux", "version":"1.8"}]}
resp = self.server.post("/api/v0/blueprints/workspace",
data=json.dumps(test_blueprint),
content_type="application/json")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
resp = self.server.get("/api/v0/blueprints/info/glusterfs")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
blueprints = data.get("blueprints")
self.assertEqual(len(blueprints), 1)
self.assertEqual(blueprints[0], test_blueprint)
changes = data.get("changes")
self.assertEqual(len(changes), 1)
self.assertEqual(changes[0], {"name":"glusterfs", "changed":True})
def test_09_blueprints_ws_delete(self):
"""Test DELETE /api/v0/blueprints/workspace/<blueprint_name>"""
# Write to the workspace first, just use the test_blueprints_ws_json test for this
self.test_07_blueprints_ws_json()
# Delete it
resp = self.server.delete("/api/v0/blueprints/workspace/glusterfs")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
# Make sure it isn't the workspace copy and that changed is False
resp = self.server.get("/api/v0/blueprints/info/glusterfs")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
blueprints = data.get("blueprints")
self.assertEqual(len(blueprints), 1)
self.assertEqual(blueprints[0]["version"], "0.2.1")
changes = data.get("changes")
self.assertEqual(len(changes), 1)
self.assertEqual(changes[0], {"name":"glusterfs", "changed":False})
def test_10_blueprints_delete(self):
"""Test DELETE /api/v0/blueprints/delete/<blueprint_name>"""
resp = self.server.delete("/api/v0/blueprints/delete/glusterfs")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
# Make sure glusterfs is no longer in the list of blueprints
resp = self.server.get("/api/v0/blueprints/list")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
blueprints = data.get("blueprints")
self.assertEqual("glusterfs" in blueprints, False)
def test_11_blueprints_undo(self):
"""Test POST /api/v0/blueprints/undo/<blueprint_name>/<commit>"""
resp = self.server.get("/api/v0/blueprints/changes/glusterfs")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
# Revert it to the first commit
blueprints = data.get("blueprints")
self.assertNotEqual(blueprints, None)
changes = blueprints[0].get("changes")
self.assertEqual(len(changes) > 1, True)
# Revert it to the first commit
commit = changes[-1]["commit"]
resp = self.server.post("/api/v0/blueprints/undo/glusterfs/%s" % commit)
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
resp = self.server.get("/api/v0/blueprints/changes/glusterfs")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
blueprints = data.get("blueprints")
self.assertNotEqual(blueprints, None)
changes = blueprints[0].get("changes")
self.assertEqual(len(changes) > 1, True)
expected_msg = "glusterfs.toml reverted to commit %s" % commit
self.assertEqual(changes[0]["message"], expected_msg)
def test_12_blueprints_tag(self):
"""Test POST /api/v0/blueprints/tag/<blueprint_name>"""
resp = self.server.post("/api/v0/blueprints/tag/glusterfs")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
resp = self.server.get("/api/v0/blueprints/changes/glusterfs")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
# Revert it to the first commit
blueprints = data.get("blueprints")
self.assertNotEqual(blueprints, None)
changes = blueprints[0].get("changes")
self.assertEqual(len(changes) > 1, True)
self.assertEqual(changes[0]["revision"], 1)
def test_13_blueprints_diff(self):
"""Test /api/v0/blueprints/diff/<blueprint_name>/<from_commit>/<to_commit>"""
resp = self.server.get("/api/v0/blueprints/changes/glusterfs")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
blueprints = data.get("blueprints")
self.assertNotEqual(blueprints, None)
changes = blueprints[0].get("changes")
self.assertEqual(len(changes) >= 2, True)
from_commit = changes[1].get("commit")
self.assertNotEqual(from_commit, None)
to_commit = changes[0].get("commit")
self.assertNotEqual(to_commit, None)
# Get the differences between the two commits
resp = self.server.get("/api/v0/blueprints/diff/glusterfs/%s/%s" % (from_commit, to_commit))
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data, {"diff": [{"new": {"Version": "0.0.1"}, "old": {"Version": "0.2.1"}}]})
# Write to the workspace and check the diff
test_blueprint = {"description": "An example GlusterFS server with samba, ws version",
"name":"glusterfs",
"version": "0.3.0",
"modules":[{"name":"glusterfs", "version":"3.8.*"},
{"name":"glusterfs-cli", "version":"3.8.*"}],
"packages":[{"name":"samba", "version":"4.7.*"},
{"name":"tmux", "version":"1.8"}]}
resp = self.server.post("/api/v0/blueprints/workspace",
data=json.dumps(test_blueprint),
content_type="application/json")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
# Get the differences between the newest commit and the workspace
resp = self.server.get("/api/v0/blueprints/diff/glusterfs/NEWEST/WORKSPACE")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
result = {"diff": [{"new": {"Description": "An example GlusterFS server with samba, ws version"},
"old": {"Description": "An example GlusterFS server with samba"}},
{"new": {"Version": "0.3.0"},
"old": {"Version": "0.0.1"}},
{"new": {"Package": {"version": "1.8", "name": "tmux"}},
"old": None}]}
self.assertEqual(data, result)
def test_14_blueprints_depsolve(self):
"""Test /api/v0/blueprints/depsolve/<blueprint_names>"""
resp = self.server.get("/api/v0/blueprints/depsolve/glusterfs")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
blueprints = data.get("blueprints")
self.assertNotEqual(blueprints, None)
self.assertEqual(len(blueprints), 1)
self.assertTrue(len(blueprints[0]["blueprint"]["modules"]) > 0)
self.assertEqual(blueprints[0]["blueprint"]["name"], "glusterfs")
self.assertEqual(len(blueprints[0]["dependencies"]) > 10, True)
self.assertFalse(data.get("errors"))
def test_14_blueprints_depsolve_empty(self):
"""Test /api/v0/blueprints/depsolve/<blueprint_names> on empty blueprint"""
test_blueprint = {"description": "An empty blueprint",
"name":"void",
"version": "0.1.0"}
resp = self.server.post("/api/v0/blueprints/new",
data=json.dumps(test_blueprint),
content_type="application/json")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
resp = self.server.get("/api/v0/blueprints/depsolve/void")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
blueprints = data.get("blueprints")
self.assertNotEqual(blueprints, None)
self.assertEqual(len(blueprints), 1)
self.assertEqual(blueprints[0]["blueprint"]["name"], "void")
self.assertEqual(blueprints[0]["blueprint"]["packages"], [])
self.assertEqual(blueprints[0]["blueprint"]["modules"], [])
self.assertEqual(blueprints[0]["dependencies"], [])
self.assertFalse(data.get("errors"))
def test_15_blueprints_freeze(self):
"""Test /api/v0/blueprints/freeze/<blueprint_names>"""
resp = self.server.get("/api/v0/blueprints/freeze/glusterfs")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
blueprints = data.get("blueprints")
self.assertNotEqual(blueprints, None)
self.assertEqual(len(blueprints), 1)
self.assertTrue(len(blueprints[0]["blueprint"]["modules"]) > 0)
self.assertEqual(blueprints[0]["blueprint"]["name"], "glusterfs")
evra = blueprints[0]["blueprint"]["modules"][0]["version"]
self.assertEqual(len(evra) > 10, True)
def test_projects_list(self):
"""Test /api/v0/projects/list"""
resp = self.server.get("/api/v0/projects/list")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
projects = data.get("projects")
self.assertEqual(len(projects) > 10, True)
def test_projects_info(self):
"""Test /api/v0/projects/info/<project_names>"""
resp = self.server.get("/api/v0/projects/info/bash")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
projects = data.get("projects")
self.assertEqual(len(projects), 1)
self.assertTrue(len(projects[0]["builds"]) > 0)
self.assertEqual(projects[0]["name"], "bash")
self.assertEqual(projects[0]["builds"][0]["source"]["license"], "GPLv3+")
def test_projects_depsolve(self):
"""Test /api/v0/projects/depsolve/<project_names>"""
resp = self.server.get("/api/v0/projects/depsolve/bash")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
deps = data.get("projects")
self.assertEqual(len(deps) > 10, True)
self.assertEqual(deps[2]["name"], "basesystem")
def test_projects_source_00_list(self):
"""Test /api/v0/projects/source/list"""
resp = self.server.get("/api/v0/projects/source/list")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["sources"], ["base", "epel", "extras", "lorax-1", "lorax-2", "lorax-3", "lorax-4", "other-repo", "single-repo", "updates"])
def test_projects_source_00_info(self):
"""Test /api/v0/projects/source/info"""
resp = self.server.get("/api/v0/projects/source/info/single-repo")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
sources = data["sources"]
self.assertTrue("single-repo" in sources)
def test_projects_source_00_new_json(self):
"""Test /api/v0/projects/source/new with a new json source"""
json_source = open("./tests/pylorax/source/test-repo.json").read()
self.assertTrue(len(json_source) > 0)
resp = self.server.post("/api/v0/projects/source/new",
data=json_source,
content_type="application/json")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
# Is it listed?
resp = self.server.get("/api/v0/projects/source/list")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
sources = data["sources"]
self.assertTrue("new-repo-1" in sources)
def test_projects_source_00_new_toml(self):
"""Test /api/v0/projects/source/new with a new toml source"""
toml_source = open("./tests/pylorax/source/test-repo.toml").read()
self.assertTrue(len(toml_source) > 0)
resp = self.server.post("/api/v0/projects/source/new",
data=toml_source,
content_type="text/x-toml")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
# Is it listed?
resp = self.server.get("/api/v0/projects/source/list")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
sources = data["sources"]
self.assertTrue("new-repo-2" in sources)
def test_projects_source_00_replace(self):
"""Test /api/v0/projects/source/new with a replacement source"""
toml_source = open("./tests/pylorax/source/replace-repo.toml").read()
self.assertTrue(len(toml_source) > 0)
resp = self.server.post("/api/v0/projects/source/new",
data=toml_source,
content_type="text/x-toml")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
# Check to see if it was really changed
resp = self.server.get("/api/v0/projects/source/info/single-repo")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
sources = data["sources"]
self.assertTrue("single-repo" in sources)
repo = sources["single-repo"]
self.assertEqual(repo["check_ssl"], False)
self.assertTrue("gpgkey_urls" not in repo)
def test_projects_source_00_bad_url(self):
"""Test /api/v0/projects/source/new with a new source that has an invalid url"""
toml_source = open("./tests/pylorax/source/bad-repo.toml").read()
self.assertTrue(len(toml_source) > 0)
resp = self.server.post("/api/v0/projects/source/new",
data=toml_source,
content_type="text/x-toml")
self.assertEqual(resp.status_code, 400)
data = json.loads(resp.data)
self.assertEqual(data["status"], False)
def test_projects_source_01_delete_system(self):
"""Test /api/v0/projects/source/delete a system source"""
resp = self.server.delete("/api/v0/projects/source/delete/base")
self.assertEqual(resp.status_code, 400)
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], False)
# Make sure base is still listed
resp = self.server.get("/api/v0/projects/source/list")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertTrue("base" in data["sources"])
def test_projects_source_02_delete_single(self):
"""Test /api/v0/projects/source/delete a single source"""
resp = self.server.delete("/api/v0/projects/source/delete/single-repo")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data, {"status":True})
# Make sure single-repo isn't listed
resp = self.server.get("/api/v0/projects/source/list")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertTrue("single-repo" not in data["sources"])
def test_projects_source_03_delete_unknown(self):
"""Test /api/v0/projects/source/delete an unknown source"""
resp = self.server.delete("/api/v0/projects/source/delete/unknown-repo")
self.assertEqual(resp.status_code, 400)
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], False)
def test_projects_source_04_delete_multi(self):
"""Test /api/v0/projects/source/delete a source from a file with multiple sources"""
resp = self.server.delete("/api/v0/projects/source/delete/lorax-3")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data, {"status":True})
# Make sure single-repo isn't listed
resp = self.server.get("/api/v0/projects/source/list")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertTrue("lorax-3" not in data["sources"])
def test_modules_list(self):
"""Test /api/v0/modules/list"""
resp = self.server.get("/api/v0/modules/list")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
modules = data.get("modules")
self.assertEqual(len(modules) > 10, True)
self.assertEqual(modules[0]["group_type"], "rpm")
resp = self.server.get("/api/v0/modules/list/d*")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
modules = data.get("modules")
self.assertEqual(len(modules) > 0, True)
self.assertEqual(modules[0]["name"].startswith("d"), True)
def test_modules_info(self):
"""Test /api/v0/modules/info"""
resp = self.server.get("/api/v0/modules/info/bash")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
modules = data.get("modules")
self.assertEqual(len(modules), 1)
self.assertEqual(modules[0]["name"], "bash")
self.assertEqual(modules[0]["dependencies"][2]["name"], "basesystem")
def test_blueprint_new_branch(self):
"""Test the /api/v0/blueprints/new route with a new branch"""
test_blueprint = {"description": "An example GlusterFS server with samba",
"name":"glusterfs",
"version": "0.2.0",
"modules":[{"name":"glusterfs", "version":"3.8.*"},
{"name":"glusterfs-cli", "version":"3.8.*"}],
"packages":[{"name":"samba", "version":"4.7.*"},
{"name":"tmux", "version":"1.8"}]}
resp = self.server.post("/api/v0/blueprints/new?branch=test",
data=json.dumps(test_blueprint),
content_type="application/json")
data = json.loads(resp.data)
self.assertEqual(data, {"status":True})
resp = self.server.get("/api/v0/blueprints/info/glusterfs?branch=test")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
blueprints = data.get("blueprints")
self.assertEqual(len(blueprints), 1)
self.assertEqual(blueprints[0], test_blueprint)
def assert_documentation(self, response):
"""
Assert response containing documentation from /api/doc/ is
valid *without* comparing to the actual file on disk.
"""
self.assertEqual(200, response.status_code)
self.assertTrue(len(response.data) > 1024)
# look for some well known strings inside the documentation
self.assertRegexpMatches(response.data, r"Lorax [\d.]+ documentation")
self.assertRegexpMatches(response.data, r"Copyright \d+, Red Hat, Inc.")
def test_api_docs(self):
"""Test the /api/docs/"""
resp = self.server.get("/api/docs/")
self.assert_documentation(resp)
def test_api_docs_with_existing_path(self):
"""Test the /api/docs/modules.html"""
resp = self.server.get("/api/docs/modules.html")
self.assert_documentation(resp)
def wait_for_status(self, uuid, wait_status):
"""Helper function that waits for a status
:param uuid: UUID of the build to check
:type uuid: str
:param wait_status: List of statuses to exit on
:type wait_status: list of str
:returns: True if status was found, False if it timed out
:rtype: bool
This will time out after 60 seconds
"""
start = time.time()
while True:
resp = self.server.get("/api/v0/compose/info/%s" % uuid)
data = json.loads(resp.data)
self.assertNotEqual(data, None)
queue_status = data.get("queue_status")
if queue_status in wait_status:
return True
if time.time() > start + 60:
return False
time.sleep(1)
def test_compose_01_types(self):
"""Test the /api/v0/compose/types route"""
resp = self.server.get("/api/v0/compose/types")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual({"name": "tar", "enabled": True} in data["types"], True)
def test_compose_02_bad_type(self):
"""Test that using an unsupported image type failes"""
test_compose = {"blueprint_name": "glusterfs",
"compose_type": "snakes",
"branch": "master"}
resp = self.server.post("/api/v0/compose?test=1",
data=json.dumps(test_compose),
content_type="application/json")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], False, "Failed to fail to start test compose: %s" % data)
self.assertEqual(data["errors"], ["Invalid compose type (snakes), must be one of ['ext4-filesystem', 'live-iso', 'partitioned-disk', 'qcow2', 'tar']"],
"Failed to get errors: %s" % data)
def test_compose_03_status_fail(self):
"""Test that requesting a status for a bad uuid is empty"""
resp = self.server.get("/api/v0/compose/status/NO-UUID-TO-SEE-HERE")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["uuids"], [], "Failed to get empty result bad uuid: %s" % data)
def test_compose_04_cancel_fail(self):
"""Test that requesting a cancel for a bad uuid fails."""
resp = self.server.delete("/api/v0/compose/cancel/NO-UUID-TO-SEE-HERE")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], False, "Failed to get an error for a bad uuid: %s" % data)
self.assertEqual(data["errors"], ["NO-UUID-TO-SEE-HERE is not a valid build uuid"], "Failed to get errors: %s" % data)
def test_compose_05_delete_fail(self):
"""Test that requesting a delete for a bad uuid fails."""
resp = self.server.delete("/api/v0/compose/delete/NO-UUID-TO-SEE-HERE")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["errors"], ["no-uuid-to-see-here is not a valid build uuid"],
"Failed to get an error for a bad uuid: %s" % data)
def test_compose_06_info_fail(self):
"""Test that requesting info for a bad uuid fails."""
resp = self.server.get("/api/v0/compose/info/NO-UUID-TO-SEE-HERE")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], False, "Failed to get an error for a bad uuid: %s" % data)
self.assertEqual(data["errors"], ["NO-UUID-TO-SEE-HERE is not a valid build_id"],
"Failed to get errors: %s" % data)
def test_compose_07_metadata_fail(self):
"""Test that requesting metadata for a bad uuid fails."""
resp = self.server.get("/api/v0/compose/metadata/NO-UUID-TO-SEE-HERE")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], False, "Failed to get an error for a bad uuid: %s" % data)
self.assertEqual(data["errors"], ["NO-UUID-TO-SEE-HERE is not a valid build uuid"],
"Failed to get errors: %s" % data)
def test_compose_08_results_fail(self):
"""Test that requesting results for a bad uuid fails."""
resp = self.server.get("/api/v0/compose/results/NO-UUID-TO-SEE-HERE")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], False, "Failed to get an error for a bad uuid: %s" % data)
self.assertEqual(data["errors"], ["NO-UUID-TO-SEE-HERE is not a valid build uuid"], "Failed to get errors: %s" % data)
def test_compose_09_logs_fail(self):
"""Test that requesting logs for a bad uuid fails."""
resp = self.server.get("/api/v0/compose/logs/NO-UUID-TO-SEE-HERE")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], False, "Failed to get an error for a bad uuid: %s" % data)
self.assertEqual(data["errors"], ["NO-UUID-TO-SEE-HERE is not a valid build uuid"],
"Failed to get errors: %s" % data)
def test_compose_10_log_fail(self):
"""Test that requesting log for a bad uuid fails."""
resp = self.server.get("/api/v0/compose/log/NO-UUID-TO-SEE-HERE")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], False, "Failed to get an error for a bad uuid: %s" % data)
self.assertEqual(data["errors"], ["NO-UUID-TO-SEE-HERE is not a valid build uuid"],
"Failed to get errors: %s" % data)
def test_compose_11_create_failed(self):
"""Test the /api/v0/compose routes with a failed test compose"""
test_compose = {"blueprint_name": "glusterfs",
"compose_type": "tar",
"branch": "master"}
resp = self.server.post("/api/v0/compose?test=1",
data=json.dumps(test_compose),
content_type="application/json")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], True, "Failed to start test compose: %s" % data)
build_id = data["build_id"]
# Is it in the queue list (either new or run is fine, based on timing)
resp = self.server.get("/api/v0/compose/queue")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
ids = [e["id"] for e in data["new"] + data["run"]]
self.assertEqual(build_id in ids, True, "Failed to add build to the queue")
# Wait for it to start
self.assertEqual(self.wait_for_status(build_id, ["RUNNING"]), True, "Failed to start test compose")
# Wait for it to finish
self.assertEqual(self.wait_for_status(build_id, ["FAILED"]), True, "Failed to finish test compose")
resp = self.server.get("/api/v0/compose/info/%s" % build_id)
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["queue_status"], "FAILED", "Build not in FAILED state")
# Test the /api/v0/compose/failed route
resp = self.server.get("/api/v0/compose/failed")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
ids = [e["id"] for e in data["failed"]]
self.assertEqual(build_id in ids, True, "Failed build not listed by /compose/failed")
# Test the /api/v0/compose/finished route
resp = self.server.get("/api/v0/compose/finished")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["finished"], [], "Finished build not listed by /compose/finished")
# Test the /api/v0/compose/status/<uuid> route
resp = self.server.get("/api/v0/compose/status/%s" % build_id)
data = json.loads(resp.data)
self.assertNotEqual(data, None)
ids = [(e["id"], e["queue_status"]) for e in data["uuids"]]
self.assertEqual((build_id, "FAILED") in ids, True, "Failed build not listed by /compose/status")
# Test the /api/v0/compose/cancel/<uuid> route
resp = self.server.post("/api/v0/compose?test=1",
data=json.dumps(test_compose),
content_type="application/json")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], True, "Failed to start test compose: %s" % data)
cancel_id = data["build_id"]
# Wait for it to start
self.assertEqual(self.wait_for_status(cancel_id, ["RUNNING"]), True, "Failed to start test compose")
# Cancel the build
resp = self.server.delete("/api/v0/compose/cancel/%s" % cancel_id)
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], True, "Failed to cancel test compose: %s" % data)
# Delete the failed build
# Test the /api/v0/compose/delete/<uuid> route
resp = self.server.delete("/api/v0/compose/delete/%s" % build_id)
data = json.loads(resp.data)
self.assertNotEqual(data, None)
ids = [(e["uuid"], e["status"]) for e in data["uuids"]]
self.assertEqual((build_id, True) in ids, True, "Failed to delete test compose: %s" % data)
# Make sure the failed list is empty
resp = self.server.get("/api/v0/compose/failed")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["failed"], [], "Failed to delete the failed build: %s" % data)
def test_compose_12_create_finished(self):
"""Test the /api/v0/compose routes with a finished test compose"""
test_compose = {"blueprint_name": "custom-base",
"compose_type": "tar",
"branch": "master"}
resp = self.server.post("/api/v0/compose?test=2",
data=json.dumps(test_compose),
content_type="application/json")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["status"], True, "Failed to start test compose: %s" % data)
build_id = data["build_id"]
# Is it in the queue list (either new or run is fine, based on timing)
resp = self.server.get("/api/v0/compose/queue")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
ids = [e["id"] for e in data["new"] + data["run"]]
self.assertEqual(build_id in ids, True, "Failed to add build to the queue")
# Wait for it to start
self.assertEqual(self.wait_for_status(build_id, ["RUNNING"]), True, "Failed to start test compose")
# Wait for it to finish
self.assertEqual(self.wait_for_status(build_id, ["FINISHED"]), True, "Failed to finish test compose")
resp = self.server.get("/api/v0/compose/info/%s" % build_id)
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["queue_status"], "FINISHED", "Build not in FINISHED state")
# Test the /api/v0/compose/finished route
resp = self.server.get("/api/v0/compose/finished")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
ids = [e["id"] for e in data["finished"]]
self.assertEqual(build_id in ids, True, "Finished build not listed by /compose/finished")
# Test the /api/v0/compose/failed route
resp = self.server.get("/api/v0/compose/failed")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["failed"], [], "Failed build not listed by /compose/failed")
# Test the /api/v0/compose/status/<uuid> route
resp = self.server.get("/api/v0/compose/status/%s" % build_id)
data = json.loads(resp.data)
self.assertNotEqual(data, None)
ids = [(e["id"], e["queue_status"]) for e in data["uuids"]]
self.assertEqual((build_id, "FINISHED") in ids, True, "Finished build not listed by /compose/status")
# Test the /api/v0/compose/metadata/<uuid> route
resp = self.server.get("/api/v0/compose/metadata/%s" % build_id)
self.assertEqual(resp.status_code, 200)
self.assertEqual(len(resp.data) > 1024, True)
# Test the /api/v0/compose/results/<uuid> route
resp = self.server.get("/api/v0/compose/results/%s" % build_id)
self.assertEqual(resp.status_code, 200)
self.assertEqual(len(resp.data) > 1024, True)
# Test the /api/v0/compose/image/<uuid> route
resp = self.server.get("/api/v0/compose/image/%s" % build_id)
self.assertEqual(resp.status_code, 200)
self.assertEqual(len(resp.data) > 0, True)
self.assertEqual(resp.data, "TEST IMAGE")
# Examine the final-kickstart.ks for the customizations
# A bit kludgy since it examines the filesystem directly, but that's better than unpacking the metadata
final_ks = open(joinpaths(self.repo_dir, "var/lib/lorax/composer/results/", build_id, "final-kickstart.ks")).read()
# Check for the expected customizations in the kickstart
self.assertTrue("network --hostname=" in final_ks)
self.assertTrue("sshkey --user root" in final_ks)
# Delete the finished build
# Test the /api/v0/compose/delete/<uuid> route
resp = self.server.delete("/api/v0/compose/delete/%s" % build_id)
data = json.loads(resp.data)
self.assertNotEqual(data, None)
ids = [(e["uuid"], e["status"]) for e in data["uuids"]]
self.assertEqual((build_id, True) in ids, True, "Failed to delete test compose: %s" % data)
# Make sure the finished list is empty
resp = self.server.get("/api/v0/compose/finished")
data = json.loads(resp.data)
self.assertNotEqual(data, None)
self.assertEqual(data["finished"], [], "Failed to delete the failed build: %s" % data)

View File

@ -1,90 +0,0 @@
#
# Copyright (C) 2017 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import os
import mock
import shutil
import tempfile
import unittest
import pylorax.api.recipes as recipes
from pylorax.api.workspace import workspace_dir, workspace_read, workspace_write, workspace_delete
from pylorax.sysutils import joinpaths
class WorkspaceTest(unittest.TestCase):
@classmethod
def setUpClass(self):
self.repo_dir = tempfile.mkdtemp(prefix="lorax.test.repo.")
self.repo = recipes.open_or_create_repo(self.repo_dir)
self.results_path = "./tests/pylorax/results/"
self.examples_path = "./tests/pylorax/blueprints/"
recipe_path = joinpaths(self.examples_path, "http-server.toml")
f = open(recipe_path, 'rb')
self.example_recipe = recipes.recipe_from_toml(f.read())
@classmethod
def tearDownClass(self):
if self.repo is not None:
del self.repo
shutil.rmtree(self.repo_dir)
def test_01_repo_creation(self):
"""Test that creating the repository succeeded"""
self.assertNotEqual(self.repo, None)
def test_02_workspace_dir(self):
"""Test the workspace_dir function"""
ws_dir = workspace_dir(self.repo, "master")
self.assertEqual(ws_dir, joinpaths(self.repo_dir, "git", "workspace", "master"))
def test_03_workspace_write(self):
"""Test the workspace_write function"""
# Use an example recipe
workspace_write(self.repo, "master", self.example_recipe)
# The file should have ended up here
ws_recipe_path = joinpaths(self.repo_dir, "git", "workspace", "master", "http-server.toml")
self.assertEqual(os.path.exists(ws_recipe_path), True)
def test_04_workspace_read(self):
"""Test the workspace_read function"""
# The recipe was written by the workspace_write test. Read it and compare with the source recipe.
recipe = workspace_read(self.repo, "master", "http-server")
self.assertEqual(self.example_recipe, recipe)
def test_04_workspace_read_ioerror(self):
"""Test the workspace_read function dealing with internal IOError"""
# The recipe was written by the workspace_write test.
with self.assertRaises(recipes.RecipeFileError):
with mock.patch('pylorax.api.workspace.recipe_from_toml', side_effect=IOError('TESTING')):
workspace_read(self.repo, "master", "http-server")
def test_05_workspace_delete(self):
"""Test the workspace_delete function"""
ws_recipe_path = joinpaths(self.repo_dir, "git", "workspace", "master", "http-server.toml")
self.assertEqual(os.path.exists(ws_recipe_path), True)
workspace_delete(self.repo, "master", "http-server")
self.assertEqual(os.path.exists(ws_recipe_path), False)
def test_05_workspace_delete_non_existing(self):
"""Test the workspace_delete function"""
ws_recipe_path = joinpaths(self.repo_dir, "git", "workspace", "master", "non-existing.toml")
workspace_delete(self.repo, "master", "non-existing")
self.assertFalse(os.path.exists(ws_recipe_path))

View File

@ -1,87 +0,0 @@
#
# Copyright (C) 2018 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import os
import shutil
import tempfile
import unittest
import ConfigParser
from pylorax.api.config import configure, make_yum_dirs
from pylorax.api.yumbase import get_base_object
class YumbaseTest(unittest.TestCase):
@classmethod
def setUpClass(self):
self.tmp_dir = tempfile.mkdtemp(prefix="lorax.test.yumbase.")
conf_file = os.path.join(self.tmp_dir, 'test.conf')
open(conf_file, 'w').write("""[composer]
# releasever different from the current default
releasever = 6
[yum]
proxy = https://proxy.example.com
sslverify = False
[repos]
use_system_repos = False
""")
# will read the above configuration
config = configure(conf_file=conf_file, root_dir=self.tmp_dir)
make_yum_dirs(config)
# will read composer config and store a yum config file
self.yb = get_base_object(config)
# will read the stored yum config file
self.yumconf = ConfigParser.ConfigParser()
self.yumconf.read([config.get("composer", "yum_conf")])
@classmethod
def tearDownClass(self):
shutil.rmtree(self.tmp_dir)
def test_stores_yum_proxy_from_composer_config(self):
self.assertEqual('https://proxy.example.com', self.yumconf.get('main', 'proxy'))
def test_disables_sslverify_if_composer_disables_it(self):
self.assertEqual('0', self.yumconf.get('main', 'sslverify'))
def test_sets_releasever_from_composer(self):
self.assertEqual('6', self.yb.conf.yumvar['releasever'])
def test_doesnt_use_system_repos(self):
# no other repos defined for this test
self.assertEqual({}, self.yb._repos.repos)
class CreateYumDirsTest(unittest.TestCase):
@classmethod
def setUpClass(self):
self.tmp_dir = tempfile.mkdtemp(prefix="lorax.test.yumbase.")
@classmethod
def tearDownClass(self):
shutil.rmtree(self.tmp_dir)
def test_creates_missing_yum_root_directory(self):
config = configure(test_config=True, root_dir=self.tmp_dir)
# will create the above directory if missing
make_yum_dirs(config)
self.assertTrue(os.path.exists(self.tmp_dir + '/var/tmp/composer/yum/root'))

View File

@ -1,32 +0,0 @@
#!/bin/bash
# Note: execute this file from the project root directory
# setup
rm -rf /var/tmp/beakerlib-*/
export top_srcdir=`pwd`
. ./tests/testenv.sh
if [ ! -d "/var/lib/lorax/composer" ]; then
mkdir -p /var/lib/lorax/composer
chown -R root:weldr /var/lib/lorax/
chmod -R 775 /var/lib/lorax/
fi
# start the lorax-composer daemon
./src/sbin/lorax-composer --sharedir ./share/ ./tests/pylorax/blueprints/ &
# wait for the backend to become ready
until curl --unix-socket /run/weldr/api.socket http://localhost:4000/api/status | grep '"db_supported": true'; do
sleep 2
echo "DEBUG: Waiting for backend API to become ready before testing ..."
done;
# invoke cli/ tests
./tests/cli/test_blueprints_sanity.sh
./tests/cli/test_compose_sanity.sh
# look for failures
grep RESULT_STRING /var/tmp/beakerlib-*/TestResults | grep -v PASS && exit 1
# explicit return code for Makefile
exit 0