#!/usr/bin/python
# -*- coding: utf-8 -*-
# This file is part of Cockpit.
#
# Copyright (C) 2015 Red Hat, Inc.
#
# Cockpit is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Cockpit 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Cockpit; If not, see .
import parent
from testlib import *
import os
import subprocess
INSTALL_RPMS = [
"empty-1-0.noarch",
"cockpit-ostree-wip-0.1.noarch",
"cockpit-machines-99999-2.noarch",
]
REPO_LOCATION = "/var/local-repo"
CHECKOUT_LOCATION = "/var/local-tree"
RPM_LOCATION = "/usr/share/rpm"
KEY_ID = "95A8BA1754D0E95E2B3A98A7EE15015654780CBD"
def get_os_name(m):
if m.image == "rhel-atomic":
return "rhel-atomic-host"
elif 'continuous' in m.image:
return 'centos-atomic-host'
else:
return "fedora-atomic"
def ensure_remote_http_port (m, remote="local"):
remote_spec = m.execute(["ostree", "remote", "show-url", remote])
if remote_spec.startswith("http"):
parts = remote_spec.strip().split(":")
port = parts[-1]
else:
m.execute(["ostree", "remote", "delete", remote])
m.execute(["ostree", "remote", "add", remote,
"http://127.0.0.1:12345", "--no-gpg-verify"])
try:
m.execute(["rpm-ostree reload"])
except subprocess.CalledProcessError:
m.execute("systemctl restart rpm-ostreed")
port = 12345
return port
def start_trivial_httpd(m, remote="local", location=REPO_LOCATION):
port = ensure_remote_http_port (m, remote)
script = "cd {0}\nsetsid python -m SimpleHTTPServer {1} >/dev/null 2>&1 < /dev/null &\necho $!".format(location, port)
result = m.execute(script=script,
environment={"PYTHONUNBUFFERED" : "1"})
m.execute(["ostree", "summary", "--repo={}".format(location), "-u"])
m.wait_for_cockpit_running(port=port)
return result.strip()
def stop_trivial_httpd(m, pid):
if pid:
m.execute(["kill", pid])
def generate_new_commit(m, pkg_to_remove):
# Make one change of each type to a new rpm tree
branch = m.execute("ostree refs --repo={0}".format(REPO_LOCATION))
m.upload(["verify/files/{0}.rpm".format(k) for k in INSTALL_RPMS],
"/home/admin/")
# move /usr/etc to /etc, makes rpm installs easier
rpm_etc = os.path.join(CHECKOUT_LOCATION, "etc")
usr_etc = os.path.join(CHECKOUT_LOCATION, "usr", "etc")
m.execute("mv {0} {1}".format(usr_etc, rpm_etc))
# Remove a package
rpm_args = [CHECKOUT_LOCATION, RPM_LOCATION, pkg_to_remove]
m.execute("rpm -e --root {0} --dbpath {1} {2}".format(*rpm_args))
# Install our dummy packages, dbonly
rpm_args[-1] = ' '.join(["{0}.rpm".format(os.path.join("/home/admin", x)) \
for x in INSTALL_RPMS])
m.execute("rpm -U --oldpackage --root {0} --dbpath {1} --justdb {2}".format(*rpm_args))
# move /etc back to /usr/etc to
m.execute("mv {0} {1}".format(rpm_etc, usr_etc))
# Upload a signing key
m.upload(["verify/files/secring.gpg",
"verify/files/pubring.gpg"], "/root/")
commit_args = [REPO_LOCATION, branch.strip(), CHECKOUT_LOCATION, KEY_ID]
command = "ostree commit -s cockpit-tree2 --repo {0} -b {1} --add-metadata-string version=cockpit-base.2 --tree=dir={2} --gpg-sign={3} --gpg-homedir=/root/"
m.execute(command.format(*commit_args))
m.execute(["ostree", "summary", "--repo={}".format(REPO_LOCATION), "-u"])
def rhsmcertd_hack(m):
# HACK: https://github.com/candlepin/subscription-manager/issues/1404
m.execute("systemctl disable rhsmcertd || true")
m.execute("systemctl stop rhsmcertd || true")
@skipImage("No OSTree available", "centos-7", "debian-stable", "debian-testing", "fedora-24", "fedora-25", "fedora-26", "fedora-testing", "fedora-i386", "rhel-7", "rhel-7-4", "ubuntu-1604", "ubuntu-stable")
class OstreeRestartCase(MachineCase):
def setUp(self):
# we need a static ip for this test becuase we restart
MachineCase.setUp(self, macaddr='52:54:00:9e:00:F5')
def switch_to_packages(self, b, sel, required_classes):
b.wait_not_visible("{0} div.packages".format(sel))
b.wait_present('{0} ul'.format(sel))
b.click('{0} ul li a:contains("Packages")'.format(sel))
b.wait_visible("{0} div.packages".format(sel))
for c in required_classes:
b.wait_present("{0} div.packages dl.{1}".format(sel, c))
def check_change_counts(self, b, sel):
for k in ['adds', 'removes', 'updates', 'downgrades']:
b.wait_present("{0} dd.{1}".format(sel, k))
b.wait_text("{0} dd.{1}".format(sel, k),
"1 package")
def check_sig(self, b, sel):
b.wait_not_visible("{0} div.signatures".format(sel))
b.wait_present('{0} ul'.format(sel))
b.click('{0} ul li a:contains("Signature")'.format(sel))
b.wait_visible("{0} div.signatures".format(sel))
b.wait_in_text("{0} div.signatures".format(sel), KEY_ID)
b.wait_in_text("{0} div.signatures".format(sel), "RSA")
b.wait_in_text("{0} div.signatures".format(sel), "Cockpit Tester ")
b.wait_in_text("{0} div.signatures".format(sel), "Good Signature")
b.wait_in_text("{0} div.signatures".format(sel), "When")
def testOstree(self):
b = self.browser
m = self.machine
# Delete local remote so we start clean, without a file based remote
ensure_remote_http_port (m)
docker_pkg = m.execute("rpm -qa | grep cockpit-docker").strip()
rhsmcertd_hack(m)
cockpit_shell = m.execute("rpm -qa | grep cockpit-ostree").strip()
cockpit_machines = m.execute("rpm -qa | grep cockpit-machines").strip()
self.login_and_go("/updates")
b.enter_page("/updates")
name = get_os_name(m)
# Check current and rollback target
b.wait_present('table.listing-ct')
b.wait_present('table.listing-ct tbody')
b.wait_text('table.listing-ct tbody:nth-child(3) div.listing-ct-head h3', name + " cockpit-base.1")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-check-circle-o')
b.wait_present('table.listing-ct tbody:nth-child(3).active')
b.wait_in_text('table.listing-ct tbody:nth-child(3) div.listing-ct-status', "Running")
b.wait_not_present("table.listing-ct tbody:nth-child(3) div.listing-ct-actions button")
b.wait_visible("table.listing-ct tbody:nth-child(3) div.tree")
b.wait_in_text("table.listing-ct tbody:nth-child(3) dd.os", name)
b.wait_in_text("table.listing-ct tbody:nth-child(3) dd.version", "cockpit-base.1")
self.switch_to_packages(b, "table.listing-ct tbody:nth-child(3)",
['rpms-col1', 'rpms-col2'])
b.wait_in_text("table.listing-ct tbody:nth-child(3) div.packages", docker_pkg)
for pkg in INSTALL_RPMS:
b.wait_not_in_text("table.listing-ct tbody:nth-child(3) div.packages", pkg)
b.wait_not_visible("table.listing-ct tbody:nth-child(3) div.signatures")
b.wait_present('table.listing-ct tbody:nth-child(3) ul')
b.click('table.listing-ct tbody:nth-child(3) ul li a:contains("Signature")')
b.wait_visible("table.listing-ct tbody:nth-child(3) div.signatures")
b.wait_in_text("table.listing-ct tbody:nth-child(3) div.signatures", "No signature avaliable")
# Require signatures
m.execute("sed -i /gpg-verify/d /etc/ostree/remotes.d/local.conf")
# HACK: rpm-ostree doesn't reload remote settings properly
# https://github.com/projectatomic/rpm-ostree/issues/401
m.execute("systemctl restart rpm-ostreed")
b.wait_not_in_text('table.listing-ct tbody:nth-child(4) div.listing-ct-head h3', "cockpit")
b.wait_present('table.listing-ct tbody:nth-child(4) i.fa-circle')
b.wait_in_text('table.listing-ct tbody:nth-child(4) div.listing-ct-status', "Available")
b.wait_in_text("table.listing-ct tbody:nth-child(4) div.listing-ct-actions button", "Roll Back")
b.wait_in_text("table.listing-ct tbody:nth-child(4) dd.os", name)
b.wait_visible("table.listing-ct tbody:nth-child(4) div.tree")
b.wait_not_visible("table.listing-ct tbody:nth-child(4) div.packages")
# Check for new commit, get error
b.wait_present('table.listing-ct tbody:nth-child(2) i.fa-caret-up')
b.wait_in_text("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button", "Check for Updates")
b.wait_not_present('table.listing-ct tbody:nth-child(2) div.alert-warning')
b.click("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button")
b.wait_present('table.listing-ct tbody:nth-child(2) div.alert-warning')
b.wait_present("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button.enabled")
# Serve repo
server_pid = start_trivial_httpd(m)
# Check for new commit
b.click("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button")
b.wait_present("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button.disabled")
b.wait_present("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button.enabled")
# Generate new commit
generate_new_commit(m, docker_pkg)
# Check again not trusted
b.click("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button")
b.wait_present('table.listing-ct tbody:nth-child(2) div.alert-warning')
b.wait_present("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button.enabled")
b.wait_in_text("table.listing-ct tbody:nth-child(2) div.alert-warning", "trusted keyring")
m.upload(["verify/files/publickey.asc"], "/root/")
m.execute("ostree remote gpg-import local -k /root/publickey.asc")
# Check again have update data
b.click("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-circle')
b.wait_in_text('table.listing-ct tbody:nth-child(3) div.listing-ct-status', "Available")
b.wait_in_text("table.listing-ct tbody:nth-child(3) div.listing-ct-actions button", "Update")
b.wait_present('table.listing-ct tbody:nth-child(4) i.fa-check-circle-o')
# Check update data
b.wait_visible("table.listing-ct tbody:nth-child(3) div.tree")
b.wait_in_text("table.listing-ct tbody:nth-child(3) dd.os", name)
b.wait_in_text("table.listing-ct tbody:nth-child(3) dd.version", "cockpit-base.2")
self.check_change_counts(b, "table.listing-ct tbody:nth-child(3)")
self.switch_to_packages(b, "table.listing-ct tbody:nth-child(3)",
['upgrades', 'downgrades',
'additions', 'removals'])
b.wait_text("table.listing-ct tbody:nth-child(3) dl.upgrades dd", "cockpit-machines-99999-2.noarch")
b.wait_text("table.listing-ct tbody:nth-child(3) dl.downgrades dd", "cockpit-ostree-wip-0.1.noarch")
b.wait_text("table.listing-ct tbody:nth-child(3) dl.additions dd", "empty-1-0.noarch")
b.wait_text("table.listing-ct tbody:nth-child(3) dl.removals dd", docker_pkg)
# Check signatures
self.check_sig (b, "table.listing-ct tbody:nth-child(3)")
# Force an error
stop_trivial_httpd(m, server_pid)
b.wait_not_present('table.listing-ct tbody:nth-child(3) div.listing-ct-error')
b.click("table.listing-ct tbody:nth-child(3) div.listing-ct-actions button")
b.wait_present("table.listing-ct tbody:nth-child(3) div.listing-ct-actions button.disabled")
b.wait_present("table.listing-ct tbody:nth-child(3) div.listing-ct-actions button.enabled")
b.wait_present('table.listing-ct tbody:nth-child(3) div.listing-ct-error')
server_pid = start_trivial_httpd(m)
# Apply update
b.click("table.listing-ct tbody:nth-child(3) div.listing-ct-actions button")
b.wait_present("table.listing-ct tbody:nth-child(3) div.ostree-progress")
b.wait_not_present('table.listing-ct tbody:nth-child(3) div.listing-ct-error')
b.switch_to_top()
with b.wait_timeout(120):
b.wait_visible(".curtains-ct")
b.wait_in_text(".curtains-ct h1", "Disconnected")
m.wait_reboot()
m.start_cockpit()
b.reload()
b.login_and_go("/updates")
m.reset_reboot_flag()
# After reboot, check commit
b.wait_present('table.listing-ct')
b.wait_present('table.listing-ct tbody')
b.wait_text('table.listing-ct tbody:nth-child(3) div.listing-ct-head h3', name + " cockpit-base.2")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-check-circle-o')
b.wait_present('table.listing-ct tbody:nth-child(3) div.listing-ct-panel,active')
b.wait_in_text('table.listing-ct tbody:nth-child(3) div.listing-ct-status', "Running")
b.wait_not_present("table.listing-ct tbody:nth-child(3) div.listing-ct-actions button")
self.switch_to_packages(b, "table.listing-ct tbody:nth-child(3)",
['rpms-col1', 'rpms-col2'])
b.wait_not_in_text("table.listing-ct tbody:nth-child(3) div.packages", docker_pkg)
for pkg in INSTALL_RPMS:
b.wait_in_text("table.listing-ct tbody:nth-child(3) div.packages", pkg)
# Check signatures
self.check_sig (b, "table.listing-ct tbody:nth-child(3)")
# Check rollback target
b.wait_text('table.listing-ct tbody:nth-child(4) div.listing-ct-head h3', name + " cockpit-base.1")
b.wait_present('table.listing-ct tbody:nth-child(4) i.fa-circle')
b.wait_in_text('table.listing-ct tbody:nth-child(4) div.listing-ct-status', "Available")
b.wait_in_text("table.listing-ct tbody:nth-child(4) div.listing-ct-actions button", "Roll Back")
b.wait_in_text("table.listing-ct tbody:nth-child(4) dd.os", name)
self.check_change_counts(b, "table.listing-ct tbody:nth-child(4)")
self.switch_to_packages(b, "table.listing-ct tbody:nth-child(4)",
['upgrades', 'downgrades',
'additions', 'removals'])
b.wait_text("table.listing-ct tbody:nth-child(4) dl.upgrades dd", cockpit_shell)
b.wait_text("table.listing-ct tbody:nth-child(4) dl.downgrades dd", cockpit_machines)
b.wait_text("table.listing-ct tbody:nth-child(4) dl.additions dd", docker_pkg)
b.wait_text("table.listing-ct tbody:nth-child(4) dl.removals dd", "empty-1-0.noarch")
# Rollback
b.wait_present("button:contains('Roll Back')");
b.click("table.listing-ct tbody:nth-child(4) div.listing-ct-actions button")
b.wait_present("table.listing-ct tbody:nth-child(4) div.ostree-progress")
b.switch_to_top()
with b.wait_timeout(120):
b.wait_visible(".curtains-ct")
b.wait_in_text(".curtains-ct h1", "Disconnected")
m.wait_reboot()
m.start_cockpit()
b.reload()
b.login_and_go("/updates")
m.reset_reboot_flag()
# After reboot upgrade but no rollback target
b.wait_present('table.listing-ct')
b.wait_present('table.listing-ct tbody')
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-circle')
b.wait_in_text("table.listing-ct tbody:nth-child(3) div.listing-ct-actions button", "Update")
b.wait_present('table.listing-ct tbody:nth-child(4) i.fa-check-circle-o')
b.wait_not_present('table.listing-ct tbody:nth-child(5)')
b.wait_not_present("button:contains('Roll Back')");
self.allow_restart_journal_messages()
def testRebase(self):
m = self.machine
b = self.browser
name = get_os_name(m)
start_trivial_httpd(m)
branch = m.execute("ostree refs --repo={0}".format(REPO_LOCATION)).strip()
# Add a new branch to the default repo
m.execute(["ostree", "commit", "--repo={}".format(REPO_LOCATION),
"-b", "znew-branch", "--tree=ref={}".format(branch),
"--add-metadata-string", "version=branch-version"])
m.execute(["ostree", "summary", "--repo={}".format(REPO_LOCATION), "-u"])
rhsmcertd_hack(m)
self.login_and_go("/updates")
b.enter_page("/updates")
b.wait_present('table.listing-ct tbody:nth-child(2) i.fa-caret-up')
b.wait_present('#change-repo')
b.wait_text("#change-repo", "local")
b.wait_present("#change-branch")
b.wait_in_text("#change-branch", branch)
b.wait_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu")
b.wait_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li")
b.wait_not_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li div.alert")
b.wait_in_text("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li:last", "znew-branch")
b.call_js_func("ph_count_check", "table.listing-ct tbody:nth-child(2) ul.dropdown-menu li", 2)
b.click("#change-branch")
b.click("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li:last a")
b.wait_text('table.listing-ct tbody:nth-child(3) div.listing-ct-head h3', name + " cockpit-base.1")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-check-circle-o')
b.wait_in_text("table.listing-ct tbody:nth-child(3) dd.origin", "local:{}".format(branch))
b.wait_in_text("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button", "Check for Updates")
b.click("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button")
b.wait_present("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button.enabled")
b.wait_text('table.listing-ct tbody:nth-child(3) div.listing-ct-head h3', name + " branch-version")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-circle')
b.wait_in_text('table.listing-ct tbody:nth-child(3) div.listing-ct-status', "Available")
b.wait_in_text("table.listing-ct tbody:nth-child(3) div.listing-ct-actions button", "Rebase")
b.wait_in_text("table.listing-ct tbody:nth-child(3) dd.os", name)
b.wait_in_text("table.listing-ct tbody:nth-child(3) dd.origin", "local:znew-branch")
b.wait_not_visible("table.listing-ct tbody:nth-child(3) div.packages")
b.wait_present('table.listing-ct tbody:nth-child(3) ul')
b.click('table.listing-ct tbody:nth-child(3) ul li a:contains("Packages")')
b.wait_visible("table.listing-ct tbody:nth-child(3) div.packages")
b.wait_in_text("table.listing-ct tbody:nth-child(3) div.packages", "contains the same packages as your currently booted")
# Apply update
b.click("table.listing-ct tbody:nth-child(3) div.listing-ct-actions button")
b.wait_present("table.listing-ct tbody:nth-child(3) div.ostree-progress")
b.wait_not_present('table.listing-ct tbody:nth-child(3) div.listing-ct-error')
b.switch_to_top()
with b.wait_timeout(120):
b.wait_visible(".curtains-ct")
b.wait_in_text(".curtains-ct h1", "Disconnected")
m.wait_reboot()
m.start_cockpit()
b.reload()
b.login_and_go("/updates")
m.reset_reboot_flag()
# After reboot, check commit
b.wait_present('table.listing-ct')
b.wait_present('table.listing-ct tbody')
b.wait_text('table.listing-ct tbody:nth-child(3) div.listing-ct-head h3', name + " branch-version")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-check-circle-o')
b.wait_present('table.listing-ct tbody:nth-child(3) div.listing-ct-panel,active')
b.wait_in_text("table.listing-ct tbody:nth-child(3) dd.origin", "local:znew-branch")
self.allow_restart_journal_messages()
@skipImage("No OSTree available", "centos-7", "debian-stable", "debian-testing", "fedora-24", "fedora-25", "fedora-26", "fedora-testing", "fedora-i386", "rhel-7", "rhel-7-4", "ubuntu-1604", "ubuntu-stable")
class OstreeCase(MachineCase):
def testRemoteManagement(self):
m = self.machine
b = self.browser
name = get_os_name(m)
start_trivial_httpd(m)
branch = m.execute("ostree refs --repo={0}".format(REPO_LOCATION)).strip()
rhsmcertd_hack(m)
self.login_and_go("/updates")
b.enter_page("/updates")
b.wait_present('table.listing-ct tbody:nth-child(2) i.fa-caret-up')
b.wait_not_present('table.listing-ct tbody:nth-child(2) div.alert-warning')
b.wait_present("#change-branch")
b.wait_in_text("#change-branch", branch)
b.wait_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu")
b.wait_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li")
b.wait_not_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li div.alert")
b.call_js_func("ph_count_check", "table.listing-ct tbody:nth-child(2) ul.dropdown-menu li", 1)
b.wait_in_text("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li", branch)
b.wait_present('#change-repo')
b.wait_text("#change-repo", "local")
b.click("#change-repo")
b.wait_present("modal-dialog")
b.wait_in_text("modal-dialog .modal-title", "Change Repository")
b.wait_present("modal-dialog .modal-body .list-group")
b.wait_in_text("modal-dialog .modal-body .list-group .active", "local")
b.wait_in_text("modal-dialog .modal-body .list-group-item:last", "Add New Repository")
b.wait_present("modal-dialog .modal-footer button.btn-primary")
b.click("modal-dialog .modal-body .list-group-item:last")
b.wait_present("modal-dialog .modal-footer button.disabled")
b.wait_present("modal-dialog #remote-name")
b.wait_present("modal-dialog #remote-url")
b.wait_present("modal-dialog #gpg-verify")
b.click("modal-dialog #gpg-verify")
b.set_val("modal-dialog #remote-url", "http://localhost:12344")
b.set_val("modal-dialog #remote-name", "zremote test")
b.wait_present("modal-dialog .group-buttons button.btn-primary")
b.wait_in_text("modal-dialog .group-buttons button.btn-primary", "Add")
b.click("modal-dialog .group-buttons button.btn-primary")
b.wait_present("modal-dialog .list-group-item:last div.dialog-error")
b.set_val("modal-dialog #remote-name", "zremote-test1")
b.click("modal-dialog .group-buttons button.btn-primary")
b.wait_not_present ("modal-dialog #remote-name")
b.wait_not_present ("modal-dialog .group-buttons")
b.wait_not_present("modal-dialog .modal-footer button.disabled")
b.wait_present("modal-dialog .modal-footer button.btn-primary")
b.wait_in_text("modal-dialog .modal-body .list-group .active", "local")
b.wait_present("modal-dialog .modal-body .list-group-item:contains('zremote-test1')")
b.wait_in_text("modal-dialog .modal-body .list-group-item:last", "Add New Repository")
b.click("modal-dialog .modal-body .list-group-item:contains('zremote-test1')")
b.click("modal-dialog .modal-footer button.btn-primary")
b.wait_not_present("modal-dialog")
b.wait_present('#change-repo')
b.wait_text("#change-repo", "zremote-test1")
# Branch is still default
b.wait_present("#change-branch")
b.wait_in_text("#change-branch", branch)
# But can't list
b.wait_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu")
b.wait_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu div.alert")
b.wait_in_text("table.listing-ct tbody:nth-child(2) ul.dropdown-menu div.alert", "Connection refused")
# Config created
self.assertEqual(m.execute("cat /etc/ostree/remotes.d/zremote-test1.conf").strip(),
'[remote "zremote-test1"]\nurl=http://localhost:12344\ngpg-verify=true')
# No custom keyring
self.assertFalse(m.execute("ls /sysroot/ostree/repo/zremote-test1.trustedkeys.gpg || true"))
# Refresh goes back to default
b.reload()
b.enter_page("/updates")
b.wait_present('table.listing-ct tbody:nth-child(2) i.fa-caret-up')
b.wait_present('#change-repo')
b.wait_text("#change-repo", "local")
b.wait_present("#change-branch")
b.wait_in_text("#change-branch", branch)
b.wait_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu")
b.wait_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li")
b.wait_not_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu div.alert")
# Create a new remote with commits, just use the rpm dir
zrepo = "/var/zrepo"
m.execute("mkdir -p {}".format(zrepo))
m.execute("mkdir -p /tmp/rpm-data/usr/share")
m.execute("cp -r /usr/share/rpm /tmp/rpm-data/usr/share/")
m.execute(["ostree", "init", "--repo", zrepo, "--mode", "archive-z2"])
m.execute(["ostree", "commit", "--repo={}".format(zrepo),
"-b", "zremote-branch1", "--orphan", "--tree=dir=/tmp/rpm-data",
"--add-metadata-string", "version=zremote-branch1.1"])
m.execute(["ostree", "commit", "--repo={}".format(zrepo),
"-b", "zremote-branch2", "--orphan", "--tree=dir=/tmp/rpm-data",
"--add-metadata-string", "version=zremote-branch2.1"])
start_trivial_httpd(m, remote="zremote-test1", location=zrepo)
# Add a new branch to the default repo
m.execute(["ostree", "commit", "--repo={}".format(REPO_LOCATION),
"-b", branch, "--tree=ref={}".format(branch),
"--add-metadata-string", "version=bad-version"])
m.execute(["ostree", "summary", "--repo={}".format(REPO_LOCATION), "-u"])
# Edit
b.wait_present('#change-repo')
b.click("#change-repo")
b.wait_present("modal-dialog")
b.wait_present("modal-dialog .modal-body .list-group")
b.wait_present("modal-dialog .modal-body .list-group-item:contains('zremote-test1')")
b.wait_present("modal-dialog .modal-body .list-group-item:contains('zremote-test1') .listing-ct-actions button.pficon-edit")
b.click("modal-dialog .modal-body .list-group-item:contains('zremote-test1') .listing-ct-actions button.pficon-edit")
b.wait_present("modal-dialog .group-buttons")
b.wait_present("modal-dialog .modal-footer button.disabled")
b.wait_present("modal-dialog .group-buttons button.btn-primary")
b.wait_in_text("modal-dialog .group-buttons", "zremote-test1")
b.wait_present("modal-dialog .form-table-ct")
b.wait_in_text("modal-dialog .form-table-ct", "http://localhost:12344")
b.wait_present("modal-dialog .form-table-ct #gpg-verify:checked")
b.wait_not_present("modal-dialog #gpg-data")
b.wait_present("modal-dialog .form-table-ct button.btn-default")
b.click("modal-dialog .form-table-ct button.btn-default")
b.wait_present("modal-dialog #gpg-data")
b.wait_not_present("modal-dialog .form-table-ct button.btn-default")
b.set_val("modal-dialog #gpg-data", "bad")
b.click("modal-dialog .group-buttons button.btn-primary")
b.wait_present("modal-dialog .group-buttons div.dialog-error")
with open(os.path.join(TEST_DIR, "verify", "files", "publickey.asc"), 'rb') as fp:
gpg_data = fp.read()
b.set_val("modal-dialog #gpg-data", gpg_data)
b.click("modal-dialog .group-buttons button.btn-primary")
b.wait_not_present ("modal-dialog .group-buttons")
b.wait_not_present("modal-dialog .form-table-ct")
b.wait_not_present("modal-dialog .modal-footer button.disabled")
m.execute("ls /sysroot/ostree/repo/zremote-test1.trustedkeys.gpg")
b.wait_present("modal-dialog .modal-body .list-group-item:contains('zremote-test1') .listing-ct-actions button.pficon-edit")
b.click("modal-dialog .modal-body .list-group-item:contains('zremote-test1') .listing-ct-actions button.pficon-edit")
b.wait_present("modal-dialog .group-buttons")
b.wait_present("modal-dialog .modal-footer button.disabled")
b.wait_present("modal-dialog .group-buttons button.btn-primary")
b.wait_present("modal-dialog .form-table-ct")
b.wait_in_text("modal-dialog .form-table-ct", "http://localhost:12344")
b.wait_present("modal-dialog .form-table-ct button.btn-default")
b.wait_present("modal-dialog .form-table-ct #gpg-verify:checked")
b.click("modal-dialog .form-table-ct #gpg-verify")
b.click("modal-dialog .group-buttons button.btn-primary")
b.wait_not_present("modal-dialog .form-table-ct")
b.wait_not_present ("modal-dialog .group-buttons")
b.wait_not_present("modal-dialog .modal-footer button.disabled")
b.click("modal-dialog .modal-body .list-group-item:contains('zremote-test1')")
b.click("modal-dialog .modal-footer button.btn-primary")
b.wait_not_present("modal-dialog")
b.wait_present('#change-repo')
b.wait_text("#change-repo", "zremote-test1")
b.wait_present("#change-branch")
b.wait_in_text("#change-branch", "zremote-branch1")
b.wait_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu")
b.wait_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li")
b.wait_not_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu div.alert")
b.wait_in_text("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li:first", "zremote-branch1")
b.wait_in_text("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li:last", "zremote-branch2")
b.call_js_func("ph_count_check", "table.listing-ct tbody:nth-child(2) ul.dropdown-menu li", 2)
self.assertEqual(m.execute("cat /etc/ostree/remotes.d/zremote-test1.conf").strip(),
'[remote "zremote-test1"]\nurl=http://localhost:12344\ngpg-verify = false')
# Check updates display
b.wait_present("table.listing-ct tbody:nth-child(3)")
b.wait_text('table.listing-ct tbody:nth-child(3) div.listing-ct-head h3', name + " cockpit-base.1")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-check-circle-o')
b.wait_in_text("table.listing-ct tbody:nth-child(3) dd.origin", "local:{}".format(branch))
b.wait_in_text("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button", "Check for Updates")
b.click("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button")
b.wait_present("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button.enabled")
b.wait_text('table.listing-ct tbody:nth-child(3) div.listing-ct-head h3', name + " zremote-branch1.1")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-circle')
b.wait_in_text('table.listing-ct tbody:nth-child(3) div.listing-ct-status', "Available")
b.wait_in_text("table.listing-ct tbody:nth-child(3) div.listing-ct-actions button", "Rebase")
b.wait_in_text("table.listing-ct tbody:nth-child(3) dd.os", name)
b.wait_in_text("table.listing-ct tbody:nth-child(3) dd.origin", "zremote-test1:zremote-branch1")
b.wait_not_visible("table.listing-ct tbody:nth-child(3) div.packages")
b.wait_present('table.listing-ct tbody:nth-child(3) ul')
b.click('table.listing-ct tbody:nth-child(3) ul li a:contains("Packages")')
b.wait_visible("table.listing-ct tbody:nth-child(3) div.packages")
b.wait_in_text("table.listing-ct tbody:nth-child(3) div.packages", "contains the same packages as your currently booted")
# Switching branch hides other
b.click("#change-branch")
b.wait_visible("table.listing-ct tbody:nth-child(2) ul.dropdown-menu")
b.wait_in_text("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li:last", "zremote-branch2")
b.click("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li:last a")
b.wait_text('table.listing-ct tbody:nth-child(3) div.listing-ct-head h3', name + " cockpit-base.1")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-check-circle-o')
# Switching back shows pulled
b.wait_present('#change-branch')
b.click("#change-branch")
b.wait_visible("table.listing-ct tbody:nth-child(2) ul.dropdown-menu")
b.wait_in_text("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li:first", "zremote-branch1")
b.click("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li:first a")
b.wait_text('table.listing-ct tbody:nth-child(3) div.listing-ct-head h3', name + " zremote-branch1.1")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-circle')
# Refresh, back to local, pull in update
b.reload()
b.enter_page("/updates")
b.wait_present('table.listing-ct tbody:nth-child(2) i.fa-caret-up')
b.wait_present("#change-branch")
b.wait_in_text("#change-branch", branch)
b.wait_in_text("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button", "Check for Updates")
b.click("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button")
b.wait_present("table.listing-ct tbody:nth-child(2) div.listing-ct-actions button.enabled")
b.wait_text('table.listing-ct tbody:nth-child(3) div.listing-ct-head h3', name + " bad-version")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-circle')
# Switching to branch shows pulled
b.wait_present('#change-repo')
b.wait_text("#change-repo", "local")
b.click("#change-repo")
b.wait_present("modal-dialog")
b.wait_present("modal-dialog .modal-body .list-group")
b.wait_in_text("modal-dialog .modal-body .list-group-item:contains('zremote-test1')", "zremote-test1")
b.click("modal-dialog .modal-body .list-group-item:contains('zremote-test1')")
b.click("modal-dialog .modal-footer button.btn-primary")
b.wait_not_present("modal-dialog")
b.wait_present('#change-repo')
b.wait_text("#change-repo", "zremote-test1")
b.wait_present("#change-branch")
b.wait_in_text("#change-branch", "zremote-branch1")
b.wait_text('table.listing-ct tbody:nth-child(3) div.listing-ct-head h3', name + " zremote-branch1.1")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-circle')
b.wait_not_in_text('table.listing-ct', name + " bad-version")
# delete
b.wait_present('#change-repo')
b.click("#change-repo")
b.wait_present("modal-dialog")
b.wait_present("modal-dialog .modal-body .list-group")
b.wait_in_text("modal-dialog .modal-body .list-group-item:contains('zremote-test1')", "zremote-test1")
b.wait_present("modal-dialog .modal-body .list-group-item:contains('zremote-test1') .listing-ct-actions button.pficon-edit")
b.click("modal-dialog .modal-body .list-group-item:contains('zremote-test1') .listing-ct-actions button.pficon-edit")
b.wait_present("modal-dialog .group-buttons")
b.wait_present("modal-dialog .group-buttons button.btn-danger")
b.wait_present("modal-dialog .modal-footer button.disabled")
b.wait_present("modal-dialog .form-table-ct")
b.wait_in_text("modal-dialog .form-table-ct", "http://localhost:12344")
b.wait_present("#gpg-verify")
b.wait_present("modal-dialog .form-table-ct #gpg-verify:not(:checked)")
b.click("modal-dialog .group-buttons button.btn-danger")
b.wait_not_present("modal-dialog .form-table-ct")
b.wait_not_present("modal-dialog .group-buttons")
b.wait_present("modal-dialog .modal-body .list-group")
b.wait_not_in_text("modal-dialog .modal-body .list-group", "zremote-test1")
b.wait_in_text("modal-dialog .modal-body .list-group", "local")
b.wait_not_present("modal-dialog .modal-body .list-group .active")
b.wait_present("modal-dialog .modal-footer button.disabled")
b.click("modal-dialog .modal-body .list-group-item:contains('local')")
b.wait_present("modal-dialog .modal-body .list-group .active")
b.click("modal-dialog .modal-footer button.btn-primary")
b.wait_not_present("modal-dialog")
b.wait_present('#change-repo')
b.wait_text("#change-repo", "local")
b.wait_present("#change-branch")
b.wait_in_text("#change-branch", branch)
b.wait_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu")
b.wait_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li")
b.wait_not_present("table.listing-ct tbody:nth-child(2) ul.dropdown-menu li div.alert")
b.call_js_func("ph_count_check", "table.listing-ct tbody:nth-child(2) ul.dropdown-menu li", 1)
b.wait_text('table.listing-ct tbody:nth-child(3) div.listing-ct-head h3', name + " bad-version")
b.wait_present('table.listing-ct tbody:nth-child(3) i.fa-circle')
b.wait_in_text("table.listing-ct tbody:nth-child(3) dd.origin", "local:{}".format(branch))
def testPermission(self):
m = self.machine
b = self.browser
rhsmcertd_hack(m)
# Create a user
m.execute("useradd user -c 'User' || true")
m.execute("echo foobar | passwd --stdin user")
# login
m.start_cockpit()
b.open("/updates")
b.wait_visible("#login")
b.set_val("#login-user-input", "user")
b.set_val("#login-password-input", "foobar")
b.click('#login-button')
b.enter_page("/updates")
b.wait_present(".curtains-ct")
b.wait_in_text(".curtains-ct", "Not authorized")
self.assertIn("Reconnect", b.text(".blank-slate-pf-main-action button"))
self.allow_authorize_journal_messages()
if __name__ == "__main__":
test_main()