Skip to content

Commit a862b7f

Browse files
feat(package_manager): manage tar files (#2034)
1 parent 63979f1 commit a862b7f

File tree

7 files changed

+393
-387
lines changed

7 files changed

+393
-387
lines changed

agent-control/src/package/extract.rs

Lines changed: 59 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,30 @@ use zip::ZipArchive;
99

1010
#[derive(Debug, Error)]
1111
#[error("extract error: {0}")]
12-
pub struct ExtractError(String);
12+
pub struct ExtractError(pub String);
1313

1414
impl PackageType {
1515
#[instrument(skip_all, fields(archive_path = %archive_path.to_string_lossy()),name = "extracting_archive")]
16-
pub fn extract(self, archive_path: &Path, destination_path: &Path) -> Result<(), ExtractError> {
16+
pub fn extract(&self, archive_path: &Path, dest_path: &Path) -> Result<(), ExtractError> {
1717
match self {
18-
PackageType::Tar => extract_tar_gz(archive_path, destination_path),
19-
PackageType::Zip => extract_zip(archive_path, destination_path),
18+
PackageType::Tar => extract_tar_gz(archive_path, dest_path),
19+
PackageType::Zip => extract_zip(archive_path, dest_path),
2020
}
2121
}
2222
}
2323

2424
/// Extracts a tar.gz archive located at `archive_path` into the directory at `destination_path`.
2525
/// This operation is relatively sensitive in that it will not write files outside of the path specified by dst.
2626
/// Files in the archive which have a '..' in their path are skipped during the unpacking process.
27-
fn extract_tar_gz(archive_path: &Path, destination_path: &Path) -> Result<(), ExtractError> {
27+
fn extract_tar_gz(tar_path: &Path, destination_path: &Path) -> Result<(), ExtractError> {
2828
debug!("Extracting tar.gz archive to '{:?}'", destination_path);
2929

30-
let tar_gz = File::open(archive_path)
31-
.map_err(|e| ExtractError(format!("opening tar.gz file: {}", e)))?;
30+
let tar_gz =
31+
File::open(tar_path).map_err(|e| ExtractError(format!("opening tar.gz file: {}", e)))?;
3232
let tar = GzDecoder::new(tar_gz);
3333
Archive::new(tar)
3434
.unpack(destination_path)
35-
.map_err(|e| ExtractError(format!("extracting tar.gz file: {}", e)))
35+
.map_err(|e| ExtractError(format!("extracting tar.gz file: {e}",)))
3636
}
3737

3838
/// Extracts a zip archive located at `zip_path` into the directory at `destination`.
@@ -48,11 +48,11 @@ fn extract_zip(zip_path: &Path, destination: &Path) -> Result<(), ExtractError>
4848

4949
archive
5050
.extract(destination)
51-
.map_err(|e| ExtractError(format!("extracting zip file: {}", e)))
51+
.map_err(|e| ExtractError(format!("extracting zip file: {e}")))
5252
}
5353

5454
#[cfg(test)]
55-
mod tests {
55+
pub mod tests {
5656
use super::*;
5757
use crate::package::extract::PackageType::{Tar, Zip};
5858
use assert_matches::assert_matches;
@@ -103,15 +103,13 @@ mod tests {
103103
let tmp_dir_archive = tempdir().unwrap();
104104
let tmp_file_archive = tmp_dir_archive.path().join("my.tar.gz");
105105

106-
create_data_to_compress(tmp_dir_to_compress.path());
107-
compress_tar_gz(tmp_dir_to_compress.path(), tmp_file_archive.as_path());
106+
TestDataHelper::compress_tar_gz(tmp_dir_to_compress.path(), tmp_file_archive.as_path());
108107

109108
let tmp_dir_extracted = tempdir().unwrap();
110109
let result = Tar.extract(&tmp_file_archive, tmp_dir_extracted.path());
111110
result.unwrap();
112111

113-
assert!(tmp_dir_extracted.path().join("./file1.txt").exists());
114-
assert!(tmp_dir_extracted.path().join("./file2.txt").exists());
112+
TestDataHelper::test_data_uncompressed(tmp_dir_to_compress.path());
115113
}
116114

117115
#[test]
@@ -139,50 +137,65 @@ mod tests {
139137
let tmp_dir_archive = tempdir().unwrap();
140138
let tmp_file_archive = tmp_dir_archive.path().join("my.zip");
141139

142-
create_data_to_compress(tmp_dir_to_compress.path());
143-
compress_zip(tmp_dir_to_compress.path(), tmp_file_archive.as_path());
140+
TestDataHelper::compress_zip(tmp_dir_to_compress.path(), tmp_file_archive.as_path());
144141

145142
let tmp_dir_extracted = tempdir().unwrap();
146143
let result = Zip.extract(&tmp_file_archive, tmp_dir_extracted.path());
147144
result.unwrap();
148145

149-
assert!(tmp_dir_extracted.path().join("./file1.txt").exists());
150-
assert!(tmp_dir_extracted.path().join("./file2.txt").exists());
146+
TestDataHelper::test_data_uncompressed(tmp_dir_to_compress.path());
151147
}
152148

153149
/// Helpers ///
154-
pub fn compress_zip(source_path: &Path, tmp_file_archive: &Path) {
155-
let file = File::create(tmp_file_archive).unwrap();
156-
let mut zip = zip::ZipWriter::new(file);
157-
for entry in std::fs::read_dir(source_path).unwrap() {
158-
let entry = entry.unwrap();
159-
let path = entry.path();
160-
let options =
161-
SimpleFileOptions::default().compression_method(zip::CompressionMethod::Deflated);
162-
zip.start_file(path.file_name().unwrap().to_string_lossy(), options)
163-
.unwrap();
164-
let mut f = File::open(&path).unwrap();
165-
std::io::copy(&mut f, &mut zip).unwrap();
150+
pub struct TestDataHelper;
151+
152+
impl TestDataHelper {
153+
const FILE1: &str = "file1.txt";
154+
const FILE2: &str = "file2.txt";
155+
const CONTENT: &str = "important content";
156+
157+
fn create_data_to_compress(tmp_dir_to_compress: &Path) {
158+
let file_path_1 = tmp_dir_to_compress.join(TestDataHelper::FILE1);
159+
File::create(file_path_1.clone()).unwrap();
160+
let file_path_2 = tmp_dir_to_compress.join(TestDataHelper::FILE2);
161+
File::create(file_path_2.clone()).unwrap();
162+
163+
std::fs::write(file_path_1.as_path(), TestDataHelper::CONTENT).unwrap();
164+
std::fs::write(file_path_2.as_path(), TestDataHelper::CONTENT).unwrap();
166165
}
167166

168-
zip.finish().unwrap();
169-
}
167+
pub fn compress_tar_gz(source_path: &Path, tmp_file_archive: &Path) {
168+
TestDataHelper::create_data_to_compress(source_path);
170169

171-
pub fn compress_tar_gz(source_path: &Path, tmp_file_archive: &Path) {
172-
let tar_gz = File::create(tmp_file_archive).unwrap();
173-
let enc = GzEncoder::new(tar_gz, Compression::default());
174-
let mut tar = tar::Builder::new(enc);
175-
tar.append_dir_all(".", source_path).unwrap();
176-
tar.finish().unwrap();
177-
}
170+
let tar_gz = File::create(tmp_file_archive).unwrap();
171+
let enc = GzEncoder::new(tar_gz, Compression::default());
172+
let mut tar = tar::Builder::new(enc);
173+
tar.append_dir_all(".", source_path).unwrap();
174+
tar.finish().unwrap();
175+
}
178176

179-
fn create_data_to_compress(tmp_dir_to_compress: &Path) {
180-
let file_path_1 = tmp_dir_to_compress.join("file1.txt");
181-
File::create(file_path_1.clone()).unwrap();
182-
let file_path_2 = tmp_dir_to_compress.join("file2.txt");
183-
File::create(file_path_2.clone()).unwrap();
177+
pub fn compress_zip(source_path: &Path, tmp_file_archive: &Path) {
178+
TestDataHelper::create_data_to_compress(source_path);
179+
180+
let file = File::create(tmp_file_archive).unwrap();
181+
let mut zip = zip::ZipWriter::new(file);
182+
for entry in std::fs::read_dir(source_path).unwrap() {
183+
let entry = entry.unwrap();
184+
let path = entry.path();
185+
let options = SimpleFileOptions::default()
186+
.compression_method(zip::CompressionMethod::Deflated);
187+
zip.start_file(path.file_name().unwrap().to_string_lossy(), options)
188+
.unwrap();
189+
let mut f = File::open(&path).unwrap();
190+
std::io::copy(&mut f, &mut zip).unwrap();
191+
}
192+
193+
zip.finish().unwrap();
194+
}
184195

185-
std::fs::write(file_path_1.as_path(), "important content").unwrap();
186-
std::fs::write(file_path_2.as_path(), "important content").unwrap();
196+
pub fn test_data_uncompressed(tmp_dir_extracted: &Path) {
197+
assert!(tmp_dir_extracted.join(TestDataHelper::FILE1).exists());
198+
assert!(tmp_dir_extracted.join(TestDataHelper::FILE2).exists());
199+
}
187200
}
188201
}

agent-control/src/package/manager.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
//! This module manages package operations such as installation, removal, and updates.
2-
3-
use std::path::PathBuf;
4-
2+
use crate::agent_control::agent_id::AgentID;
3+
use crate::agent_type::runtime_config::on_host::package::PackageType;
4+
use crate::package::oci::package_manager::OCIPackageManagerError;
55
use oci_client::Reference;
6-
7-
use crate::{
8-
agent_control::agent_id::AgentID, package::oci::package_manager::OCIPackageManagerError,
9-
};
6+
use std::path::PathBuf;
107

118
/// Information required to reference and install a package
129
#[derive(Debug)]
1310
pub struct PackageData {
1411
pub id: String, // same type as the packages map on an agent type definition
12+
pub package_type: PackageType,
1513
pub oci_reference: Reference,
1614
}
1715

0 commit comments

Comments
 (0)