I have a Cloud Foundry Bosh Lite install with Garden/Runc support running on my local dev machine with an app hosted on it. I can ssh into the Diego cell VM and execute
cell_z1/0# runc exec 5f9c8b67-9170-4c53-4bab-bbb2e6a3acdf /usr/bin/printenv
This will produce the following output:
INSTANCE_GUID=5f9c8b67-9170-4c53-4bab-bbb2e6a3acdf
INSTANCE_INDEX=0
CF_INSTANCE_GUID=5f9c8b67-9170-4c53-4bab-bbb2e6a3acdf
CF_INSTANCE_INDEX=0
LANG=en_US.UTF-8
CF_INSTANCE_CERT=/etc/cf-instance-credentials/instance.crt
CF_INSTANCE_KEY=/etc/cf-instance-credentials/instance.key
HOME=/root
I assumed I could achieve the same through the Garden API by invoking
cell_z1/0# curl -X POST -d '{"path":"/usr/bin/printenv"}' localhost:7777/containers/5f9c8b67-9170-4c53-4bab-bbb2e6a3acdf/processes
However, this will return
{"Type":"","Message":"EOF","Handle":""}
which unfortunately tells me nothing. I tried adding "user":"vcap"
in the JSON payload but the result is the same. When I add -H "Content-Type: application/json" -d
I get
curl: (56) Problem (2) in the Chunked-Encoded data
Question: how can I execute an arbitrary command inside a container via the Garden API and retrieve it's output?
Go Library
The supported way to execute commands within a Garden container is via the Go client library. For example:
gdnClient := client.New(connection.New("tcp", "127.0.0.1:7777"))
container, err := gdnClient.Create(garden.ContainerSpec{})
if err != nil {
os.Exit(1)
}
buffer := &bytes.Buffer{}
process, err := container.Run(garden.ProcessSpec{
Path: "/usr/bin/printenv",
}, garden.ProcessIO{
Stdout: buffer,
Stderr: buffer,
})
if err != nil {
os.Exit(1)
}
exitCode, err := process.Wait()
if err != nil {
os.Exit(1)
}
fmt.Printf("Exit code: %d, Process output %s", exitCode, buffer.String())
Gaol CLI
If you would prefer not to write any Go code you can use the unsupported (but very useful) Gaol CLI. For example:
gaol create -n myContainer
gaol run -c "/usr/bin/printenv" myContainer
Ensure that you set your GAOL_TARGET
appropriately e.g. 10.244.16.6:7777 on bosh-lite if you are running from your dev machine.
HTTP Clients
Finally, it is technically feasible to work with the entire Garden API through any HTTP client, but the supported client/server libraries do some connection hijacking which might confuse things. In particular, running a process is the most complicated API interaction.
Firstly, a request is made to the run endpoint and then the connection is hijacked. The garden client starts streaming stdio for the process by using the hijacked connection for stdin and hitting two other endpoints.
It shouldn't be too hard to get a process running in a container, requiring only a json encoded garden.ProcessSpec
in the request body but streaming the output is quite a bit trickier.