Handle "pinned commits" specifically

There are a few scenarios today where one might deliver content
to a machine via an external transport.  For example, take the
scenario of a single server updated via USB drive.  While we
can provide a refspec...what should the remote be?  (This gets
into ostree collections).  There's nothing really that can
happen when typing `rpm-ostree upgrade` unless the USB stick
is plugged in.  That type of scenario should be emphasized
by pinning the commit - the machine is updated via an external
script.

Another case: we're experimenting embedding OSTree commits inside OCI
containers.  Here again since rpm-ostree can't understand how to
pull content from containers, it's saner to drop the refspec
bits, and pin to a commit.

Further enhancements will follow to make the admin experience more
obvious.

Closes: #1396
Approved by: jlebon
This commit is contained in:
Colin Walters 2018-06-08 17:09:10 -04:00 committed by Atomic Bot
parent 26f04595b2
commit 27bd7b97bb
8 changed files with 93 additions and 20 deletions

View File

@ -480,6 +480,7 @@ print_one_deployment (RPMOSTreeSysroot *sysroot_proxy,
g_autofree char *canonrefspec = rpmostree_refspec_to_string (refspectype, refspec_data);
switch (refspectype)
{
case RPMOSTREE_REFSPEC_TYPE_CHECKSUM:
case RPMOSTREE_REFSPEC_TYPE_OSTREE:
{
g_print ("%s", canonrefspec);

View File

@ -397,6 +397,7 @@ rpmostree_sysroot_upgrader_pull_base (RpmOstreeSysrootUpgrader *self,
switch (refspec_type)
{
case RPMOSTREE_REFSPEC_TYPE_CHECKSUM:
case RPMOSTREE_REFSPEC_TYPE_OSTREE:
{
g_autofree char *origin_remote = NULL;

View File

@ -303,6 +303,9 @@ rpmostreed_deployment_generate_variant (OstreeSysroot *sysroot,
switch (refspec_type)
{
case RPMOSTREE_REFSPEC_TYPE_CHECKSUM:
/* Nothing to do here */
break;
case RPMOSTREE_REFSPEC_TYPE_OSTREE:
{
if (!variant_add_remote_status (repo, refspec, base_checksum, &dict, error))
@ -424,7 +427,9 @@ add_all_commit_details_to_vardict (OstreeDeployment *deployment,
return FALSE;
refspec = refspec_remainder;
}
refspec_is_ostree = (refspec_type == RPMOSTREE_REFSPEC_TYPE_OSTREE);
refspec_is_ostree = refspec_type == RPMOSTREE_REFSPEC_TYPE_OSTREE;
if (refspec_type == RPMOSTREE_REFSPEC_TYPE_CHECKSUM && !commit)
checksum = refspec;
g_assert (refspec);
@ -962,10 +967,14 @@ rpmostreed_update_generate_variant (OstreeDeployment *booted_deployment,
return FALSE;
/* we don't support rojig-based origins yet */
if (refspectype != RPMOSTREE_REFSPEC_TYPE_OSTREE)
switch (refspectype)
{
case RPMOSTREE_REFSPEC_TYPE_ROJIG:
*out_update = NULL;
return TRUE; /* NB: early return */
case RPMOSTREE_REFSPEC_TYPE_OSTREE:
case RPMOSTREE_REFSPEC_TYPE_CHECKSUM:
break;
}
/* just skip over "ostree://" so we can talk with libostree without thinking about it */

View File

@ -76,6 +76,7 @@ change_origin_refspec (OstreeSysroot *sysroot,
return TRUE;
}
case RPMOSTREE_REFSPEC_TYPE_OSTREE:
case RPMOSTREE_REFSPEC_TYPE_CHECKSUM:
break;
}
@ -137,6 +138,9 @@ apply_revision_override (RpmostreedTransaction *transaction,
RpmOstreeRefspecType refspectype;
rpmostree_origin_classify_refspec (origin, &refspectype, NULL);
if (refspectype == RPMOSTREE_REFSPEC_TYPE_CHECKSUM)
return glnx_throw (error, "Cannot look up version while pinned to commit");
g_autofree char *checksum = NULL;
g_autofree char *version = NULL;
if (!rpmostreed_parse_revision (revision, &checksum, &version, error))
@ -163,6 +167,8 @@ apply_revision_override (RpmostreedTransaction *transaction,
/* This case we'll look up later */
rpmostree_origin_set_rojig_version (origin, version);
break;
case RPMOSTREE_REFSPEC_TYPE_CHECKSUM:
g_assert_not_reached (); /* Handled above */
}
}
else
@ -182,6 +188,8 @@ apply_revision_override (RpmostreedTransaction *transaction,
* on.
*/
break;
case RPMOSTREE_REFSPEC_TYPE_CHECKSUM:
g_assert_not_reached (); /* Handled above */
}
rpmostree_origin_set_override_commit (origin, checksum, version);
@ -1135,6 +1143,10 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
changed = TRUE;
}
/* Past this point we've computed the origin */
RpmOstreeRefspecType refspec_type;
rpmostree_origin_classify_refspec (origin, &refspec_type, NULL);
if (download_metadata_only)
{
/* We have to short-circuit the usual path here; we already downloaded the ostree
@ -1246,7 +1258,10 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
}
else
{
if (!self->revision)
if (refspec_type == RPMOSTREE_REFSPEC_TYPE_CHECKSUM
&& layering_type < RPMOSTREE_SYSROOT_UPGRADER_LAYERING_RPMMD_REPOS)
rpmostree_output_message ("Pinned to commit; no upgrade available");
else if (!self->revision)
rpmostree_output_message ("No upgrade available.");
else
rpmostree_output_message ("No change.");

View File

@ -50,7 +50,9 @@
static OstreeRepo * get_pkgcache_repo (RpmOstreeContext *self);
/* Given a string, look for ostree:// or rojig:// prefix and
* return its type and the remainder of the string.
* return its type and the remainder of the string. Note
* that ostree:// can be either a refspec (TYPE_OSTREE) or
* a bare commit (TYPE_COMMIT).
*/
gboolean
rpmostree_refspec_classify (const char *refspec,
@ -58,29 +60,28 @@ rpmostree_refspec_classify (const char *refspec,
const char **out_remainder,
GError **error)
{
if (g_str_has_prefix (refspec, RPMOSTREE_REFSPEC_OSTREE_PREFIX))
{
*out_type = RPMOSTREE_REFSPEC_TYPE_OSTREE;
if (out_remainder)
*out_remainder = refspec + strlen (RPMOSTREE_REFSPEC_OSTREE_PREFIX);
return TRUE;
}
else if (g_str_has_prefix (refspec, RPMOSTREE_REFSPEC_ROJIG_PREFIX))
if (g_str_has_prefix (refspec, RPMOSTREE_REFSPEC_ROJIG_PREFIX))
{
*out_type = RPMOSTREE_REFSPEC_TYPE_ROJIG;
if (out_remainder)
*out_remainder = refspec + strlen (RPMOSTREE_REFSPEC_ROJIG_PREFIX);
return TRUE;
}
/* Add any other prefixes here */
/* Fallback case when we have no explicit prefix - treat this as ostree://
* for compatibility. In the future we may do some error checking here,
* i.e. trying to parse the refspec.
*/
*out_type = RPMOSTREE_REFSPEC_TYPE_OSTREE;
/* For compatibility, fall back to ostree:// when we have no prefix. */
const char *remainder;
if (g_str_has_prefix (refspec, RPMOSTREE_REFSPEC_OSTREE_PREFIX))
remainder = refspec + strlen (RPMOSTREE_REFSPEC_OSTREE_PREFIX);
else
remainder = refspec;
if (ostree_validate_checksum_string (remainder, NULL))
*out_type = RPMOSTREE_REFSPEC_TYPE_CHECKSUM;
else
*out_type = RPMOSTREE_REFSPEC_TYPE_OSTREE;
if (out_remainder)
*out_remainder = refspec;
*out_remainder = remainder;
return TRUE;
}
@ -92,6 +93,7 @@ rpmostree_refspec_to_string (RpmOstreeRefspecType reftype,
switch (reftype)
{
case RPMOSTREE_REFSPEC_TYPE_OSTREE:
case RPMOSTREE_REFSPEC_TYPE_CHECKSUM:
prefix = RPMOSTREE_REFSPEC_OSTREE_PREFIX;
break;
case RPMOSTREE_REFSPEC_TYPE_ROJIG:

View File

@ -51,6 +51,7 @@ G_DECLARE_FINAL_TYPE (RpmOstreeTreespec, rpmostree_treespec, RPMOSTREE, TREESPEC
typedef enum {
RPMOSTREE_REFSPEC_TYPE_OSTREE,
RPMOSTREE_REFSPEC_TYPE_ROJIG,
RPMOSTREE_REFSPEC_TYPE_CHECKSUM,
} RpmOstreeRefspecType;
#define RPMOSTREE_REFSPEC_OSTREE_PREFIX "ostree://"

View File

@ -125,7 +125,8 @@ rpmostree_origin_parse_keyfile (GKeyFile *origin,
return glnx_null_throw (error, "Duplicate origin/refspec and origin/rojig in deployment origin");
else if (refspec)
{
ret->refspec_type = RPMOSTREE_REFSPEC_TYPE_OSTREE;
if (!rpmostree_refspec_classify (refspec, &ret->refspec_type, NULL, error))
return FALSE;
/* Note the lack of a prefix here so that code that just calls
* rpmostree_origin_get_refspec() in the ostree:// case
* sees it without the prefix for compatibility.
@ -206,6 +207,7 @@ rpmostree_origin_get_full_refspec (RpmOstreeOrigin *origin,
switch (origin->refspec_type)
{
case RPMOSTREE_REFSPEC_TYPE_OSTREE:
case RPMOSTREE_REFSPEC_TYPE_CHECKSUM:
return g_strdup (origin->cached_refspec);
case RPMOSTREE_REFSPEC_TYPE_ROJIG:
return g_strconcat (RPMOSTREE_REFSPEC_ROJIG_PREFIX, origin->cached_refspec, NULL);
@ -485,6 +487,7 @@ rpmostree_origin_set_rebase (RpmOstreeOrigin *origin,
origin->cached_refspec = g_strdup (refspecdata);
switch (origin->refspec_type)
{
case RPMOSTREE_REFSPEC_TYPE_CHECKSUM:
case RPMOSTREE_REFSPEC_TYPE_OSTREE:
{
g_key_file_remove_key (origin->kf, "origin", "rojig", NULL);
@ -577,6 +580,7 @@ update_keyfile_pkgs_from_cache (RpmOstreeOrigin *origin,
switch (origin->refspec_type)
{
case RPMOSTREE_REFSPEC_TYPE_OSTREE:
case RPMOSTREE_REFSPEC_TYPE_CHECKSUM:
{
g_key_file_set_value (origin->kf, "origin", "baserefspec",
origin->cached_refspec);

View File

@ -0,0 +1,40 @@
#!/bin/bash
#
# Copyright (C) 2018 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
set -euo pipefail
. ${commondir}/libtest.sh
. ${commondir}/libvm.sh
set -x
checksum=$(vm_get_booted_csum)
vm_rpmostree rebase :${checksum}
vm_assert_status_jq ".deployments[0][\"origin\"] == \"${checksum}\""
vm_rpmostree status > status.txt
assert_file_has_content status.txt '^ ostree://'${checksum}
echo "ok pin to commit"
vm_rpmostree upgrade >out.txt
assert_file_has_content out.txt 'Pinned to commit; no upgrade available'
if vm_rpmostree deploy 42 2>err.txt; then
fatal "deployed version from commit?"
fi
assert_file_has_content err.txt 'Cannot look up version while pinned to commit'
echo "ok cmds"