Skip to content

Commit 87a293a

Browse files
committed
feat: File ops cli implemented
1 parent f98cfb9 commit 87a293a

File tree

3 files changed

+333
-32
lines changed

3 files changed

+333
-32
lines changed

README.MD

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,34 @@
1-
### Volume Toolkit
1+
## Volume Toolkit
22

3-
This is an utility to do various operation on docker volumes.
3+
This is an utility to do various file based operations on a persistent volume. The toolkit is designed to work with the persistent volume mounted at `/data`.
44

5-
#### Commands
5+
### Commands
66

7-
| Command | Flags | Description |
8-
| --------- | -------------------- | ---------------------------------------------- |
9-
| `export` | `path` `http-method` | Export a persistent volume to a file or URL. |
10-
| `import` | `path` `http-method` | Import a persistent volume from a file or URL. |
11-
| `size` | | Measure the size of a persistent volume. |
12-
| `destroy` | | Destroy all data in the persistent volume. |
7+
| Command | Flags | Description |
8+
| --------- | ---------------------------------------- | ---------------------------------------------- |
9+
| `export` | `--path <path>` `--http-method <method>` | Export a persistent volume to a file or URL. |
10+
| `import` | `--path <path>` `--http-method <method>` | Import a persistent volume from a file or URL. |
11+
| `size` | None | Measure the size of a persistent volume. |
12+
| `destroy` | None | Destroy all data in the persistent volume. |
13+
| `file-op` | `--path <path>` | Perform file operations. |
14+
15+
#### File Related Commands
16+
17+
The `file-op` command supports the following subcommands:
18+
19+
| Subcommand | Flags | Description |
20+
| ---------- | ------------------------------------------- | ------------------------------------------------- |
21+
| `ls` | `--path <path>` | List files in the specified directory. |
22+
| `cat` | `--path <path>` | Display the contents of the specified file. |
23+
| `cp` | `--path <src>` `<dest>` | Copy a file from source to destination. |
24+
| `mv` | `--path <src>` `<dest>` | Move a file from source to destination. |
25+
| `rm` | `--path <path>` | Remove the specified file or directory. |
26+
| `mkdir` | `--path <path>` | Create a directory at the specified path. |
27+
| `chmod` | `--path <path>` `<mode>` | Change the permissions of the specified file. |
28+
| `chown` | `--path <path>` `--uid <uid>` `--gid <gid>` | Change the ownership of the specified file. |
29+
| `download` | `--path <dest>` `<url>` | Download a file from a URL to the specified path. |
30+
31+
**Note :** `cat` command will stream the binary data of the file to stdout.
1332

1433
### Output format
1534

