145 );145 );
146 }146 }
147147
148 let mut missing_parts = expectations.parts.clone();
148 let mut parts = BTreeMap::new();149 let mut parts = BTreeMap::new();
149 for part in host_on.read_dir(&out).await? {150 for part in host_on.read_dir(&out).await? {
150 if part == "created_at" || part == "expires_at" || part == "marker" {151 if part == "created_at" || part == "expires_at" || part == "marker" {
151 continue;152 continue;
152 }153 }
154 let Some(part_def) = missing_parts.remove(&part) else {
155 bail!("secret generator has produced an unexpected part: {part}");
156 };
153 let contents: SecretData = host_on157 let contents: SecretData = host_on
154 .read_file_text(format!("{out}/{part}"))158 .read_file_text(format!("{out}/{part}"))
155 .await?159 .await?
156 .parse()160 .parse()
157 .map_err(|e| anyhow!("failed to decode secret {out:?} part {part:?}: {e}"))?;161 .map_err(|e| anyhow!("failed to decode secret {out:?} part {part:?}: {e}"))?;
162
163 ensure!(
164 contents.encrypted == part_def.encrypted,
165 "part {part} produced by generator is supposed to be {}, but it was not",
166 if part_def.encrypted {
167 "encrypted"
168 } else {
169 "plaintext"
170 }
171 );
172
158 parts.insert(part.to_owned(), FleetSecretPart { raw: contents });173 parts.insert(part.to_owned(), FleetSecretPart { raw: contents });
159 }174 }
175 if !missing_parts.is_empty() {
176 bail!(
177 "the secret generator has not produced the following expected parts: {missing_parts:?}"
178 );
179 }
160180
161 let created_at = host_on.read_file_value(format!("{out}/created_at")).await?;181 let created_at = host_on.read_file_value(format!("{out}/created_at")).await?;
162 let expires_at = host_on182 let expires_at = host_on