Skip to content

Commit

Permalink
dev-overlay: New command
Browse files Browse the repository at this point in the history
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...
  • Loading branch information
cgwalters committed Apr 25, 2019
1 parent b4f38d9 commit a7a9739
Showing 1 changed file with 80 additions and 0 deletions.
80 changes: 80 additions & 0 deletions src/cmd-dev-overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/python3 -u
# Add content on top of a commit, handling SELinux labeling etc.
# This is a more flexible (and correct) replacement for the CI flow developed
# in https://github.com/smarterclayton/origin/blob/4de957b019aee56931b1a29af148cf64865a969b/images/os/Dockerfile
# Down the line we want to lower this into rpm-ostree (and support RPMs too).
# This script though should be very convenient for the common case of
# overlaying some new binaries into /usr/bin that don't need any scripts
# run and also don't need e.g. to regenerate the initramfs that would
# happen in a full `rpm-ostree compose tree`.
# Also related to the initramfs, this script explicitly doesn't
# use or require any container features, so it will work inside
# an podman/Kube container without special privileges.

import argparse
import gi
import sys, os
import tempfile
import subprocess

gi.require_version('OSTree', '1.0')
gi.require_version('Json', '1.0')
from gi.repository import GLib, Gio, OSTree, Json

# This seems to not be exposed by Python which has its own wrappers,
# It's also not exposed by GLib. This is a Linux specific value
# but that's totally fine, OSTree only works there too.
AT_FDCWD = -100

parser = argparse.ArgumentParser()
parser.add_argument("--repo", help="repo", required=True)
parser.add_argument("--rev", help="Revision to override")
#parser.add_argument("--add-rpm", help="Unpack literal RPM content (does not currently update rpm DB, replace older RPM, or run any scripts)")
parser.add_argument("--add-tree", help="Add local filesystem tree", default=[], action="append")
parser.add_argument("--output-ref", help="Output ref (if unset, will just write new commit)")
args = parser.parse_args()

repo = OSTree.Repo.new(Gio.File.new_for_path(args.repo))
repo.open(None)

if args.rev is not None:
rev = args.rev
else:
[_,refs] = repo.list_refs(None, None)
nrefs = len(refs)
if nrefs > 1:
raise SystemExit(f"No rev specified and repo has {nrefs} refs")
rev = refs[0]
[_,root,rev] = repo.read_commit(rev, None)
[_, base_commit, _] = repo.load_commit(rev)
# See https://github.com/ostreedev/ostree/pull/1643
base_contents_checksum = OSTree.checksum_from_bytes_v(base_commit.get_child_value(6))
base_meta_checksum = OSTree.checksum_from_bytes_v(base_commit.get_child_value(7))
mtree = OSTree.MutableTree.new_from_checksum(repo, base_contents_checksum, base_meta_checksum)

tmpd = tempfile.TemporaryDirectory(dir=f"{args.repo}/tmp/", prefix="dev-overlay")
def add_commit_filter(repo, path, finfo):
# Canonicalize uid/gid to 0
finfo.set_attribute_uint32("unix::uid", 0)
finfo.set_attribute_uint32("unix::gid", 0)
return OSTree.RepoCommitFilterResult.ALLOW
add_modifier = OSTree.RepoCommitModifier.new(OSTree.RepoCommitModifierFlags.DEVINO_CANONICAL |
OSTree.RepoCommitModifierFlags.SKIP_XATTRS, add_commit_filter)
if root.get_child("usr/etc/selinux"):
opts = OSTree.RepoCheckoutAtOptions()
opts.mode = OSTree.RepoCheckoutMode.USER
opts.subpath = "/usr/etc/selinux"
dest = tmpd.name + "/" + opts.subpath
os.makedirs(os.path.dirname(dest))
repo.checkout_at(opts, AT_FDCWD, dest, rev, None)
add_modifier.set_sepolicy(OSTree.SePolicy.new(Gio.File.new_for_path(tmpd.name)))
for d in args.add_tree:
repo.write_dfd_to_mtree(AT_FDCWD, d, mtree, add_modifier, None)

[_,dir_tree] = repo.write_mtree(mtree, None)
[_,new_commit] = repo.write_commit(None, None, None, None, dir_tree, None)
if args.output_ref is not None:
repo.set_ref_immediate(None, args.output_ref, new_commit)
print(f"Wrote {args.output_ref} => {new_commit}")
else:
print(f"Wrote {new_commit}")

0 comments on commit a7a9739

Please sign in to comment.