Skip to content

Commit 8221036

Browse files
Initial import
1 parent c82f72d commit 8221036

File tree

11 files changed

+982
-3
lines changed

11 files changed

+982
-3
lines changed

.gitignore

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Compiled Object files, Static and Dynamic libs (Shared Objects)
2+
*.o
3+
*.a
4+
*.so
5+
6+
# Folders
7+
_obj
8+
_test
9+
10+
# Architecture specific extensions/prefixes
11+
*.[568vq]
12+
[568vq].out
13+
14+
*.cgo1.go
15+
*.cgo2.c
16+
_cgo_defun.c
17+
_cgo_gotypes.go
18+
_cgo_export.*
19+
20+
_testmain.go
21+
22+
*.exe
23+
*.test
24+
*.prof
25+
26+
# Tools
27+
counterfeiter
28+
29+
# Built binaries
30+
build/
31+
32+
# built project binary (go build)
33+
cf-java-plugin

LICENSE

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
Apache License
23
Version 2.0, January 2004
34
http://www.apache.org/licenses/
@@ -186,7 +187,7 @@
186187
same "printed page" as the copyright notice for easier
187188
identification within third-party archives.
188189

189-
Copyright {yyyy} {name of copyright owner}
190+
Copyright 2017 SAP SE
190191

191192
Licensed under the Apache License, Version 2.0 (the "License");
192193
you may not use this file except in compliance with the License.

Makefile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
JAVA_PLUGIN_INSTALLED = $(cf plugins | grep -q)
2+
3+
all: install
4+
5+
compile: cf_cli_java_plugin.go
6+
go build -o build/cf-cli-java-plugin cf_cli_java_plugin.go
7+
8+
compile-all: cf_cli_java_plugin.go
9+
ginkgo -p
10+
GOOS=linux GOARCH=386 go build -o build/cf-cli-java-plugin-linux32 cf_cli_java_plugin.go
11+
GOOS=linux GOARCH=amd64 go build -o build/cf-cli-java-plugin-linux64 cf_cli_java_plugin.go
12+
GOOS=darwin GOARCH=amd64 go build -o build/cf-cli-java-plugin-osx cf_cli_java_plugin.go
13+
GOOS=windows GOARCH=386 go build -o build/cf-cli-java-plugin-win32.exe cf_cli_java_plugin.go
14+
GOOS=windows GOARCH=amd64 go build -o build/cf-cli-java-plugin-win64.exe cf_cli_java_plugin.go
15+
16+
clean:
17+
rm -r build
18+
19+
install: compile remove
20+
yes | cf install-plugin build/cf-cli-java-plugin
21+
22+
remove: $(objects)
23+
ifeq ($(JAVA_PLUGIN_INSTALLED),)
24+
cf uninstall-plugin JavaPlugin || true
25+
endif
26+
27+
vclean: remove clean

