Add releasever opt, avoid opening up host's rpmdb in treecompose

Closes: https://github.com/projectatomic/rpm-ostree/issues/546

Previously, we'd open up the host's rpmdb for both `compose tree`
and `ex container`.  In the first case, because we require root, we'd
succeed.  For `ex container`, we'd spew an error.

Fixing this was trickier than I thought.  First because there was
*also* a libdnf bug here: https://github.com/rpm-software-management/libdnf/pull/307

Second, there's a compatibility hazard here for anyone using `.repo` files that
reference `$releasever`. This actually happened to me with `ex container` as I'd
just done a `ln -s /etc/yum.repos.d/fedora.repo rpmmd.repos.d`.  I fixed
that first by doing a `sed -i -e 's,$releasever,26,' rpmmd.repos.d/*.repo`.

As far as I can see today, none of Fedora Atomic or CentOS AH rely on this. But
in order to enhance compatibility, let's add a "releasever" option. This makes
it easier again to reuse stock `.repo` files if we wanted to do so.

(Also, I realized we can just use `/usr/share/empty` as *the* canonical immutable
 empty directory)

Closes: #875
Approved by: jlebon
This commit is contained in:
Colin Walters 2017-07-13 12:37:41 -04:00 committed by Atomic Bot
parent b52263506f
commit b46fc35901
6 changed files with 49 additions and 17 deletions

View File

@ -89,8 +89,9 @@ required: true
host:
distro: fedora/26/atomic
# copy yum.repos.d to get any injected repos from the host, which
# will point to a closer mirror
# Copy yum.repos.d to get any injected repos from the host, which
# will point to a closer mirror. Note we substitute $releasever
# since https://github.com/projectatomic/rpm-ostree/pull/875
tests:
- docker run --privileged --rm
-e RPMOSTREE_COMPOSE_TEST_USE_HOST_REPO=1
@ -98,6 +99,7 @@ tests:
-v $(pwd):/srv/code -w /srv/code
registry.fedoraproject.org/fedora:26 /bin/sh -c
"cp -fv /etc/yum.repos.d{.host/*.repo,} &&
for x in /etc/yum.repos.d/*.repo; do sed -i -e 's,\$releasever,26,' \$x; done &&
./ci/build.sh && make install && ./tests/compose"
artifacts:

View File

@ -133,6 +133,11 @@ It supports the following parameters:
Example: `ignore-removed-groups: ["avahi"]`
* `releasever`: String, optional: Used to set the librepo `$releasever` variable,
commonly used in yum repo files.
Example: `releasever: "26"`
* `automatic_version_prefix`: String, optional: Set the prefix for versions
on the commits. The idea is that if the previous commit on the branch to the
doesn't match the prefix, or doesn't have a version, then the new commit will

View File

@ -338,6 +338,13 @@ install_packages_in_root (RpmOstreeTreeComposeContext *self,
g_autoptr(GKeyFile) treespec = g_key_file_new ();
g_key_file_set_string (treespec, "tree", "ref", self->ref);
g_key_file_set_string_list (treespec, "tree", "packages", (const char *const*)packages, g_strv_length (packages));
{ const char *releasever;
if (!_rpmostree_jsonutil_object_get_optional_string_member (treedata, "releasever",
&releasever, error))
return FALSE;
if (releasever)
g_key_file_set_string (treespec, "tree", "releasever", releasever);
}
/* Some awful code to translate between JSON and GKeyFile */
if (json_object_has_member (treedata, "install-langs"))
@ -379,7 +386,7 @@ install_packages_in_root (RpmOstreeTreeComposeContext *self,
g_autoptr(RpmOstreeTreespec) treespec_value = rpmostree_treespec_new_from_keyfile (treespec, &tmp_error);
g_assert_no_error (tmp_error);
if (!rpmostree_context_setup (ctx, gs_file_get_path_cached (yumroot), "/", treespec_value,
if (!rpmostree_context_setup (ctx, gs_file_get_path_cached (yumroot), NULL, treespec_value,
cancellable, error))
return FALSE;
}

View File

@ -114,7 +114,7 @@ roc_context_prepare_for_root (ROContainerContext *rocctx,
if (!rocctx->ctx)
goto out;
if (!rpmostree_context_setup (rocctx->ctx, NULL, "/", treespec, cancellable, error))
if (!rpmostree_context_setup (rocctx->ctx, NULL, NULL, treespec, cancellable, error))
goto out;
ret = TRUE;

View File

@ -831,7 +831,7 @@ do_local_assembly (RpmOstreeSysrootUpgrader *self,
if (treespec == NULL)
return FALSE;
if (!rpmostree_context_setup (ctx, tmprootfs_abspath, NULL, treespec, cancellable, error))
if (!rpmostree_context_setup (ctx, tmprootfs_abspath, tmprootfs_abspath, treespec, cancellable, error))
return FALSE;
g_autoptr(OstreeRepo) pkgcache_repo = NULL;

View File

@ -531,6 +531,16 @@ context_repos_enable_only (RpmOstreeContext *context,
return TRUE;
}
/* Wraps `dnf_context_setup()`, and initializes state based on the treespec
* @spec. Another way to say it is we pair `DnfContext` with an
* `RpmOstreeTreespec`. For example, we handle "instlangs", set the rpmdb root
* to `/usr/share/rpm`, and handle the required rpm-md repos. The "packages"
* entry from @spec is processed later.
*
* If either @install_root or @source_root are `NULL`, `/usr/share/empty` is
* used. Typically @source_root being `NULL` is for "from scratch" root
* filesystems.
*/
gboolean
rpmostree_context_setup (RpmOstreeContext *self,
const char *install_root,
@ -539,24 +549,32 @@ rpmostree_context_setup (RpmOstreeContext *self,
GCancellable *cancellable,
GError **error)
{
const char *releasever = NULL;
g_autofree char **enabled_repos = NULL;
g_autofree char **instlangs = NULL;
/* This exists (as a canonically empty dir) at least on RHEL7+ */
static const char emptydir_path[] = "/usr/share/empty";
self->spec = g_object_ref (spec);
if (install_root)
dnf_context_set_install_root (self->hifctx, install_root);
else
{
/* We need this to ensure that libdnf doesn't read the host system packages */
if (!rpmostree_context_ensure_tmpdir (self, "dummy-instroot", error))
return FALSE;
g_autofree char *root = g_strconcat (self->tmpdir_path, "/dummy-instroot", NULL);
dnf_context_set_install_root (self->hifctx, root);
}
g_variant_dict_lookup (self->spec->dict, "releasever", "&s", &releasever);
if (source_root)
dnf_context_set_source_root (self->hifctx, source_root);
if (!install_root)
install_root = emptydir_path;
if (!source_root)
{
source_root = emptydir_path;
/* Hackaround libdnf's auto-introspection semantics. For e.g.
* treecompose/container, we currently require using .repo files which
* don't reference $releasever.
*/
dnf_context_set_release_ver (self->hifctx, releasever ?: "rpmostree-unset-releasever");
}
else if (releasever)
dnf_context_set_release_ver (self->hifctx, releasever);
dnf_context_set_install_root (self->hifctx, install_root);
dnf_context_set_source_root (self->hifctx, source_root);
if (g_variant_dict_lookup (self->spec->dict, "instlangs", "^a&s", &instlangs))
{