Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[merged] compose: support adding external files #253

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile-tests.am
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ tests/test-ucontainer.sh: tests/compose/test-repo-local.repo
installed_test_data = tests/libtest.sh \
tests/compose/test-repo.repo \
tests/compose/test-repo.json \
tests/compose/test-repo-add-files.json \
tests/compose/test-repo.repo.in \
$(NULL)

Expand Down
8 changes: 8 additions & 0 deletions docs/manual/treefile.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,11 @@ It supports the following parameters:
rpm-ostree will not do any special handling of kernel, initrd or the
/boot directory. This is useful if the target for the tree is some kind
of container which does not have its own kernel.

* `copy-files`: Array, optional: Copy external files to the rootfs.

Each array element is an array, whose first member is the source
file name, and the second element is the destination name. The
source file must be in the same directory as the treefile.

Example: `"add-files": [["bar", "/bar"], ["foo", "/foo"]]`
48 changes: 48 additions & 0 deletions src/app/rpmostree-compose-builtin-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ typedef struct {
static gboolean
compute_checksum_from_treefile_and_goal (RpmOstreeTreeComposeContext *self,
HyGoal goal,
GFile *contextdir,
JsonArray *add_files,
char **out_checksum,
GError **error)
{
Expand All @@ -118,6 +120,43 @@ compute_checksum_from_treefile_and_goal (RpmOstreeTreeComposeContext *self,
g_checksum_update (checksum, buf, len);
}

if (add_files)
{
guint i, len = json_array_get_length (add_files);
for (i = 0; i < len; i++)
{
gs_unref_object GFile *srcfile = NULL;
const char *src, *dest;
JsonArray *add_el = json_array_get_array_element (add_files, i);
gs_unref_object GFile *child = NULL;

if (!add_el)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Element in add-files is not an array");
goto out;
}
src = _rpmostree_jsonutil_array_require_string_element (add_el, 0, error);
if (!src)
goto out;

dest = _rpmostree_jsonutil_array_require_string_element (add_el, 1, error);
if (!dest)
goto out;

srcfile = g_file_resolve_relative_path (contextdir, src);

if (!_rpmostree_util_update_checksum_from_file (checksum,
srcfile,
NULL,
error))
goto out;

g_checksum_update (checksum, (const guint8 *) dest, strlen (dest));
}

}

/* FIXME; we should also hash the post script */

/* Hash in each package */
Expand All @@ -126,6 +165,7 @@ compute_checksum_from_treefile_and_goal (RpmOstreeTreeComposeContext *self,
ret_checksum = g_strdup (g_checksum_get_string (checksum));

ret = TRUE;
out:
gs_transfer_out_value (out_checksum, &ret_checksum);
if (checksum) g_checksum_free (checksum);
return ret;
Expand Down Expand Up @@ -190,6 +230,7 @@ install_packages_in_root (RpmOstreeTreeComposeContext *self,
gs_free char *ret_new_inputhash = NULL;
g_autoptr(GKeyFile) treespec = g_key_file_new ();
JsonArray *enable_repos = NULL;
JsonArray *add_files = NULL;

/* TODO - uncomment this once we have SELinux working */
#if 0
Expand Down Expand Up @@ -268,8 +309,12 @@ install_packages_in_root (RpmOstreeTreeComposeContext *self,
if (!rpmostree_context_prepare_install (ctx, &hifinstall, cancellable, error))
goto out;

if (json_object_has_member (treedata, "add-files"))
add_files = json_object_get_array_member (treedata, "add-files");

/* FIXME - just do a depsolve here before we compute download requirements */
if (!compute_checksum_from_treefile_and_goal (self, hif_context_get_goal (hifctx),
contextdir, add_files,
&ret_new_inputhash, error))
goto out;

Expand Down Expand Up @@ -796,6 +841,9 @@ rpmostree_compose_builtin_tree (int argc,
if (!rpmostree_prepare_rootfs_for_commit (yumroot, treefile, cancellable, error))
goto out;

if (!rpmostree_copy_additional_files (yumroot, self->treefile_context_dirs->pdata[0], treefile, cancellable, error))
goto out;

if (!rpmostree_check_passwd (repo, yumroot, treefile_dirpath, treefile,
cancellable, error))
goto out;
Expand Down
77 changes: 77 additions & 0 deletions src/libpriv/rpmostree-postprocess.c
Original file line number Diff line number Diff line change
Expand Up @@ -1171,6 +1171,83 @@ rpmostree_rootfs_postprocess_common (int rootfs_fd,
return ret;
}

/**
* rpmostree_copy_additional_files:
*
* Copy external files, if specified in the configuration file, from
* the context directory to the rootfs.
*/
gboolean
rpmostree_copy_additional_files (GFile *rootfs,
GFile *context_directory,
JsonObject *treefile,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
JsonArray *add = NULL;
guint i, len;

gs_free char *dest_rootfs_path = g_strconcat (gs_file_get_path_cached (rootfs), ".post", NULL);
gs_unref_object GFile *targetroot = g_file_new_for_path (dest_rootfs_path);

if (json_object_has_member (treefile, "add-files"))
{
add = json_object_get_array_member (treefile, "add-files");
len = json_array_get_length (add);
}
else
{
ret = TRUE;
goto out;
}

for (i = 0; i < len; i++)
{
const char *src, *dest;

JsonArray *add_el = json_array_get_array_element (add, i);
gs_unref_object GFile *child = NULL;

if (!add_el)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Element in add-files is not an array");
goto out;
}

src = _rpmostree_jsonutil_array_require_string_element (add_el, 0, error);
if (!src)
goto out;

dest = _rpmostree_jsonutil_array_require_string_element (add_el, 1, error);
if (!dest)
goto out;

{
gs_unref_object GFile *srcfile = g_file_resolve_relative_path (context_directory, src);
const char *rootfs_path = gs_file_get_path_cached (rootfs);
gs_free char *destpath = g_strconcat (rootfs_path, "/", dest, NULL);
gs_unref_object GFile *destfile = g_file_resolve_relative_path (targetroot, destpath);
gs_unref_object GFile *target_tmpfilesd_parent = g_file_get_parent (destfile);

g_print ("Adding file '%s'\n", dest);

if (!gs_file_ensure_directory (target_tmpfilesd_parent, TRUE, cancellable, error))
goto out;

if (!g_file_copy (srcfile, destfile, 0, cancellable, NULL, NULL, error))
{
g_prefix_error (error, "Copying file '%s' into target: ", src);
goto out;
}
}
}
ret = TRUE;
out:
return ret;
}

gboolean
rpmostree_treefile_postprocessing (GFile *yumroot,
GFile *context_directory,
Expand Down
6 changes: 6 additions & 0 deletions src/libpriv/rpmostree-postprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,9 @@ rpmostree_commit (GFile *rootfs,
gboolean enable_selinux,
GCancellable *cancellable,
GError **error);
gboolean
rpmostree_copy_additional_files (GFile *rootfs,
GFile *context_directory,
JsonObject *treefile,
GCancellable *cancellable,
GError **error);
11 changes: 11 additions & 0 deletions tests/compose/test-repo-add-files.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"ref": "fedora/test",

"repos": ["test-repo"],

"selinux": false,

"packages": ["empty"],

"add-files": [["exported_file", "/exports/exported_file"]]
}
31 changes: 30 additions & 1 deletion tests/test-compose.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ unset G_DEBUG

(arch | grep -q x86_64) || { echo 1>&2 "$0 can be run only on x86_64"; echo "1..0" ; exit 77; }

echo "1..1"
echo "1..4"

ostree init --repo=repo --mode=archive-z2

Expand All @@ -47,3 +47,32 @@ ostree --repo=repo refs >refs.txt
assert_file_has_content refs.txt fedora/test

echo "ok compose"

# bring them in the current context so we can modify exported_file
ln -s $SRCDIR/test-repo-add-files.json .
ln -s $SRCDIR/test-repo.repo .

echo hello > exported_file

rpm-ostree --repo=repo compose tree --touch-if-changed=$(pwd)/touched test-repo-add-files.json
assert_has_file touched
old_mtime=$(stat -c %y touched)
ostree --repo=repo ls fedora/test /exports/exported_file | grep exported > exported.txt

assert_file_has_content exported.txt "/exports/exported_file"
assert_file_has_content exported.txt "0 0"
ostree --repo=repo rev-parse fedora/test > oldref.txt
rpm-ostree --repo=repo compose tree --touch-if-changed=$(pwd)/touched test-repo-add-files.json
new_mtime=$(stat -c %y touched)
ostree --repo=repo rev-parse fedora/test > newref.txt
assert_streq $(cat oldref.txt) $(cat newref.txt)
assert_streq "$old_mtime" "$new_mtime"

echo . >> exported_file
rpm-ostree --repo=repo compose tree --touch-if-changed=$(pwd)/touched test-repo-add-files.json
new_mtime=$(stat -c %y touched)
ostree --repo=repo rev-parse fedora/test > newref.txt
assert_not_streq $(cat oldref.txt) $(cat newref.txt)
assert_not_streq "$old_mtime" "$new_mtime"

echo "ok compose add files"