README.md

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,87 @@
1-
# cf-cli-java-plugin
2-
Plugin for the Cloud Foundry CLI that adds tools to troubleshoot CF Java apps
1+
# Cloud Foundry Command Line Java plugin
2+
3+
This plugin for the [Cloud Foundry Command Line](https://github.com/cloudfoundry/cli) provides convenience utilities to work with Java applications deployed on Cloud Foundry.
4+
5+
Currently, it allows to:
6+
* Trigger and retrieve a heap-dump from an instance of a Cloud Foundry Java application
7+
* Trigger and retrieve a thread-dump from an instance of a Cloud Foundry Java application
8+
9+
## Installation
10+
11+
Download the binary file for your target OS from the [latest release](https://github.com/SAP/cf-cli-java-plugin/releases/latest).
12+
13+
If you've already installed the plugin and are updating it, you must first execute the `cf uninstall-plugin JavaPlugin` command.
14+
15+
Install the plugin with `cf install-plugin [cf-cli-java-plugin]` (replace `[cf-cli-java-plugin]` with the actual binary name you will use, which depends on the OS you are running).
16+
17+
You can verify that the plugin is successfully installed by looking for `JavaPlugin` in the output of `cf plugins`.
18+
19+
### Permission Issues
20+
21+
On Linux and macOS, if you get a permission error, run `chmod +x [cf-cli-java-plugin]` (replace `[cf-cli-java-plugin]` with the actual binary name you will use, which depends on the OS you are running) on the plugin binary.
22+
On Windows, the plugin will refuse to install unless the binary has the `.exe` file extension.
23+
24+
## Usage
25+
26+
<pre>
27+
NAME:
28+
java - Obtain a heap-dump or thread-dump from a running, Diego-enabled, SSH-enabled Java application
29+
30+
USAGE:
31+
cf java [heap-dump|thread-dump] APP_NAME
32+
33+
OPTIONS:
34+
-app-instance-index -i [index], select to which instance of the app to connect
35+
-dry-run -n, just output to command line what would be executed
36+
-keep -k, keep the heap dump in the container; by default the heap dump will be deleted from the container's filesystem after been downloaded
37+
</pre>
38+
39+
The heap-dump or thread-dump (depending on what you execute) will be outputted to `std-out`.
40+
You may want to redirect the command's output to file, e.g., by executing:
41+
`cf java heap-dump [my_app] -i [my_instance_index] > heap-dump.hprof`
42+
43+
The `-k` flag is invalid when invoking `cf java thread-dump`.
44+
(Unlike with heap-dumps, the JVM does not need to output the threaddump to file before streaming it out.)
45+
46+
## Limitations
47+
48+
As it is built directly on `cf ssh`, the `cf java` plugin can work only with Diego applications that have `cf ssh` enabled.
49+
To check if your app fulfills the requirements, you can find out by running the `cf ssh-enabled [app-name]` command.
50+
51+
Also, `cf ssh` is *very* picky with proxies.
52+
If `cf java` is having issues connecting to your app, chances are the problem is in the networking issues encountered by `cf ssh`.
53+
To verify, run your `cf java` command in "dry-run" mode by adding the `-n` flag and try to execute the command line that `cf java` gives you back.
54+
If it fails, the issue is not in `cf java`, but in whatever makes `cf ssh` fail.
55+
56+
From the perspective of integration in workflows and overall shell-friendliness, the `cf java` plugin suffers from some shortcomings in the current `cf-cli` plugin framework:
57+
* There is no distinction between `stdout` and `stderr` output from the underlying `cf ssh` command (see [this issue on the `cf-cli` project](https://github.com/cloudfoundry/cli/issues/1074))
58+
* The `cf java` will however exit with status code `1` when the underpinning `cf ssh` command fails
59+
* If split between `stdout` and `stderr` is needed, you can run the `cf java` plugin in dry-run mode (`--dry-run` flag) and execute its output instead
60+
* The plugin is not current capability of storing output directly to file (see [this issue on the `cf-cli` project](https://github.com/cloudfoundry/cli/issues/1069))
61+
* The upstream change needed to fix this issue has been scheduled at Pivotal; when they provide the new API we need, we'll update the `cf java` command to save output to file.
62+
63+
## Side-effects on the running instance
64+
65+
Executing a thread-dump via the `cf java` command does not have much of an overhead on the affected JVM.
66+
(Unless you have **a lot** of threads, that is.)
67+
68+
Heap-dumps, on the other hand, have to be treated with a little more care.
69+
First of all, triggering the heap-dump of a JVM makes the latter execute in most cases a full garbage collection, which will cause your JVM to become unresponsive for the duration.
70+
How much time is needed to execute the heap-dump, depends on the size of the heap (the bigger, the slower), the algorithm used and, above all, whether your container is swapping memory to disk or not (swap is *bad* for the JVM).
71+
Since Cloud Foundry allows for over-commit in its cells, it is possible that a container would begin swapping when executing a full garbage collection.
72+
(To be fair, it could be swapping even *before* the garbage collection begins, but let's not knit-pick here.)
73+
So, it is theoretically possible that execuing a heap dump on a JVM in poor status of health will make it go even worse.
74+
75+
Secondly, JVMs output heap dumps to the filesystem.
76+
What the `cf java heap-dump` command does it, quite literally, trigger the heap dump to file system, read the content of the file over the SSH connection, and then remove the heap dump file from the container's file system (unless you have the `-k` flag set).
77+
The amount of filesystem space available to a container is set for the entire Cloud Foundry landscape with a global configuration.
78+
The size of a heap dump is linear with the size of the heap.
79+
So, it could be that, in case of large heaps or the filesystem having too much stuff in it, there is not enough space on the filesystem for creating the heap dump.
80+
In that case, the command will likely fail in a rather unpredictable fashion.
81+
82+
## Tests and Mocking
83+
84+
The tests are written using [Ginkgo](https://onsi.github.io/ginkgo/) and [Gomega](https://onsi.github.io/gomega/) for the BDD structure, and [Counterfeit](https://github.com/maxbrunsfeld/counterfeiter) for the mocking generation.
85+
Unless modifications are needed to the helper interfaces `cmd.CommandExecutor` and `uuid.UUIDGenerator` are needed, there should be no need to regenerate the mocks.
86+
87+
To run the tests, go to the root of the repository and simply run `gingko` (you may need to install the package, e.g., `sudo apt install golang-ginkgo-dev` on Ubuntu).

0 commit comments

Comments
 (0)