@@ -21,8 +40,24 @@ This is an utility to do various operation on docker volumes.
2140
}
2241
```
2342

24-
#### Notes
43+
### Notes
2544

2645
- `/data` > This is the mounting point for the persistent volume
2746
- `/app` > This is the mounting point for the toolkit. After export volume, the `backup.tar.gz` file will be created in this directory. And for import volume, the `backup.tar.gz` file should be placed in this directory.
2847
- All the sizes will be in bytes format.
48+
- File Metadata
49+
```json
50+
{
51+
"name": "100MB.bin",
52+
"size": 104857600,
53+
"mode": "777",
54+
"mod_time": "2020-05-20T11:14:26Z",
55+
"uid": 999,
56+
"gid": 999,
57+
"is_dir": false
58+
}
59+
```
60+
61+
### License
62+
63+
This project is licensed under Apache 2.0 License - see the LICENSE file for details.

cli.go

Lines changed: 188 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"fmt"
55
"os"
6+
"strconv"
67

78
"github.com/spf13/cobra"
89
)
@@ -17,15 +18,41 @@ var rootCmd = &cobra.Command{
1718
},
1819
}
1920

21+
var filePath string
22+
2023
func init() {
21-
importCmd.Flags().String("path", "/app/backup.tar.gz", "Path of tar to import")
22-
importCmd.Flags().String("http-method", "GET", "HTTP method to use")
24+
rootCmd.Flags().SortFlags = false
2325
rootCmd.AddCommand(importCmd)
24-
exportCmd.Flags().String("path", "/app/backup.tar.gz", "Path of tar to export") // Path or URL where the backup will be stored.
25-
exportCmd.Flags().String("http-method", "PUT", "HTTP method to use")
2626
rootCmd.AddCommand(exportCmd)
2727
rootCmd.AddCommand(sizeCmd)
2828
rootCmd.AddCommand(destroyCmd)
29+
rootCmd.AddCommand(fileOpCmd)
30+
31+
importCmd.Flags().String("path", "/app/backup.tar.gz", "Path of tar to import")
32+
importCmd.Flags().String("http-method", "GET", "HTTP method to use")
33+
34+
exportCmd.Flags().String("path", "/app/backup.tar.gz", "Path of tar to export") // Path or URL where the backup will be stored.
35+
exportCmd.Flags().String("http-method", "PUT", "HTTP method to use")
36+
37+
fileOpCmd.PersistentFlags().StringVar(&filePath, "path", "", "Path of the file")
38+
fileOpCmd.MarkPersistentFlagRequired("path")
39+
40+
fileOpCmd.Flags().SortFlags = false
41+
fileOpCmd.AddCommand(lsCmd)
42+
fileOpCmd.AddCommand(catCmd)
43+
fileOpCmd.AddCommand(cpCmd)
44+
fileOpCmd.AddCommand(mvCmd)
45+
fileOpCmd.AddCommand(rmCmd)
46+
fileOpCmd.AddCommand(mkdirCmd)
47+
fileOpCmd.AddCommand(chmodCmd)
48+
49+
chownCmd.Flags().String("uid", "", "User ID")
50+
chownCmd.Flags().String("gid", "", "Group ID")
51+
chownCmd.MarkFlagRequired("uid")
52+
chownCmd.MarkFlagRequired("gid")
53+
fileOpCmd.AddCommand(chownCmd)
54+
55+
fileOpCmd.AddCommand(downloadCmd)
2956
}
3057

3158
func main() {
@@ -110,3 +137,160 @@ var destroyCmd = &cobra.Command{
110137
PrintData("All data has been destroyed")
111138
},
112139
}
140+
141+
/*
142+
file-op command
143+
- ls <full_path>
144+
- cat <full_path>
145+
- cp <full_path> <full_path_dest>
146+
- mv <full_path> <full_path_dest>
147+
- rm <full_path> [Do recursive delete anyway]
148+
- mkdir <full_path> [Will create all the directories in the path]
149+
- chmod <mode> <full_path>
150+
- chown <uid> <gid> <full_path>
151+
- download <url> <full_path>
152+
*/
153+
154+
var fileOpCmd = &cobra.Command{
155+
Use: "file-op",
156+
Run: func(cmd *cobra.Command, args []string) {
157+
cmd.Help()
158+
},
159+
}
160+
161+
var lsCmd = &cobra.Command{
162+
Use: "ls",
163+
Run: func(cmd *cobra.Command, args []string) {
164+
path := filePath
165+
files, err := ListFiles(path)
166+
if err != nil {
167+
PrintError(err.Error())
168+
}
169+
PrintData(files)
170+
},
171+
}
172+
173+
var catCmd = &cobra.Command{
174+
Use: "cat",
175+
Run: func(cmd *cobra.Command, args []string) {
176+
path := filePath
177+
data, err := os.ReadFile(path)
178+
if err != nil {
179+
PrintError(err.Error())
180+
}
181+
// Stream the bytes to the stdout.
182+
os.Stdout.Write(data)
183+
},
184+
}
185+
186+
var cpCmd = &cobra.Command{
187+
Use: "cp",
188+
Run: func(cmd *cobra.Command, args []string) {
189+
if len(args) != 1 {
190+
PrintError("Invalid number of arguments")
191+
}
192+
src := filePath
193+
dest := args[0]
194+
// copy file without changing the ownership and permissions.
195+
err := CopyFile(src, dest)
196+
if err != nil {
197+
PrintError(err.Error())
198+
}
199+
PrintData("file has been copied")
200+
},
201+
}
202+
203+
var mvCmd = &cobra.Command{
204+
Use: "mv",
205+
Run: func(cmd *cobra.Command, args []string) {
206+
if len(args) != 1 {
207+
PrintError("Invalid number of arguments")
208+
}
209+
src := filePath
210+
dest := args[0]
211+
// move file without changing the ownership and permissions.
212+
err := MoveFile(src, dest)
213+
if err != nil {
214+
PrintError(err.Error())
215+
}
216+
PrintData("file has been moved")
217+
},
218+
}
219+
220+
var rmCmd = &cobra.Command{
221+
Use: "rm",
222+
Run: func(cmd *cobra.Command, args []string) {
223+
path := filePath
224+
err := os.RemoveAll(path)
225+
if err != nil {
226+
PrintError(err.Error())
227+
}
228+
PrintData("file has been removed")
229+
},
230+
}
231+
232+
var mkdirCmd = &cobra.Command{
233+
Use: "mkdir",
234+
Run: func(cmd *cobra.Command, args []string) {
235+
path := filePath
236+
err := os.MkdirAll(path, 0777)
237+
if err != nil {
238+
PrintError(err.Error())
239+
}
240+
PrintData("directory has been created")
241+
},
242+
}
243+
244+
var chmodCmd = &cobra.Command{
245+
Use: "chmod",
246+
Run: func(cmd *cobra.Command, args []string) {
247+
if len(args) != 1 {
248+
PrintError("Invalid number of arguments")
249+
}
250+
mode := args[0] // mode should be in octal format like 777, 755 etc.
251+
perm, err := strconv.ParseUint(mode, 8, 32)
252+
if err != nil {
253+
PrintError(err.Error())
254+
}
255+
path := filePath
256+
err = os.Chmod(path, os.FileMode(perm))
257+
if err != nil {
258+
PrintError(err.Error())
259+
}
260+
PrintData("file permissions have been changed")
261+
},
262+
}
263+
264+
var chownCmd = &cobra.Command{
265+
Use: "chown",
266+
Run: func(cmd *cobra.Command, args []string) {
267+
uid, err := strconv.Atoi(cmd.Flag("uid").Value.String())
268+
if err != nil {
269+
PrintError(err.Error())
270+
}
271+
gid, err := strconv.Atoi(cmd.Flag("gid").Value.String())
272+
if err != nil {
273+
PrintError(err.Error())
274+
}
275+
err = os.Chown(filePath, uid, gid)
276+
if err != nil {
277+
PrintError(err.Error())
278+
}
279+
PrintData("file ownership has been changed")
280+
},
281+
}
282+
283+
var downloadCmd = &cobra.Command{
284+
Use: "download",
285+
Run: func(cmd *cobra.Command, args []string) {
286+
if len(args) != 1 {
287+
PrintError("Invalid number of arguments")
288+
}
289+
url := args[0]
290+
err := DownloadFile(url, filePath)
291+
if err != nil {
292+
PrintError(err.Error())
293+
}
294+
PrintData("file has been downloaded")
295+
},
296+
}

0 commit comments

Comments
 (0)