Skip to content

Commit e9b6e8b

Browse files
cgwaltersjlebon
authored andcommitted
dev-overlay: New command
I want to add some more testing of OS updates to https://github.com/openshift/machine-config-operator/ and it's not really necessary to do a full e2e build - just adding a dummy file to the oscontainer is going to be sufficient to start. Related to this, requiring privileges (like `compose tree`) does would be a huge ergonomic hit. This script aims to improve the code that landed for overriding the kubelet in Origin: https://github.com/smarterclayton/origin/blob/4de957b019aee56931b1a29af148cf64865a969b/images/os/Dockerfile Once this lands I'll do a PR to origin to change it to use coreos-assembler. (though that image is enormous, maybe we want explicit layering for things that don't need image building, also we really need to cut out Anaconda) Side note: while writing this I ended up rediscovering ostreedev/ostree#1643 It was less than a year ago but that already feels like forever...
1 parent eb3f85f commit e9b6e8b

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

src/cmd-dev-overlay

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/python3 -u
2+
# Add content on top of a commit, handling SELinux labeling etc.
3+
# This is a more flexible (and correct) replacement for the CI flow developed
4+
# in https://github.com/smarterclayton/origin/blob/4de957b019aee56931b1a29af148cf64865a969b/images/os/Dockerfile
5+
# Down the line we want to lower this into rpm-ostree (and support RPMs too).
6+
# This script though should be very convenient for the common case of
7+
# overlaying some new binaries into /usr/bin that don't need any scripts
8+
# run and also don't need e.g. to regenerate the initramfs that would
9+
# happen in a full `rpm-ostree compose tree`.
10+
# Also related to the initramfs, this script explicitly doesn't
11+
# use or require any container features, so it will work inside
12+
# an podman/Kube container without special privileges.
13+
14+
import argparse
15+
import gi
16+
import sys, os
17+
import tempfile
18+
import subprocess
19+
20+
gi.require_version('OSTree', '1.0')
21+
gi.require_version('Json', '1.0')
22+
from gi.repository import GLib, Gio, OSTree, Json
23+
24+
# This seems to not be exposed by Python which has its own wrappers,
25+
# It's also not exposed by GLib. This is a Linux specific value
26+
# but that's totally fine, OSTree only works there too.
27+
AT_FDCWD = -100
28+
29+
parser = argparse.ArgumentParser()
30+
parser.add_argument("--repo", help="repo", required=True)
31+
parser.add_argument("--rev", help="Revision to override")
32+
#parser.add_argument("--add-rpm", help="Unpack literal RPM content (does not currently update rpm DB, replace older RPM, or run any scripts)")
33+
parser.add_argument("--add-tree", help="Add local filesystem tree", default=[], action="append")
34+
parser.add_argument("--output-ref", help="Output ref (if unset, will just write new commit)")
35+
args = parser.parse_args()
36+
37+
repo = OSTree.Repo.new(Gio.File.new_for_path(args.repo))
38+
repo.open(None)
39+
40+
if args.rev is not None:
41+
rev = args.rev
42+
else:
43+
[_,refs] = repo.list_refs(None, None)
44+
nrefs = len(refs)
45+
if nrefs > 1:
46+
raise SystemExit(f"No rev specified and repo has {nrefs} refs")
47+
rev = refs[0]
48+
[_,root,rev] = repo.read_commit(rev, None)
49+
[_, base_commit, _] = repo.load_commit(rev)
50+
# See https://github.com/ostreedev/ostree/pull/1643
51+
base_contents_checksum = OSTree.checksum_from_bytes_v(base_commit.get_child_value(6))
52+
base_meta_checksum = OSTree.checksum_from_bytes_v(base_commit.get_child_value(7))
53+
mtree = OSTree.MutableTree.new_from_checksum(repo, base_contents_checksum, base_meta_checksum)
54+
55+
tmpd = tempfile.TemporaryDirectory(dir=f"{args.repo}/tmp/", prefix="dev-overlay")
56+
def add_commit_filter(repo, path, finfo):
57+
# Canonicalize uid/gid to 0
58+
finfo.set_attribute_uint32("unix::uid", 0)
59+
finfo.set_attribute_uint32("unix::gid", 0)
60+
return OSTree.RepoCommitFilterResult.ALLOW
61+
add_modifier = OSTree.RepoCommitModifier.new(OSTree.RepoCommitModifierFlags.DEVINO_CANONICAL |
62+
OSTree.RepoCommitModifierFlags.SKIP_XATTRS, add_commit_filter)
63+
if root.get_child("usr/etc/selinux"):
64+
opts = OSTree.RepoCheckoutAtOptions()
65+
opts.mode = OSTree.RepoCheckoutMode.USER
66+
opts.subpath = "/usr/etc/selinux"
67+
dest = tmpd.name + "/" + opts.subpath
68+
os.makedirs(os.path.dirname(dest))
69+
repo.checkout_at(opts, AT_FDCWD, dest, rev, None)
70+
add_modifier.set_sepolicy(OSTree.SePolicy.new(Gio.File.new_for_path(tmpd.name)))
71+
for d in args.add_tree:
72+
repo.write_dfd_to_mtree(AT_FDCWD, d, mtree, add_modifier, None)
73+
74+
[_,dir_tree] = repo.write_mtree(mtree, None)
75+
[_,new_commit] = repo.write_commit(None, None, None, None, dir_tree, None)
76+
if args.output_ref is not None:
77+
repo.set_ref_immediate(None, args.output_ref, new_commit)
78+
print(f"Wrote {args.output_ref} => {new_commit}")
79+
else:
80+
print(f"Wrote {new_commit}")

0 commit comments

Comments
 (0)