Skip to content

Commit c6353a6

Browse files
authored
Merge pull request #17 from sarus-suite/fc-strict-input-validation
Ro Storage is now validated to be either an empty dir or to have the overlay directories of a podman initialized store. This would make more difficult, options mistakes that trigger large mirror operations.
2 parents 9153731 + f6ce8d2 commit c6353a6

File tree

3 files changed

+140
-28
lines changed

3 files changed

+140
-28
lines changed

common/config.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package common
33
import (
44
"os"
55
"fmt"
6+
"path/filepath"
67
)
78

89
type Config struct {
@@ -38,3 +39,30 @@ func IsExecutable(path string) error {
3839
return nil
3940
}
4041

42+
func ValidateRoStore(path string) error {
43+
fileInfo, err := os.Stat(path)
44+
if err != nil || !fileInfo.IsDir() {
45+
return fmt.Errorf("'%s' is not a valid directory", path)
46+
}
47+
48+
files, err := os.ReadDir(path)
49+
if err != nil {
50+
return fmt.Errorf("failed reading directory '%s': %w", path, err)
51+
}
52+
// Quick accept if directory is empty
53+
if len(files) == 0 {
54+
return nil
55+
}
56+
57+
// Validate that at least Podman-overlay Store subdirectories are present
58+
requiredSubdirs := []string{"overlay", "overlay-images", "overlay-layers"}
59+
for _, dir := range requiredSubdirs {
60+
fullPath := filepath.Join(path, dir)
61+
if err := IsDir(fullPath); err != nil {
62+
return fmt.Errorf("storage validation failed: %w", err)
63+
}
64+
}
65+
66+
return nil
67+
}
68+

main.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,17 @@ func main() {
3838

3939
switch cli.Op {
4040
case common.OpMigrate:
41-
// TODO: we are not using migration return anymore, maybe drop it
41+
if err := common.ValidateRoStore(cli.Config.RoStoragePath); err != nil {
42+
logrus.Fatalf("Storage validation failed before migration: %v", err)
43+
}
4244
_, err := cmd.RunMigration(cli.Config)
4345
if err != nil {
4446
logrus.Fatalf("Migration failed for image '%s': %v", cli.Config.Image, err)
4547
}
4648
case common.OpRmi:
49+
if err := common.ValidateRoStore(cli.Config.RoStoragePath); err != nil {
50+
logrus.Fatalf("Storage validation failed before rmi: %v", err)
51+
}
4752
err = cmd.RunRmi(cli.Config)
4853
if err != nil {
4954
logrus.Fatalf("RMI operation failed for image '%s': %v", cli.Config.Image, err)

tests/parallax-cli-checks.bats

Lines changed: 106 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,126 @@
11
load helpers.bash
22

33
@test "Either -migrate or -rmi is specified" {
4-
run \
5-
"$PARALLAX_BINARY"
6-
[ "$status" -ne 0 ]
7-
[[ "$output" =~ "Must specify either -migrate or -rmi" ]]
4+
run \
5+
"$PARALLAX_BINARY"
6+
[ "$status" -ne 0 ]
7+
[[ "$output" =~ "Must specify either -migrate or -rmi" ]]
88
}
99

1010
@test "Fails if both -migrate and -rmi are passed" {
11-
run \
12-
"$PARALLAX_BINARY" -migrate -rmi -image ubuntu:latest
13-
[ "$status" -ne 0 ]
14-
[[ "$output" =~ "Must specify either -migrate or -rmi" ]]
11+
run \
12+
"$PARALLAX_BINARY" -migrate -rmi -image ubuntu:latest
13+
[ "$status" -ne 0 ]
14+
[[ "$output" =~ "Must specify either -migrate or -rmi" ]]
1515
}
1616

1717
@test "Fails if --image is missing" {
18-
run \
19-
"$PARALLAX_BINARY" -migrate
20-
[ "$status" -ne 0 ]
21-
[[ "$output" =~ "Must specify -image" ]]
18+
run \
19+
"$PARALLAX_BINARY" -migrate
20+
[ "$status" -ne 0 ]
21+
[[ "$output" =~ "Must specify -image" ]]
2222
}
2323

2424
@test "Checks version" {
25-
run \
26-
"$PARALLAX_BINARY" -version
27-
[ "$status" -eq 0 ]
28-
[[ "$output" =~ "Parallax version" ]]
25+
run \
26+
"$PARALLAX_BINARY" -version
27+
[ "$status" -eq 0 ]
28+
[[ "$output" =~ "Parallax version" ]]
2929
}
3030

3131
@test "Usage is printed" {
32-
run \
33-
"$PARALLAX_BINARY" -help
34-
[ "$status" -eq 0 ]
35-
[[ "$output" =~ "OCI image migration tool" ]]
36-
[[ "$output" =~ "Usage" ]]
37-
[[ "$output" =~ "-migrate" ]]
38-
[[ "$output" =~ "-image" ]]
32+
run \
33+
"$PARALLAX_BINARY" -help
34+
[ "$status" -eq 0 ]
35+
[[ "$output" =~ "OCI image migration tool" ]]
36+
[[ "$output" =~ "Usage" ]]
37+
[[ "$output" =~ "-migrate" ]]
38+
[[ "$output" =~ "-image" ]]
3939
}
4040

4141
@test "Checks unknown flag message" {
42-
run \
43-
"$PARALLAX_BINARY" -unknownflag
44-
[ "$status" -ne 0 ]
45-
[[ "$output" =~ "flag provided but not defined" ]]
42+
run \
43+
"$PARALLAX_BINARY" -unknownflag
44+
[ "$status" -ne 0 ]
45+
[[ "$output" =~ "flag provided but not defined" ]]
46+
}
47+
48+
@test "Fails migration when --roStoragePath directory is non-empty" {
49+
# Populate the storage dir with a dummy file
50+
# This way the directory is neither empty or with a store structure
51+
touch "$RO_STORAGE/dummy-file"
52+
53+
run "$PARALLAX_BINARY" \
54+
--podmanRoot "$PODMAN_ROOT" \
55+
--roStoragePath "$RO_STORAGE" \
56+
--mksquashfsPath "$MKSQUASHFS_PATH" \
57+
--log-level info \
58+
--migrate \
59+
--image ubuntu:latest
60+
61+
# Expect a non-zero exit code and a validation error
62+
[ "$status" -ne 0 ]
63+
[[ "$output" =~ "Storage validation failed" ]]
64+
}
65+
66+
@test "Advanced --roStoragePath directory is initialized" {
67+
# Populate the storage dir with a dummy file
68+
# This way the directory is neither empty or with a store structure
69+
touch "$RO_STORAGE/dummy-file"
70+
71+
run "$PARALLAX_BINARY" \
72+
--podmanRoot "$PODMAN_ROOT" \
73+
--roStoragePath "$RO_STORAGE" \
74+
--mksquashfsPath "$MKSQUASHFS_PATH" \
75+
--log-level info \
76+
--migrate \
77+
--image alpine:latest
78+
79+
# Expect a non-zero exit code and a validation error
80+
[ "$status" -ne 0 ]
81+
[[ "$output" =~ "Storage validation failed" ]]
82+
83+
# Bootstrap RO_STORAGE with a pulled image, this satisfies the dir structure validation
84+
run "$PODMAN_BINARY" \
85+
--root "$RO_STORAGE" \
86+
--runroot "$PODMAN_RUNROOT" \
87+
pull alpine:latest
88+
[ "$status" -eq 0 ]
89+
90+
run "$PODMAN_BINARY" \
91+
--root "$PODMAN_ROOT" \
92+
--runroot "$PODMAN_RUNROOT" \
93+
pull ubuntu:latest
94+
[ "$status" -eq 0 ]
95+
96+
# Now migration should pass check, and also complete a ubuntu migration
97+
run "$PARALLAX_BINARY" \
98+
--podmanRoot "$PODMAN_ROOT" \
99+
--roStoragePath "$RO_STORAGE" \
100+
--mksquashfsPath "$MKSQUASHFS_PATH" \
101+
--log-level info \
102+
--migrate \
103+
--image ubuntu:latest
104+
105+
[ "$status" -eq 0 ]
106+
[[ "$output" =~ "Migration successfully completed" ]]
107+
}
108+
109+
@test "Fails RMI when --roStoragePath directory is non-empty" {
110+
# Populate the storage dir with a dummy file
111+
# This way the directory is neither empty or with a store structure
112+
touch "$RO_STORAGE/dummy-file"
113+
114+
run "$PARALLAX_BINARY" \
115+
--podmanRoot "$PODMAN_ROOT" \
116+
--roStoragePath "$RO_STORAGE" \
117+
--mksquashfsPath "$MKSQUASHFS_PATH" \
118+
--log-level info \
119+
--rmi \
120+
--image ubuntu:latest
121+
122+
# Expect a non-zero exit code and a validation error
123+
[ "$status" -ne 0 ]
124+
[[ "$output" =~ "Storage validation failed" ]]
46125
}
47126

0 commit comments

Comments
 (0)