Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more content on how to use Exec function #1970

Merged
merged 3 commits into from
Dec 15, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
73 changes: 70 additions & 3 deletions docs/features/override_container_command.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Sending a CMD to a Container
# Executing commands

If you would like to send a CMD (command) to a container, you can pass it in to
the container request via the `Cmd` field...
## Container startup command

By default the container will execute whatever command is specified in the image's Dockerfile. If you would like to send a CMD (command) to a container, you can pass it in to
the container request via the `Cmd` field. For example:

```go
req := ContainerRequest{
Expand All @@ -13,3 +15,68 @@ req := ContainerRequest{
}
```

## Executing a command

You can execute a command inside a running container, similar to a `docker exec` call:

```go
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of pasting here code snippets, we usually embed code blocks with the <!--codeinclude--> block.

Please take a look at how it's implemented, as it's unfortunately not documented (yet).

It basically needs:

  1. in the markdown:
<!--codeinclude-->
[Tab text](../path/to/file.extension) inside_block:name_of_the_block
<!--/codeinclude-->
  1. in the file.extension
// name_of_the_block {
... code snippet to be rendered in the markdown
// }

I'm going to use this comment as seed for an issue to include that in our docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @mdelapenya. That makes sense. The thing is that the examples included in this PR are made up, don't correspond with any test available. I've seen that the those codeinclude chunks reference code in test suite. Want me to include the examples to the test suite? Or where should I put those examples?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gonna be proactive and I'll add that example to the test suite. I'll let you know when that's ready.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @danvergara, much appreciated! 🙏

func TestIntegrationNginxLatestReturn(t *testing.T) {
ctx := context.Background()
req := ContainerRequest{
Image: "docker.io/busybox",
Cmd: []string{"sleep", "10"},
Tmpfs: map[string]string{"/testtmpfs": "rw"},
}

container, err := GenericContainer(ctx, GenericContainerRequest{
ContainerRequest: req,
Started: true,
})

require.NoError(t, err)

t.Cleanup(func() {
t.Log("terminating container")
require.NoError(t, container.Terminate(ctx))
})

path := "/testtmpfs/test.file"

c, _, err := container.Exec(ctx, []string{"ls", path})
if err != nil {
t.Fatal(err)
}
}
```

This can be useful for software that has a command line administration tool. You can also get the logs of the command execution (from an object that implements the [io.Reader](https://pkg.go.dev/io#Reader) interface). For example:

```go
import (
"fmt"
"io"
"log"
"strings"
"testing"
)

func TestIntegrationNginxLatestReturn(t *testing.T) {
// ...

c, reader, err := container.Exec(ctx, []string{"ls", path})
if err != nil {
t.Fatal(err)
}

buf := new(strings.Builder)
_, err := io.Copy(buf, reader)
if err != nil {
t.Fatal(err)
}

// See the logs of the command execution.
t.Log(buf.String())
}
```

This is done this way, because it brings more flexibility to the user, rather than returning a string.