-
Notifications
You must be signed in to change notification settings - Fork 42
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
Implement silo level images #2772
Changes from 25 commits
f3c30a8
fa120f8
3d470c8
f6a99d5
3343ead
094ec23
974f31e
8c05776
1f77553
532e6e5
7016701
053d14e
96ab341
acdb77e
420af77
4c58909
3b1c576
5c34397
68e649a
e74f595
239c37a
7fd9329
abfb634
093f09b
c2a605e
fd48b21
d48460b
da9d1e7
ae67793
5d9dd3f
28c87cb
c96d484
c288e85
2f9ef0c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -136,6 +136,9 @@ enum PolarSnippet { | |
/// Generate it as a global resource, manipulable only to administrators | ||
FleetChild, | ||
|
||
/// Generate it as resource nested under the Silo | ||
InSilo, | ||
|
||
/// Generate it as a resource nested within a Project (either directly or | ||
/// indirectly) | ||
InProject, | ||
|
@@ -200,6 +203,31 @@ fn do_authz_resource( | |
resource_name, resource_name, | ||
), | ||
|
||
// If this resource is directly inside a Silo, we only need to define | ||
// permissions that are contingent on having roles on that Silo. | ||
(PolarSnippet::InSilo, _) => format!( | ||
r#" | ||
resource {} {{ | ||
permissions = [ | ||
"list_children", | ||
"modify", | ||
"read", | ||
"create_child", | ||
]; | ||
|
||
relations = {{ containing_silo: Silo }}; | ||
"list_children" if "viewer" on "containing_silo"; | ||
"read" if "viewer" on "containing_silo"; | ||
"modify" if "collaborator" on "containing_silo"; | ||
"create_child" if "collaborator" on "containing_silo"; | ||
}} | ||
|
||
has_relation(parent: Silo, "containing_silo", child: {}) | ||
if child.silo = parent; | ||
"#, | ||
resource_name, resource_name, | ||
), | ||
Comment on lines
+206
to
+229
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I patterned this off of |
||
|
||
// If this resource is directly inside a Project, we only need to define | ||
// permissions that are contingent on having roles on that Project. | ||
(PolarSnippet::InProject, "Project") => format!( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,14 +3,15 @@ | |
// file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
|
||
use super::{BlockSize, ByteCount, Digest}; | ||
use crate::schema::image; | ||
use crate::schema::{image, project_image, silo_image}; | ||
use db_macros::Resource; | ||
use nexus_types::external_api::views; | ||
use nexus_types::identity::Resource; | ||
use omicron_common::api::external::Error; | ||
use serde::{Deserialize, Serialize}; | ||
use uuid::Uuid; | ||
|
||
// Project images | ||
// Shared image definition | ||
zephraph marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#[derive( | ||
Queryable, | ||
Insertable, | ||
|
@@ -26,6 +27,29 @@ pub struct Image { | |
#[diesel(embed)] | ||
pub identity: ImageIdentity, | ||
|
||
pub silo_id: Uuid, | ||
pub project_id: Option<Uuid>, | ||
|
||
pub volume_id: Uuid, | ||
pub url: Option<String>, | ||
pub os: String, | ||
pub version: String, | ||
pub digest: Option<Digest>, | ||
pub block_size: BlockSize, | ||
|
||
#[diesel(column_name = size_bytes)] | ||
pub size: ByteCount, | ||
} | ||
|
||
#[derive( | ||
Queryable, Selectable, Clone, Debug, Resource, Serialize, Deserialize, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
)] | ||
#[diesel(table_name = project_image)] | ||
pub struct ProjectImage { | ||
#[diesel(embed)] | ||
pub identity: ProjectImageIdentity, | ||
|
||
pub silo_id: Uuid, | ||
pub project_id: Uuid, | ||
pub volume_id: Uuid, | ||
pub url: Option<String>, | ||
|
@@ -38,6 +62,142 @@ pub struct Image { | |
pub size: ByteCount, | ||
} | ||
|
||
#[derive( | ||
Queryable, Selectable, Clone, Debug, Resource, Serialize, Deserialize, | ||
)] | ||
#[diesel(table_name = silo_image)] | ||
pub struct SiloImage { | ||
#[diesel(embed)] | ||
pub identity: SiloImageIdentity, | ||
|
||
pub silo_id: Uuid, | ||
pub volume_id: Uuid, | ||
pub url: Option<String>, | ||
pub os: String, | ||
pub version: String, | ||
pub digest: Option<Digest>, | ||
pub block_size: BlockSize, | ||
|
||
#[diesel(column_name = size_bytes)] | ||
pub size: ByteCount, | ||
} | ||
|
||
impl TryFrom<Image> for ProjectImage { | ||
type Error = Error; | ||
|
||
fn try_from(image: Image) -> Result<Self, Self::Error> { | ||
match image.project_id { | ||
Some(project_id) => Ok(Self { | ||
identity: ProjectImageIdentity { | ||
id: image.id(), | ||
name: image.name().clone().into(), | ||
description: image.description().to_string(), | ||
time_created: image.time_created(), | ||
time_modified: image.time_modified(), | ||
time_deleted: image.time_deleted(), | ||
}, | ||
silo_id: image.silo_id, | ||
project_id, | ||
volume_id: image.volume_id, | ||
url: image.url, | ||
os: image.os, | ||
version: image.version, | ||
digest: image.digest, | ||
block_size: image.block_size, | ||
size: image.size, | ||
}), | ||
None => Err(Error::internal_error( | ||
"tried to convert non-project image to project image", | ||
)), | ||
} | ||
} | ||
} | ||
|
||
impl From<ProjectImage> for SiloImage { | ||
fn from(value: ProjectImage) -> Self { | ||
let image: Image = value.into(); | ||
Image { project_id: None, ..image }.try_into().unwrap() | ||
} | ||
} | ||
|
||
impl TryFrom<Image> for SiloImage { | ||
type Error = Error; | ||
|
||
fn try_from(image: Image) -> Result<Self, Self::Error> { | ||
match image.project_id { | ||
Some(_) => Err(Error::internal_error( | ||
"tried to convert non-silo image to silo image", | ||
)), | ||
None => Ok(Self { | ||
identity: SiloImageIdentity { | ||
id: image.id(), | ||
name: image.name().clone().into(), | ||
description: image.description().to_string(), | ||
time_created: image.time_created(), | ||
time_modified: image.time_modified(), | ||
time_deleted: image.time_deleted(), | ||
}, | ||
silo_id: image.silo_id, | ||
volume_id: image.volume_id, | ||
url: image.url, | ||
os: image.os, | ||
version: image.version, | ||
digest: image.digest, | ||
block_size: image.block_size, | ||
size: image.size, | ||
}), | ||
} | ||
} | ||
} | ||
|
||
impl From<ProjectImage> for Image { | ||
fn from(image: ProjectImage) -> Self { | ||
Self { | ||
identity: ImageIdentity { | ||
id: image.id(), | ||
name: image.name().clone().into(), | ||
description: image.description().to_string(), | ||
time_created: image.time_created(), | ||
time_modified: image.time_modified(), | ||
time_deleted: image.time_deleted(), | ||
}, | ||
silo_id: image.silo_id, | ||
project_id: Some(image.project_id), | ||
volume_id: image.volume_id, | ||
url: image.url, | ||
os: image.os, | ||
version: image.version, | ||
digest: image.digest, | ||
block_size: image.block_size, | ||
size: image.size, | ||
} | ||
} | ||
} | ||
|
||
impl From<SiloImage> for Image { | ||
fn from(image: SiloImage) -> Self { | ||
Self { | ||
identity: ImageIdentity { | ||
id: image.id(), | ||
name: image.name().clone().into(), | ||
description: image.description().to_string(), | ||
time_created: image.time_created(), | ||
time_modified: image.time_modified(), | ||
time_deleted: image.time_deleted(), | ||
}, | ||
silo_id: image.silo_id, | ||
project_id: None, | ||
volume_id: image.volume_id, | ||
url: image.url, | ||
os: image.os, | ||
version: image.version, | ||
digest: image.digest, | ||
block_size: image.block_size, | ||
size: image.size, | ||
} | ||
} | ||
} | ||
|
||
impl From<Image> for views::Image { | ||
fn from(image: Image) -> Self { | ||
Self { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that project images also include
silo_id
. This is necessary to convert them back to the base image type.