Skip to content
Open
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
53 changes: 45 additions & 8 deletions nexus/db-model/src/target_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use super::{Generation, impl_enum_type};
use super::Generation;
use crate::typed_uuid::DbTypedUuid;
use anyhow::Context;
use chrono::{DateTime, Utc};
use nexus_db_schema::schema::target_release;
use omicron_uuid_kinds::TufRepoKind;
use omicron_uuid_kinds::{TufRepoKind, TufRepoUuid};

use crate::impl_enum_type;

impl_enum_type!(
TargetReleaseSourceEnum:

/// The source of the software release that should be deployed to the rack.
#[derive(Copy, Clone, Debug, AsExpression, FromSqlRow, PartialEq, Eq, Hash)]
pub enum TargetReleaseSource;
/// The source of the software release that should be deployed to the
/// rack.
#[derive(
Copy, Clone, Debug, AsExpression, FromSqlRow, PartialEq, Eq, Hash,
)]
pub enum DbTargetReleaseSource;

Unspecified => b"unspecified"
SystemVersion => b"system_version"
Expand All @@ -32,18 +38,30 @@ pub struct TargetRelease {
pub time_requested: DateTime<Utc>,

/// The source of the target release.
pub release_source: TargetReleaseSource,
///
/// Strongly consider using `TargetRelease::release_source()` instead of
/// accessing this field; this is `pub` to allow database queries.
pub release_source: DbTargetReleaseSource,

/// The TUF repo containing the target release.
///
/// Strongly consider using `TargetRelease::release_source()` instead of
/// accessing this field; this is `pub` to allow database queries.
pub tuf_repo_id: Option<DbTypedUuid<TufRepoKind>>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TargetReleaseSource {
Unspecified,
SystemVersion(TufRepoUuid),
}

impl TargetRelease {
pub fn new_unspecified(prev: &TargetRelease) -> Self {
Self {
generation: Generation(prev.generation.next()),
time_requested: Utc::now(),
release_source: TargetReleaseSource::Unspecified,
release_source: DbTargetReleaseSource::Unspecified,
tuf_repo_id: None,
}
}
Expand All @@ -55,8 +73,27 @@ impl TargetRelease {
Self {
generation: Generation(prev.generation.next()),
time_requested: Utc::now(),
release_source: TargetReleaseSource::SystemVersion,
release_source: DbTargetReleaseSource::SystemVersion,
tuf_repo_id: Some(tuf_repo_id),
}
}

pub fn release_source(&self) -> anyhow::Result<TargetReleaseSource> {
match self.release_source {
DbTargetReleaseSource::Unspecified => {
Ok(TargetReleaseSource::Unspecified)
}
DbTargetReleaseSource::SystemVersion => {
let repo_id = self.tuf_repo_id.with_context(|| {
format!(
"invalid database contents: target release generation \
{} has release source `system_version` with no \
`tuf_repo_id`",
*self.generation
)
})?;
Ok(TargetReleaseSource::SystemVersion(repo_id.into()))
}
}
}
}
13 changes: 7 additions & 6 deletions nexus/db-queries/src/db/datastore/target_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,10 +346,9 @@ mod test {
assert_eq!(initial_target_release.generation, Generation(1.into()));
assert!(initial_target_release.time_requested < Utc::now());
assert_eq!(
initial_target_release.release_source,
initial_target_release.release_source().unwrap(),
TargetReleaseSource::Unspecified
);
assert!(initial_target_release.tuf_repo_id.is_none());

// We should be able to set a new generation just like the first.
// We allow some slack in the timestamp comparison because the
Expand All @@ -366,7 +365,10 @@ mod test {
.abs()
< TimeDelta::new(0, 1_000).expect("1 μsec")
);
assert!(target_release.tuf_repo_id.is_none());
assert_eq!(
target_release.release_source().unwrap(),
TargetReleaseSource::Unspecified
);

// Trying to reuse a generation should fail.
assert!(
Expand Down Expand Up @@ -408,10 +410,9 @@ mod test {
assert!(target_release.time_requested >= before);
assert!(target_release.time_requested <= after);
assert_eq!(
target_release.release_source,
TargetReleaseSource::SystemVersion
target_release.release_source().unwrap(),
TargetReleaseSource::SystemVersion(tuf_repo_id.into())
);
assert_eq!(target_release.tuf_repo_id, Some(tuf_repo_id));

// Clean up.
db.terminate().await;
Expand Down
12 changes: 5 additions & 7 deletions nexus/db-queries/src/db/datastore/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,23 @@ use nexus_db_errors::OptionalError;
use nexus_db_errors::{ErrorHandler, public_error_from_diesel};
use nexus_db_lookup::DbConnection;
use nexus_db_model::{
ArtifactHash, DbTypedUuid, TargetRelease, TufArtifact, TufRepo,
TufRepoDescription, TufRepoUpload, TufTrustRoot, to_db_typed_uuid,
ArtifactHash, TargetRelease, TufArtifact, TufRepo, TufRepoDescription,
TufRepoUpload, TufTrustRoot, to_db_typed_uuid,
};
use nexus_types::external_api::views::TufRepoUploadStatus;
use omicron_common::api::external::{
self, CreateResult, DataPageParams, DeleteResult, Generation,
ListResultVec, LookupResult, LookupType, ResourceType, UpdateResult,
};
use omicron_common::api::external::{Error, InternalContext};
use omicron_uuid_kinds::TufRepoKind;
use omicron_uuid_kinds::TypedUuid;
use omicron_uuid_kinds::{GenericUuid, TufRepoUuid};
use semver::Version;
use swrite::{SWrite, swrite};
use tufaceous_artifact::ArtifactVersion;
use uuid::Uuid;

async fn artifacts_for_repo(
repo_id: TypedUuid<TufRepoKind>,
repo_id: TufRepoUuid,
conn: &async_bb8_diesel::Connection<DbConnection>,
) -> Result<Vec<TufArtifact>, DieselError> {
use nexus_db_schema::schema::tuf_artifact::dsl as tuf_artifact_dsl;
Expand Down Expand Up @@ -102,7 +100,7 @@ impl DataStore {
pub async fn tuf_repo_get_by_id(
&self,
opctx: &OpContext,
repo_id: TypedUuid<TufRepoKind>,
repo_id: TufRepoUuid,
) -> LookupResult<TufRepoDescription> {
opctx.authorize(authz::Action::Read, &authz::FLEET).await?;

Expand Down Expand Up @@ -165,7 +163,7 @@ impl DataStore {
pub async fn tuf_repo_get_version(
&self,
opctx: &OpContext,
tuf_repo_id: &DbTypedUuid<TufRepoKind>,
tuf_repo_id: &TufRepoUuid,
) -> LookupResult<semver::Version> {
opctx
.authorize(authz::Action::Read, &authz::TARGET_RELEASE_CONFIG)
Expand Down
Loading
Loading