Repository: comtrya/comtrya (language: rust)

Issue:
'chmod' option in file.copy
Motiviation: I have a set of little shell scripts that I want to bring down and install. Successful completion of the installation involves setting the execute bit with chmod. In some cases you might also want to install a file, like one that holds a secret, as something other than world-readable.

Suggested concrete syntax:

```
actions:
  - name: setup-tailscale-ubuntu-focal
   action: file.copy
   from: bin/setup-tailscale-ubuntu-focal
   to: /root/.bin/setup-tailscale-ubuntu-focal
   chmod: "700"
   template: false
```

Alternatives considered: This is a workaround for #35 where I might be able to install everything with the 'Aptitude' driver. The more general case of `chmod` is a little bit of flexibility to make things just so. Even without the execute bit I can do this bootstrapping phase with `sh -x` so not all is lost. 

[Noted: updated reference syntax to reflect quoting necessary, because that integer is really an octal value]


Discussion / hints:

Fix patch:
diff --git a/src/actions/file/copy.rs b/src/actions/file/copy.rs
index 37ee2f2b..f79a5fa7 100644
--- a/src/actions/file/copy.rs
+++ b/src/actions/file/copy.rs
@@ -2,8 +2,8 @@ use super::FileAction;
 use crate::actions::{Action, ActionError, ActionResult};
 use crate::manifest::Manifest;
 use serde::{Deserialize, Serialize};
-use std::io::Write;
 use std::{fs::create_dir_all, ops::Deref, path::PathBuf};
+use std::{fs::Permissions, io::Write, os::unix::prelude::PermissionsExt};
 use tera::Context;
 use tracing::debug;
 
@@ -12,12 +12,19 @@ pub struct FileCopy {
     pub from: String,
     pub to: String,
 
-    #[serde(default = "get_true")]
+    #[serde(default = "default_chmod")]
+    pub chmod: u32,
+
+    #[serde(default = "default_template")]
     pub template: bool,
 }
 
-fn get_true() -> bool {
-    true
+fn default_chmod() -> u32 {
+    644
+}
+
+fn default_template() -> bool {
+    false
 }
 
 impl FileCopy {}
@@ -86,6 +93,15 @@ impl Action for FileCopy {
             }
         }
 
+        match std::fs::set_permissions(self.to.clone(), Permissions::from_mode(self.chmod)) {
+            Ok(_) => {}
+            Err(e) => {
+                return Err(ActionError {
+                    message: format!("Failed to set permissions: {}", e.to_string()),
+                })
+            }
+        }
+
         Ok(ActionResult {
             message: String::from("Copied"),
         })


Test patch: