diff --git a/cf_cli_java_plugin.go b/cf_cli_java_plugin.go index 3f094f6..2e64868 100644 --- a/cf_cli_java_plugin.go +++ b/cf_cli_java_plugin.go @@ -56,7 +56,7 @@ func (u uuidGeneratorImpl) Generate() string { const ( // JavaDetectionCommand is the prologue command to detect on the Garden container if it contains a Java app. Visible for tests - JavaDetectionCommand = "if ! pgrep -x \"java\" > /dev/null; then echo \"No 'java' process found running. Are you sure this is a Java app?\" >&2; exit 1; fi;" + JavaDetectionCommand = "if ! pgrep -x \"java\" > /dev/null; then echo \"No 'java' process found running. Are you sure this is a Java app?\" >&2; exit 1; fi" heapDumpCommand = "heap-dump" threadDumpCommand = "thread-dump" ) @@ -167,17 +167,31 @@ func (c *JavaPlugin) execute(commandExecutor cmd.CommandExecutor, uuidGenerator cfSSHArguments = append(cfSSHArguments, "--app-instance-index", strconv.Itoa(applicationInstance)) } - var remoteCommandTokens = []string{} + var remoteCommandTokens = []string{JavaDetectionCommand} switch command { case heapDumpCommand: heapdumpFileName := "/tmp/heapdump-" + uuidGenerator.Generate() + ".hprof" - remoteCommandTokens = append(remoteCommandTokens, JavaDetectionCommand+"$(find -executable -name jmap | head -1) -dump:format=b,file="+heapdumpFileName+" $(pidof java) > /dev/null", "cat "+heapdumpFileName) + remoteCommandTokens = append(remoteCommandTokens, + // Check file does not already exist + "if [ -f "+heapdumpFileName+" ]; then echo >&2 'Heap dump "+heapdumpFileName+" already exists'; exit 1; fi", + /* + * If there is not enough space on the filesystem to write the dump, jmap will create a file + * with size 0, output something about not enough space left on device and exit with status code 0. + * Because YOLO. + * + * Also: if the heap dump file already exists, jmap will output something about the file already + * existing and exit with status code 0. At least it is consistent. + */ + "OUTPUT=$( $(find -executable -name jmap | head -1) -dump:format=b,file="+heapdumpFileName+" $(pidof java) ) || STATUS_CODE=$?", + "if [ ! -s "+heapdumpFileName+" ]; then echo >&2 ${OUTPUT}; exit 1; fi", + "if [ ${STATUS_CODE:-0} -gt 0 ]; then echo >&2 ${OUTPUT}; exit ${STATUS_CODE}; fi", + "cat "+heapdumpFileName) if !keepAfterDownload { remoteCommandTokens = append(remoteCommandTokens, "rm -f "+heapdumpFileName) } case threadDumpCommand: - remoteCommandTokens = append(remoteCommandTokens, JavaDetectionCommand+"$(find -executable -name jstack | head -1) $(pidof java)") + remoteCommandTokens = append(remoteCommandTokens, "$(find -executable -name jstack | head -1) $(pidof java)") } cfSSHArguments = append(cfSSHArguments, "--command") @@ -215,7 +229,7 @@ func (c *JavaPlugin) GetMetadata() plugin.PluginMetadata { Name: "JavaPlugin", Version: plugin.VersionType{ Major: 1, - Minor: 0, + Minor: 1, Build: 0, }, MinCliVersion: plugin.VersionType{ diff --git a/cf_cli_java_plugin_test.go b/cf_cli_java_plugin_test.go index eb0946b..602634c 100644 --- a/cf_cli_java_plugin_test.go +++ b/cf_cli_java_plugin_test.go @@ -180,7 +180,7 @@ var _ = Describe("CfJavaPlugin", func() { Expect(cliOutput).To(Equal("")) Expect(commandExecutor.ExecuteCallCount()).To(Equal(1)) - Expect(commandExecutor.ExecuteArgsForCall(0)).To(Equal([]string{"ssh", "my_app", "--command", JavaDetectionCommand + "$(find -executable -name jmap | head -1) -dump:format=b,file=/tmp/heapdump-abcd-123456.hprof $(pidof java) > /dev/null; cat /tmp/heapdump-abcd-123456.hprof; rm -f /tmp/heapdump-abcd-123456.hprof"})) + Expect(commandExecutor.ExecuteArgsForCall(0)).To(Equal([]string{"ssh", "my_app", "--command", JavaDetectionCommand + "; if [ -f /tmp/heapdump-abcd-123456.hprof ]; then echo >&2 'Heap dump /tmp/heapdump-abcd-123456.hprof already exists'; exit 1; fi; OUTPUT=$( $(find -executable -name jmap | head -1) -dump:format=b,file=/tmp/heapdump-abcd-123456.hprof $(pidof java) ) || STATUS_CODE=$?; if [ ! -s /tmp/heapdump-abcd-123456.hprof ]; then echo >&2 ${OUTPUT}; exit 1; fi; if [ ${STATUS_CODE:-0} -gt 0 ]; then echo >&2 ${OUTPUT}; exit ${STATUS_CODE}; fi; cat /tmp/heapdump-abcd-123456.hprof; rm -f /tmp/heapdump-abcd-123456.hprof"})) }) }) @@ -200,7 +200,7 @@ var _ = Describe("CfJavaPlugin", func() { Expect(cliOutput).To(Equal("")) Expect(commandExecutor.ExecuteCallCount()).To(Equal(1)) - Expect(commandExecutor.ExecuteArgsForCall(0)).To(Equal([]string{"ssh", "my_app", "--app-instance-index", "4", "--command", JavaDetectionCommand + "$(find -executable -name jmap | head -1) -dump:format=b,file=/tmp/heapdump-abcd-123456.hprof $(pidof java) > /dev/null; cat /tmp/heapdump-abcd-123456.hprof; rm -f /tmp/heapdump-abcd-123456.hprof"})) + Expect(commandExecutor.ExecuteArgsForCall(0)).To(Equal([]string{"ssh", "my_app", "--app-instance-index", "4", "--command", JavaDetectionCommand + "; if [ -f /tmp/heapdump-abcd-123456.hprof ]; then echo >&2 'Heap dump /tmp/heapdump-abcd-123456.hprof already exists'; exit 1; fi; OUTPUT=$( $(find -executable -name jmap | head -1) -dump:format=b,file=/tmp/heapdump-abcd-123456.hprof $(pidof java) ) || STATUS_CODE=$?; if [ ! -s /tmp/heapdump-abcd-123456.hprof ]; then echo >&2 ${OUTPUT}; exit 1; fi; if [ ${STATUS_CODE:-0} -gt 0 ]; then echo >&2 ${OUTPUT}; exit ${STATUS_CODE}; fi; cat /tmp/heapdump-abcd-123456.hprof; rm -f /tmp/heapdump-abcd-123456.hprof"})) }) }) @@ -220,7 +220,7 @@ var _ = Describe("CfJavaPlugin", func() { Expect(cliOutput).To(Equal("")) Expect(commandExecutor.ExecuteCallCount()).To(Equal(1)) - Expect(commandExecutor.ExecuteArgsForCall(0)).To(Equal([]string{"ssh", "my_app", "--app-instance-index", "4", "--command", JavaDetectionCommand + "$(find -executable -name jmap | head -1) -dump:format=b,file=/tmp/heapdump-abcd-123456.hprof $(pidof java) > /dev/null; cat /tmp/heapdump-abcd-123456.hprof"})) + Expect(commandExecutor.ExecuteArgsForCall(0)).To(Equal([]string{"ssh", "my_app", "--app-instance-index", "4", "--command", JavaDetectionCommand + "; if [ -f /tmp/heapdump-abcd-123456.hprof ]; then echo >&2 'Heap dump /tmp/heapdump-abcd-123456.hprof already exists'; exit 1; fi; OUTPUT=$( $(find -executable -name jmap | head -1) -dump:format=b,file=/tmp/heapdump-abcd-123456.hprof $(pidof java) ) || STATUS_CODE=$?; if [ ! -s /tmp/heapdump-abcd-123456.hprof ]; then echo >&2 ${OUTPUT}; exit 1; fi; if [ ${STATUS_CODE:-0} -gt 0 ]; then echo >&2 ${OUTPUT}; exit ${STATUS_CODE}; fi; cat /tmp/heapdump-abcd-123456.hprof"})) }) }) @@ -235,9 +235,9 @@ var _ = Describe("CfJavaPlugin", func() { return output, err }) - Expect(output).To(Equal("cf ssh my_app --app-instance-index 4 --command '" + JavaDetectionCommand + "$(find -executable -name jmap | head -1) -dump:format=b,file=/tmp/heapdump-abcd-123456.hprof $(pidof java) > /dev/null; cat /tmp/heapdump-abcd-123456.hprof'")) + Expect(output).To(Equal("cf ssh my_app --app-instance-index 4 --command '" + JavaDetectionCommand + "; if [ -f /tmp/heapdump-abcd-123456.hprof ]; then echo >&2 'Heap dump /tmp/heapdump-abcd-123456.hprof already exists'; exit 1; fi; OUTPUT=$( $(find -executable -name jmap | head -1) -dump:format=b,file=/tmp/heapdump-abcd-123456.hprof $(pidof java) ) || STATUS_CODE=$?; if [ ! -s /tmp/heapdump-abcd-123456.hprof ]; then echo >&2 ${OUTPUT}; exit 1; fi; if [ ${STATUS_CODE:-0} -gt 0 ]; then echo >&2 ${OUTPUT}; exit ${STATUS_CODE}; fi; cat /tmp/heapdump-abcd-123456.hprof'")) Expect(err).To(BeNil()) - Expect(cliOutput).To(ContainSubstring("cf ssh my_app --app-instance-index 4 --command '" + JavaDetectionCommand + "$(find -executable -name jmap | head -1) -dump:format=b,file=/tmp/heapdump-abcd-123456.hprof $(pidof java) > /dev/null; cat /tmp/heapdump-abcd-123456.hprof'")) + Expect(cliOutput).To(ContainSubstring("cf ssh my_app --app-instance-index 4 --command '" + JavaDetectionCommand + "; if [ -f /tmp/heapdump-abcd-123456.hprof ]; then echo >&2 'Heap dump /tmp/heapdump-abcd-123456.hprof already exists'; exit 1; fi; OUTPUT=$( $(find -executable -name jmap | head -1) -dump:format=b,file=/tmp/heapdump-abcd-123456.hprof $(pidof java) ) || STATUS_CODE=$?; if [ ! -s /tmp/heapdump-abcd-123456.hprof ]; then echo >&2 ${OUTPUT}; exit 1; fi; if [ ${STATUS_CODE:-0} -gt 0 ]; then echo >&2 ${OUTPUT}; exit ${STATUS_CODE}; fi; cat /tmp/heapdump-abcd-123456.hprof'")) Expect(commandExecutor.ExecuteCallCount()).To(Equal(0)) }) @@ -303,7 +303,7 @@ var _ = Describe("CfJavaPlugin", func() { Expect(cliOutput).To(Equal("")) Expect(commandExecutor.ExecuteCallCount()).To(Equal(1)) - Expect(commandExecutor.ExecuteArgsForCall(0)).To(Equal([]string{"ssh", "my_app", "--command", JavaDetectionCommand + "$(find -executable -name jstack | head -1) $(pidof java)"})) + Expect(commandExecutor.ExecuteArgsForCall(0)).To(Equal([]string{"ssh", "my_app", "--command", JavaDetectionCommand + "; $(find -executable -name jstack | head -1) $(pidof java)"})) }) }) @@ -323,7 +323,7 @@ var _ = Describe("CfJavaPlugin", func() { Expect(cliOutput).To(Equal("")) Expect(commandExecutor.ExecuteCallCount()).To(Equal(1)) - Expect(commandExecutor.ExecuteArgsForCall(0)).To(Equal([]string{"ssh", "my_app", "--app-instance-index", "4", "--command", JavaDetectionCommand + "$(find -executable -name jstack | head -1) $(pidof java)"})) + Expect(commandExecutor.ExecuteArgsForCall(0)).To(Equal([]string{"ssh", "my_app", "--app-instance-index", "4", "--command", JavaDetectionCommand + "; $(find -executable -name jstack | head -1) $(pidof java)"})) }) }) @@ -358,9 +358,9 @@ var _ = Describe("CfJavaPlugin", func() { return output, err }) - Expect(output).To(Equal("cf ssh my_app --app-instance-index 4 --command '" + JavaDetectionCommand + "$(find -executable -name jstack | head -1) $(pidof java)'")) + Expect(output).To(Equal("cf ssh my_app --app-instance-index 4 --command '" + JavaDetectionCommand + "; $(find -executable -name jstack | head -1) $(pidof java)'")) Expect(err).To(BeNil()) - Expect(cliOutput).To(ContainSubstring("cf ssh my_app --app-instance-index 4 --command '" + JavaDetectionCommand + "$(find -executable -name jstack | head -1) $(pidof java)'")) + Expect(cliOutput).To(ContainSubstring("cf ssh my_app --app-instance-index 4 --command '" + JavaDetectionCommand + "; $(find -executable -name jstack | head -1) $(pidof java)'")) Expect(commandExecutor.ExecuteCallCount()).To(Equal(0)) })