From 5085f2042815af966073c3999980386ca41da47f Mon Sep 17 00:00:00 2001 From: Robert Fink Date: Sun, 23 Apr 2017 09:03:46 -0700 Subject: [PATCH] Add support for creating directories (#33) --- README.md | 8 +++++++ integration_test/integration_test.go | 16 ++++++++++++++ .../launcher-static-with-dirs.yml | 12 ++++++++++ launcher/main/main.go | 22 ++++++++++++++++++- launchlib/config.go | 1 + launchlib/launcher.go | 15 +++++++++++++ launchlib/launcher_test.go | 20 +++++++++++++++++ 7 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 integration_test/test_resources/launcher-static-with-dirs.yml diff --git a/README.md b/README.md index e1b2bce9..af93e0c2 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,10 @@ jvmOpts: # OPTIONAL - Arguments passed to the main method of the main class args: - arg1 +# OPTIONAL - A list of directories to be created before executing the command. Must be relative to CWD and over [A-Za-z0-9]. +args: + - var/data/tmp + - var/log ``` ```yaml @@ -47,6 +51,10 @@ executable: "{{CWD}}/service/bin/postgres" # OPTIONAL - Arguments passed to the main method of the excutable or main class args: - arg1 +# OPTIONAL - A list of directories to be created before executing the command. Must be relative to CWD and over [A-Za-z0-9]. +args: + - var/data/tmp + - var/log ``` ```yaml diff --git a/integration_test/integration_test.go b/integration_test/integration_test.go index a88ecba7..dd631aa6 100644 --- a/integration_test/integration_test.go +++ b/integration_test/integration_test.go @@ -15,6 +15,7 @@ package integration_test import ( + "os" "os/exec" "testing" @@ -49,6 +50,21 @@ func TestMainMethodWithoutCustomConfig(t *testing.T) { assert.Regexp(t, `\nmain method\n`, string(output)) } +func TestCreatesDirs(t *testing.T) { + output, err := runMainWithArgs(t, "test_resources/launcher-static-with-dirs.yml", "foo") + require.NoError(t, err, "failed: %s", output) + + dir, err := os.Stat("foo") + assert.NoError(t, err) + assert.True(t, dir.IsDir()) + require.NoError(t, os.RemoveAll("foo")) + + dir, err = os.Stat("bar/baz") + assert.NoError(t, err) + assert.True(t, dir.IsDir()) + require.NoError(t, os.RemoveAll("bar")) +} + func runMainWithArgs(t *testing.T, staticConfigFile, customConfigFile string) (string, error) { cli, err := products.Bin("go-java-launcher") require.NoError(t, err) diff --git a/integration_test/test_resources/launcher-static-with-dirs.yml b/integration_test/test_resources/launcher-static-with-dirs.yml new file mode 100644 index 00000000..595ed53e --- /dev/null +++ b/integration_test/test_resources/launcher-static-with-dirs.yml @@ -0,0 +1,12 @@ +configType: java +configVersion: 1 +mainClass: Main +classpath: + - ./test_resources/ +jvmOpts: + - '-Xmx4M' +args: + - arg1 +dirs: + - foo + - bar/baz diff --git a/launcher/main/main.go b/launcher/main/main.go index e0e3703e..d2ad3cb5 100644 --- a/launcher/main/main.go +++ b/launcher/main/main.go @@ -41,12 +41,32 @@ func main() { customConfigFile = os.Args[2] } - cmd, err := launchlib.CompileCmdFromConfigFiles(staticConfigFile, customConfigFile) + // Read configuration + staticConfig, err := launchlib.GetStaticConfigFromFile(staticConfigFile) + if err != nil { + fmt.Println("Failed to read static config file", err) + panic(err) + } + customConfig, err := launchlib.GetCustomConfigFromFile(customConfigFile) + if err != nil { + fmt.Println("Failed to read custom config file", err) + panic(err) + } + + // Create configured directories + if err := launchlib.MkDirs(staticConfig.Dirs); err != nil { + fmt.Println("Failed to create directories", err) + panic(err) + } + + // Compile command + cmd, err := launchlib.CompileCmdFromConfig(&staticConfig, &customConfig) if err != nil { fmt.Println("Failed to assemble executable metadata", cmd, err) panic(err) } + // Execute command execErr := syscall.Exec(cmd.Path, cmd.Args, cmd.Env) if execErr != nil { if os.IsNotExist(execErr) { diff --git a/launchlib/config.go b/launchlib/config.go index 66cf13a4..58f473b9 100644 --- a/launchlib/config.go +++ b/launchlib/config.go @@ -41,6 +41,7 @@ type StaticLauncherConfig struct { Env map[string]string `yaml:"env"` Executable string `yaml:"executable,omitempty"` Args []string `yaml:"args"` + Dirs []string `yaml:"dirs"` } type CustomLauncherConfig struct { diff --git a/launchlib/launcher.go b/launchlib/launcher.go index 85bbfb71..5400994f 100644 --- a/launchlib/launcher.go +++ b/launchlib/launcher.go @@ -91,6 +91,21 @@ func CompileCmdFromConfig(staticConfig *StaticLauncherConfig, customConfig *Cust return createCmd(executable, args, env) } +func MkDirs(dirs []string) error { + isDirMatcher := regexp.MustCompile(`^[A-Za-z0-9]+(/[A-Za-z0-9]+)*$`).MatchString + for _, dir := range dirs { + if !isDirMatcher(dir) { + return fmt.Errorf("Cannot create directory with non [A-Za-z0-9] characters: %s", dir) + } + + fmt.Printf("Creating directory: %s\n", dir) + if err := os.MkdirAll(dir, 0700); err != nil { + return err + } + } + return nil +} + // Returns true iff the given path is safe to be passed to exec(): must not contain funky characters and be a valid file. func verifyPathIsSafeForExec(execPath string) (string, error) { if unsafe, err := regexp.MatchString(ExecPathBlackListRegex, execPath); err != nil { diff --git a/launchlib/launcher_test.go b/launchlib/launcher_test.go index b067bfac..5560a91b 100644 --- a/launchlib/launcher_test.go +++ b/launchlib/launcher_test.go @@ -112,3 +112,23 @@ func TestKeysAreNotExpanded(t *testing.T) { t.Errorf("Expected %%CWD%% to exist in map and not be expanded, but it didn't") } } + +func TestMkdirChecksDirectorySyntax(t *testing.T) { + err := MkDirs([]string{"abc/def1"}) + assert.NoError(t, err) + + err = MkDirs([]string{"abc"}) + assert.NoError(t, err) + + require.NoError(t, os.RemoveAll("abc")) + + badCases := []string{ + "^&*", + "abc//def", + "abc/../def", + } + for _, dir := range badCases { + err = MkDirs([]string{dir}) + assert.EqualError(t, err, "Cannot create directory with non [A-Za-z0-9] characters: "+dir) + } +}