Skip to content

Commit 55d2efe

Browse files
Directory resource
1 parent 54f5060 commit 55d2efe

File tree

5 files changed

+217
-0
lines changed

5 files changed

+217
-0
lines changed

dsc/examples/filesys_delete.dsc.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Example configuration mixing native app resources with classic PS resources
2+
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
3+
resources:
4+
- name: Create empty file
5+
type: Microsoft.DSC/File
6+
properties:
7+
path: "[path('d:\\', 'temp', 'a.txt')]"
8+
_exist: false
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Example configuration mixing native app resources with classic PS resources
2+
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
3+
resources:
4+
- name: Create empty directory
5+
type: Microsoft.DSC/Directory
6+
properties:
7+
path: "[path('d:\\', 'temp', 'testdir')]"
8+
_exist: true

dsc/examples/filesys_dir_delete.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Example configuration mixing native app resources with classic PS resources
2+
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
3+
resources:
4+
- name: Delete empty directory
5+
type: Microsoft.DSC/Directory
6+
properties:
7+
path: "[path('d:\\', 'temp', 'testdir')]"
8+
_exist: false
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Example configuration mixing native app resources with classic PS resources
2+
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2024/04/config/document.json
3+
resources:
4+
- name: Delete non-empty directory
5+
type: Microsoft.DSC/Directory
6+
properties:
7+
path: "[path('d:\\', 'temp', 'testdir')]"
8+
recurse: true
9+
_exist: false

