Skip to content

Commit 69ca562

Browse files
authored
[1/n] ensure uniqueness of fake artifact hashes
In Omicron we're adding a constraint that (deployment unit kind, hash) is globally unique. We can't ensure *global* uniqueness in tufaceous at the moment, but we can ensure uniqueness within a repository. This change makes it so that deployment units are unique, but does not verify this. The next commit in the series (#16) will perform this verification (that's a bit big so I wanted to separate this out). Reviewers: iliana Reviewed By: iliana Pull Request: #15
1 parent d647770 commit 69ca562

File tree

2 files changed

+67
-21
lines changed

2 files changed

+67
-21
lines changed

lib/src/artifact.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,27 @@ impl AddArtifact {
110110
}
111111
}
112112

113-
pub(crate) fn make_filler_text(length: usize) -> Vec<u8> {
114-
std::iter::repeat(FILLER_TEXT).flatten().copied().take(length).collect()
113+
pub(crate) fn make_filler_text(
114+
// This can be either the artifact kind, or the deployment unit kind for a
115+
// composite artifact.
116+
kind: &str,
117+
version: &ArtifactVersion,
118+
length: usize,
119+
) -> Vec<u8> {
120+
// Add the kind and version to the filler text first. This ensures that
121+
// hashes are unique by kind and version.
122+
let mut out = Vec::with_capacity(length);
123+
out.extend_from_slice(kind.as_bytes());
124+
out.extend_from_slice(b":");
125+
out.extend_from_slice(version.as_str().as_bytes());
126+
out.extend_from_slice(b":");
127+
128+
let remaining = length.saturating_sub(out.len());
129+
out.extend(
130+
std::iter::repeat(FILLER_TEXT).flatten().copied().take(remaining),
131+
);
132+
133+
out
115134
}
116135

117136
/// Represents host phase images.

lib/src/assemble/manifest.rs

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,17 @@ impl ArtifactManifest {
8989
) -> Result<(KnownArtifactKind, Vec<ArtifactData>)> {
9090
let entries = entries
9191
.into_iter()
92-
.map(|data| {
93-
let source = match data.source {
92+
.map(|artifact_data| {
93+
let source = match artifact_data.source {
9494
DeserializedArtifactSource::File { path } => {
9595
ArtifactSource::File(base_dir.join(path))
9696
}
9797
DeserializedArtifactSource::Fake { size } => {
98-
let fake_data =
99-
FakeDataAttributes::new(kind, &data.version)
100-
.make_data(size as usize);
98+
let fake_data = FakeDataAttributes::new(
99+
kind,
100+
&artifact_data.version,
101+
)
102+
.make_data(size as usize);
101103
ArtifactSource::Memory(fake_data.into())
102104
}
103105
DeserializedArtifactSource::CompositeHost {
@@ -127,11 +129,17 @@ impl ArtifactManifest {
127129
mtime_source,
128130
)?;
129131
phase_1.with_entry(
130-
FakeDataAttributes::new(kind, &data.version),
132+
FakeDataAttributes::new(
133+
kind,
134+
&artifact_data.version,
135+
),
131136
|entry| builder.append_phase_1(entry),
132137
)?;
133138
phase_2.with_entry(
134-
FakeDataAttributes::new(kind, &data.version),
139+
FakeDataAttributes::new(
140+
kind,
141+
&artifact_data.version,
142+
),
135143
|entry| builder.append_phase_2(entry),
136144
)?;
137145
ArtifactSource::Memory(builder.finish()?.into())
@@ -164,11 +172,17 @@ impl ArtifactManifest {
164172
mtime_source,
165173
)?;
166174
archive_a.with_entry(
167-
FakeDataAttributes::new(kind, &data.version),
175+
FakeDataAttributes::new(
176+
kind,
177+
&artifact_data.version,
178+
),
168179
|entry| builder.append_archive_a(entry),
169180
)?;
170181
archive_b.with_entry(
171-
FakeDataAttributes::new(kind, &data.version),
182+
FakeDataAttributes::new(
183+
kind,
184+
&artifact_data.version,
185+
),
172186
|entry| builder.append_archive_b(entry),
173187
)?;
174188
ArtifactSource::Memory(builder.finish()?.into())
@@ -198,16 +212,17 @@ impl ArtifactManifest {
198212
)?;
199213

200214
for zone in zones {
201-
zone.with_name_and_entry(|name, entry| {
202-
builder.append_zone(name, entry)
203-
})?;
215+
zone.with_name_and_entry(
216+
&artifact_data.version,
217+
|name, entry| builder.append_zone(name, entry),
218+
)?;
204219
}
205220
ArtifactSource::Memory(builder.finish()?.into())
206221
}
207222
};
208223
let data = ArtifactData {
209-
name: data.name,
210-
version: data.version,
224+
name: artifact_data.name,
225+
version: artifact_data.version,
211226
source,
212227
};
213228
Ok(data)
@@ -286,7 +301,13 @@ impl<'a> FakeDataAttributes<'a> {
286301
KnownArtifactKind::Host
287302
| KnownArtifactKind::Trampoline
288303
| KnownArtifactKind::ControlPlane
289-
| KnownArtifactKind::Zone => return make_filler_text(size),
304+
| KnownArtifactKind::Zone => {
305+
return make_filler_text(
306+
&self.kind.to_string(),
307+
self.version,
308+
size,
309+
);
310+
}
290311

291312
// hubris artifacts: build a fake archive (SimGimletSp and
292313
// SimGimletRot are used by sp-sim)
@@ -569,7 +590,11 @@ impl DeserializedControlPlaneZoneSource {
569590
matches!(self, DeserializedControlPlaneZoneSource::Fake { .. })
570591
}
571592

572-
fn with_name_and_entry<F, T>(&self, f: F) -> Result<T>
593+
fn with_name_and_entry<F, T>(
594+
&self,
595+
version: &ArtifactVersion,
596+
f: F,
597+
) -> Result<T>
573598
where
574599
F: FnOnce(&str, CompositeEntry<'_>) -> Result<T>,
575600
{
@@ -600,8 +625,7 @@ impl DeserializedControlPlaneZoneSource {
600625

601626
let metadata = Metadata::new(ArchiveType::Layer(LayerInfo {
602627
pkg: name.clone(),
603-
// TODO: replace with `ArtifactVersion` once it's passed in
604-
version: ArtifactVersion::new_const("0.0.0"),
628+
version: version.clone(),
605629
}));
606630
metadata.append_to_tar(&mut tar, 0)?;
607631

@@ -612,7 +636,10 @@ impl DeserializedControlPlaneZoneSource {
612636
h.set_size(*size);
613637
h.set_mtime(0);
614638
h.set_cksum();
615-
tar.append(&h, make_filler_text(*size as usize).as_slice())?;
639+
tar.append(
640+
&h,
641+
make_filler_text(name, version, *size as usize).as_slice(),
642+
)?;
616643

617644
let data = tar.into_inner()?.finish()?;
618645
(format!("{name}.tar.gz"), data, MtimeSource::Zero)

0 commit comments

Comments
 (0)