This adds a `default: true` option for all cases where OSTree information is specified in schemas and allows for the information to be picked up from the filesystem. This is a safe operation because when building disk images there is no known case where having two deployments makes sense. In the case there ever were a case then the osname, ref, and serial options still exist and can be used. Co-authored-by: Luke Yang <luyang@redhat.com> Co-authored-by: Michael Vogt <michael.vogt@gmail.com>
249 lines
8.2 KiB
Python
249 lines
8.2 KiB
Python
#
|
|
# Tests for the 'osbuild.util.ostree' module.
|
|
#
|
|
|
|
import io
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
|
|
import pytest
|
|
|
|
from osbuild.testutil import make_fake_tree
|
|
from osbuild.util import ostree
|
|
|
|
from .. import test
|
|
|
|
|
|
def run(*args, check=True, encoding="utf8", **kwargs):
|
|
res = subprocess.run(*args,
|
|
encoding=encoding,
|
|
check=check,
|
|
**kwargs)
|
|
return res
|
|
|
|
|
|
class TestObjectStore(test.TestBase):
|
|
|
|
# pylint: disable=no-self-use
|
|
@unittest.skipUnless(test.TestBase.have_rpm_ostree(), "rpm-ostree missing")
|
|
def test_treefile_empty(self):
|
|
# check we produce a valid treefile from an empty object
|
|
tf = ostree.Treefile()
|
|
|
|
with tf.as_tmp_file() as f:
|
|
run(["rpm-ostree", "compose", "tree", "--print-only", f])
|
|
|
|
def test_treefile_types(self):
|
|
tf = ostree.Treefile()
|
|
|
|
tf["repos"] = ["a", "b", "c"] # valid list of strings
|
|
tf["selinux"] = True # valid boolean
|
|
tf["ref"] = "ref/sample/tip" # valid string
|
|
|
|
with self.assertRaises(ValueError):
|
|
tf["repos"] = "not a list" # not a list
|
|
|
|
with self.assertRaises(ValueError):
|
|
tf["repos"] = [1, 2, 3] # not a string list
|
|
|
|
with self.assertRaises(ValueError):
|
|
tf["selinux"] = "not a bool" # not a boolean
|
|
|
|
def test_treefile_dump(self):
|
|
tf = ostree.Treefile()
|
|
test_ref = "a/sample/ref"
|
|
tf["ref"] = test_ref
|
|
|
|
with tf.as_tmp_file() as path:
|
|
with open(path, "r", encoding="utf8") as f:
|
|
js = json.load(f)
|
|
self.assertEqual(js["ref"], test_ref)
|
|
self.assertEqual(tf["ref"], test_ref)
|
|
|
|
@unittest.skipUnless(test.TestBase.have_rpm_ostree(), "rpm-ostree missing")
|
|
def test_treefile_full(self):
|
|
params = {
|
|
"ref": "osbuild/ostree/devel",
|
|
"repos": ["fedora", "osbuild"],
|
|
"selinux": True,
|
|
"boot-location": "new",
|
|
"etc-group-members": ["wheel"],
|
|
"machineid-compat": True
|
|
}
|
|
|
|
tf = ostree.Treefile()
|
|
for p, v in params.items():
|
|
tf[p] = v
|
|
|
|
with tf.as_tmp_file() as path:
|
|
r = run(["rpm-ostree",
|
|
"compose",
|
|
"tree",
|
|
"--print-only",
|
|
path],
|
|
stdout=subprocess.PIPE)
|
|
self.assertEqual(r.returncode, 0)
|
|
js = json.loads(r.stdout)
|
|
|
|
for p, v in params.items():
|
|
self.assertEqual(v, js[p])
|
|
|
|
@unittest.skipUnless(test.TestBase.have_test_data(), "no test-data access")
|
|
@unittest.skipUnless(test.TestBase.have_rpm_ostree(), "rpm-ostree missing")
|
|
def test_show_commit(self):
|
|
repo_path = os.path.join(self.locate_test_data(), "sources/org.osbuild.ostree/data/repo")
|
|
ostree.show(repo_path, "d6243b0d0ca3dc2aaef2e0eb3e9f1f4836512c2921007f124b285f7c466464d8")
|
|
with pytest.raises(RuntimeError):
|
|
ostree.show(repo_path, "f000000000000000000000000DEADBEEF000000000000000000000000000000f")
|
|
|
|
|
|
class TestPasswdLike(unittest.TestCase):
|
|
|
|
def test_merge_passwd(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
primary_file_lines = [
|
|
"root:x:0:0:root:/root:/bin/bash\n",
|
|
"bin:x:1:1:bin:/bin:/sbin/nologin\n",
|
|
"daemon:x:2:2:daemon:/sbin:/sbin/nologin\n"
|
|
]
|
|
secondary_file_lines = [
|
|
"daemon:x:9:9:daemon:/sbin:/sbin/nologin\n"
|
|
"lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\n",
|
|
"sync:x:5:0:sync:/sbin:/bin/sync\n"
|
|
]
|
|
result_file_lines = [
|
|
"root:x:0:0:root:/root:/bin/bash\n",
|
|
"bin:x:1:1:bin:/bin:/sbin/nologin\n",
|
|
"daemon:x:2:2:daemon:/sbin:/sbin/nologin\n",
|
|
"lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\n",
|
|
"sync:x:5:0:sync:/sbin:/bin/sync\n"
|
|
]
|
|
with open(os.path.join(tmpdir, "primary"), "w", encoding="utf8") as f:
|
|
f.writelines(primary_file_lines)
|
|
with open(os.path.join(tmpdir, "secondary"), "w", encoding="utf8") as f:
|
|
f.writelines(secondary_file_lines)
|
|
|
|
passwd = ostree.PasswdLike.from_file(os.path.join(tmpdir, "primary"))
|
|
passwd.merge_with_file(os.path.join(tmpdir, "secondary"))
|
|
passwd.dump_to_file(os.path.join(tmpdir, "result"))
|
|
|
|
with open(os.path.join(tmpdir, "result"), "r", encoding="utf8") as f:
|
|
self.assertEqual(sorted(f.readlines()), sorted(result_file_lines))
|
|
|
|
def test_merge_group(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
primary_file_lines = [
|
|
"root:x:0:\n",
|
|
"bin:x:1:\n"
|
|
]
|
|
secondary_file_lines = [
|
|
"bin:x:4:\n",
|
|
"daemon:x:2:\n"
|
|
]
|
|
result_file_lines = [
|
|
"root:x:0:\n",
|
|
"bin:x:1:\n",
|
|
"daemon:x:2:\n"
|
|
]
|
|
with open(os.path.join(tmpdir, "primary"), "w", encoding="utf8") as f:
|
|
f.writelines(primary_file_lines)
|
|
with open(os.path.join(tmpdir, "secondary"), "w", encoding="utf8") as f:
|
|
f.writelines(secondary_file_lines)
|
|
|
|
passwd = ostree.PasswdLike.from_file(os.path.join(tmpdir, "primary"))
|
|
passwd.merge_with_file(os.path.join(tmpdir, "secondary"))
|
|
passwd.dump_to_file(os.path.join(tmpdir, "result"))
|
|
|
|
with open(os.path.join(tmpdir, "result"), "r", encoding="utf8") as f:
|
|
self.assertEqual(sorted(f.readlines()), sorted(result_file_lines))
|
|
|
|
# pylint: disable=no-self-use
|
|
def test_subids_cfg(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
|
|
first = [
|
|
"gicmo:100000:65536",
|
|
"achilles:100000:65536",
|
|
"ondrej:100000:65536"
|
|
]
|
|
|
|
txt = io.StringIO("\n".join(first))
|
|
|
|
subids = ostree.SubIdsDB()
|
|
subids.read(txt)
|
|
|
|
assert len(subids.db) == 3
|
|
|
|
for name in ("gicmo", "achilles", "ondrej"):
|
|
assert name in subids.db
|
|
uid, count = subids.db[name]
|
|
assert uid == "100000"
|
|
assert count == "65536"
|
|
|
|
second = [
|
|
"gicmo:200000:1000",
|
|
"tom:200000:1000",
|
|
"lars:200000:1000"
|
|
]
|
|
|
|
txt = io.StringIO("\n".join(second))
|
|
subids.read(txt)
|
|
|
|
assert len(subids.db) == 5
|
|
|
|
for name in ("gicmo", "achilles", "tom", "lars"):
|
|
assert name in subids.db
|
|
|
|
for name in ("gicmo", "tom", "lars"):
|
|
uid, count = subids.db[name]
|
|
assert uid == "200000"
|
|
assert count == "1000"
|
|
|
|
file = os.path.join(tmpdir, "subuid")
|
|
subids.write_to(file)
|
|
|
|
check = ostree.SubIdsDB()
|
|
check.read_from(file)
|
|
|
|
assert subids.db == check.db
|
|
|
|
|
|
def test_parse_default_deployment_happy(tmp_path):
|
|
deployment = {
|
|
"default": True,
|
|
}
|
|
make_fake_tree(tmp_path, {
|
|
"ostree/deploy/fedora-coreos/deploy/72f807.0": "",
|
|
})
|
|
osname, ref, serial = ostree.parse_deployment_option(tmp_path, deployment)
|
|
assert osname == "fedora-coreos"
|
|
assert ref == "72f807"
|
|
assert serial == "0"
|
|
|
|
|
|
def test_parse_default_deployment_sad(tmp_path):
|
|
deployment = {
|
|
"default": True,
|
|
}
|
|
make_fake_tree(tmp_path, {
|
|
"ostree/deploy/fedora-coreos/deploy/72f807.0": "",
|
|
"ostree/deploy/fedora-coreos/deploy/123456.0": "",
|
|
})
|
|
with pytest.raises(ValueError) as exp:
|
|
ostree.parse_deployment_option(tmp_path, deployment)
|
|
assert "More than one deployment found: [" in str(exp.value)
|
|
|
|
|
|
def test_parse_deployment_happy(tmp_path):
|
|
deployment = {
|
|
"osname": "fedora-coreos",
|
|
"ref": "some-ref",
|
|
"serial": "0",
|
|
}
|
|
osname, ref, serial = ostree.parse_deployment_option(tmp_path, deployment)
|
|
assert osname == "fedora-coreos"
|
|
assert ref == "some-ref"
|
|
assert serial == "0"
|