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:
parent
3a1d7da06e
commit
4f373dcc10
4
Makefile
4
Makefile
@ -36,14 +36,12 @@ test: docs
|
|||||||
sudo mkdir -p $(USER_SITE_PACKAGES)
|
sudo mkdir -p $(USER_SITE_PACKAGES)
|
||||||
sudo cp ./tests/usercustomize.py $(USER_SITE_PACKAGES)
|
sudo cp ./tests/usercustomize.py $(USER_SITE_PACKAGES)
|
||||||
sudo COVERAGE_PROCESS_START=$(PW_DIR)/.coveragerc PYTHONPATH=$(PYTHONPATH):./src/ \
|
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)
|
sudo rm -rf $(USER_SITE_PACKAGES)
|
||||||
|
|
||||||
coverage combine
|
coverage combine
|
||||||
coverage report -m
|
coverage report -m
|
||||||
[ -f "/usr/bin/coveralls" ] && [ -n "$(COVERALLS_REPO_TOKEN)" ] && coveralls || echo
|
[ -f "/usr/bin/coveralls" ] && [ -n "$(COVERALLS_REPO_TOKEN)" ] && coveralls || echo
|
||||||
|
|
||||||
./tests/test_cli.sh
|
|
||||||
|
|
||||||
|
|
||||||
check:
|
check:
|
||||||
|
@ -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
|
|
@ -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
|
|
@ -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)
|
|
@ -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")
|
|
@ -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")
|
|
@ -1,10 +0,0 @@
|
|||||||
name = "atlas"
|
|
||||||
description = "Automatically Tuned Linear Algebra Software"
|
|
||||||
|
|
||||||
[[modules]]
|
|
||||||
name = "atlas"
|
|
||||||
version = "3.10.*"
|
|
||||||
|
|
||||||
[[modules]]
|
|
||||||
name = "numpy"
|
|
||||||
version = "1.7.*"
|
|
@ -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"
|
|
@ -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 = "*"
|
|
@ -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.*"
|
|
@ -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.*"
|
|
@ -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.*"
|
|
@ -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.*"
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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'}]}}
|
|
@ -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"
|
|
@ -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'}
|
|
@ -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.*"
|
|
@ -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'}
|
|
@ -1,3 +0,0 @@
|
|||||||
name = "http-server"
|
|
||||||
description = "An example http server with PHP and MySQL support."
|
|
||||||
version = "0.0.1"
|
|
@ -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'}
|
|
@ -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.*"
|
|
@ -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'}
|
|
@ -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.*"
|
|
@ -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"]
|
|
@ -1,6 +0,0 @@
|
|||||||
name = "single-repo"
|
|
||||||
url = "file:///tmp/lorax-empty-repo/"
|
|
||||||
type = "yum-baseurl"
|
|
||||||
check_ssl = false
|
|
||||||
check_gpg = true
|
|
||||||
gpgkey_urls = []
|
|
@ -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"]}
|
|
@ -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"]
|
|
@ -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")
|
|
||||||
|
|
@ -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'])
|
|
@ -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())
|
|
@ -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)
|
|
@ -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)
|
|
@ -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))
|
|
@ -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'))
|
|
@ -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
|
|
Loading…
Reference in New Issue
Block a user