resources/filesys/src/dir_helpers.rs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use crate::config::File;
5+
use crate::config::Directory;
6+
use crate::file_helper::get_file;
7+
use std::fs;
8+
use std::path::Path;
9+
use tracing::{debug};
10+
use fs_extra::dir::get_size;
11+
12+
impl Directory {
13+
/// Create a new `Directory`.
14+
///
15+
/// # Arguments
16+
///
17+
/// * `string` - The string for the Path
18+
#[must_use]
19+
pub fn new(path: &str) -> Directory {
20+
Directory {
21+
path: path.to_string(),
22+
size: None,
23+
files: None,
24+
recurse: Some(false),
25+
exist: None,
26+
}
27+
}
28+
}
29+
30+
pub fn get_dir(dir: &Directory) -> Result<Directory, Box<dyn std::error::Error>> {
31+
debug!("In get_dir");
32+
match compare_dir_state(dir) {
33+
Ok(d) => {
34+
Ok(d)
35+
},
36+
Err(e) => {
37+
Err(e)?
38+
}
39+
}
40+
}
41+
42+
pub fn set_dir(dir: &Directory) -> Result<Directory, Box<dyn std::error::Error>> {
43+
match compare_dir_state(dir) {
44+
Ok(current_dir) => {
45+
debug!("In set_dir");
46+
debug!("dir exist {:?}", dir.exist);
47+
debug!("expected dir exist {:?}", dir.exist.unwrap_or(true));
48+
49+
match (current_dir.exist.unwrap_or(true), dir.exist.unwrap_or(true)) {
50+
// if the current dir exists and expected state is exist == true, do nothing
51+
(true, true) | (false, false) => {
52+
return Ok(current_dir);
53+
}
54+
55+
// if the current dir exists and expected state is exist == true, create it
56+
(true, false) => {
57+
debug!("Deleting directory: {:?}", dir.path);
58+
59+
if dir.recurse.unwrap_or(false) {
60+
fs::remove_dir_all(dir.path.as_str())?;
61+
} else {
62+
fs::remove_dir(dir.path.as_str())?;
63+
}
64+
65+
return Ok(get_dir(&dir)?)
66+
}
67+
68+
// if the current dir does not exist and expected state is exist == true, create it
69+
(false, true) => {
70+
debug!("Creating directory: {:?}", dir.path);
71+
fs::create_dir_all(dir.path.as_str())?;
72+
return Ok(get_dir(&dir)?)
73+
}
74+
}
75+
},
76+
Err(e) => {
77+
Err(e)?
78+
}
79+
}
80+
}
81+
82+
pub fn export_dir_path(dir: &Directory) -> Result<Directory, Box<dyn std::error::Error>> {
83+
// Export the file or directory
84+
let path = Path::new(dir.path.as_str());
85+
86+
match path.exists() {
87+
false => {
88+
return Ok(Directory { path: path.to_str().unwrap().to_string(), size: None, files: None, recurse: dir.recurse, exist: Some(false) });
89+
}
90+
_ => {}
91+
}
92+
93+
match path.is_dir() {
94+
true => {
95+
let files: Vec<File> = {
96+
let dir = fs::read_dir(path)?;
97+
let mut files = Vec::new();
98+
for entry in dir {
99+
let entry = entry?;
100+
let path = entry.path();
101+
let f = File::new(path.to_str().unwrap());
102+
files.push(get_file(&f)?);
103+
}
104+
files
105+
};
106+
107+
let dir_size = get_size(path)?;
108+
109+
Ok(Directory { path: path.to_str().unwrap().to_string(), size: Some(dir_size), files: Some(files), recurse: dir.recurse, exist: Some(true) })
110+
}
111+
false => {
112+
let path = Path::new(path);
113+
let f = File::new(path.to_str().unwrap());
114+
let file = get_file(&f)?;
115+
let parent = path.parent();
116+
match parent {
117+
Some(parent) => {
118+
Ok(Directory { path: parent.to_str().unwrap().to_string(), size: file.size, files: vec![file].into(), recurse: dir.recurse, exist: Some(true) })
119+
}
120+
_ => {
121+
return Err("Path is not a file or directory")?;
122+
}
123+
}
124+
}
125+
}
126+
}
127+
128+
pub fn delete_dir(dir: &Directory) -> Result<(), Box<dyn std::error::Error>> {
129+
match compare_dir_state(dir) {
130+
Ok(d) => {
131+
132+
if d.exist == Some(false) {
133+
return Ok(());
134+
}
135+
136+
if d.recurse == Some(true) {
137+
debug!("Deleting directory: {:?}", d.path);
138+
fs::remove_dir_all(d.path)?;
139+
return Ok(());
140+
}
141+
else {
142+
debug!("Deleting directory: {:?}", d.path);
143+
fs::remove_dir(d.path)?;
144+
return Ok(());
145+
}
146+
},
147+
Err(e) => {
148+
Err(e)?
149+
}
150+
}
151+
}
152+
153+
pub fn compare_dir_state(dir: &Directory) -> Result<Directory, Box<dyn std::error::Error>> {
154+
let path = Path::new(dir.path.as_str());
155+
156+
match path.exists() {
157+
false => {
158+
return Ok(Directory { path: path.to_str().unwrap().to_string(), size: None, files: None, recurse: dir.recurse, exist: Some(false) });
159+
}
160+
true => {
161+
match path.is_dir() {
162+
false => {
163+
return Err("Path is not a directory")?;
164+
}
165+
_ => {}
166+
}
167+
}
168+
}
169+
170+
let dir_size = get_size(path)?;
171+
172+
match dir.size {
173+
Some(size) => {
174+
if size != dir_size {
175+
Ok(Directory { path: path.to_str().unwrap().to_string(), size: Some(dir_size), files: None, recurse: dir.recurse, exist: Some(true) })
176+
} else {
177+
Ok(Directory { path: path.to_str().unwrap().to_string(), size: Some(dir_size), files: None, recurse: dir.recurse, exist: Some(true) })
178+
}
179+
}
180+
None => {
181+
Ok(Directory { path: path.to_str().unwrap().to_string(), size: Some(dir_size), files: None, recurse: dir.recurse, exist: Some(true) })
182+
}
183+
}
184+
}

0 commit comments

Comments
 (0)