feat: add docker logs data source (#471)

* working docker-logs

Signed-off-by: bukowa <gitbukowa@gmail.com>

* add tests

Signed-off-by: bukowa <gitbukowa@gmail.com>

* add description to logs_list_string

Signed-off-by: bukowa <gitbukowa@gmail.com>

* allow discarding docker-logs headers

Signed-off-by: bukowa <gitbukowa@gmail.com>

* add auto generated docs

Signed-off-by: Buk Bukowski <gitbukowa@gmail.com>

Signed-off-by: bukowa <gitbukowa@gmail.com>
Signed-off-by: Buk Bukowski <gitbukowa@gmail.com>
This commit is contained in:
Buk Bukowski 2022-10-17 13:50:45 +02:00 committed by GitHub
parent 4cd1f8206a
commit 3534622b92
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 215 additions and 0 deletions

40
docs/data-sources/logs.md Normal file
View file

@ -0,0 +1,40 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "docker_logs Data Source - terraform-provider-docker"
subcategory: ""
description: |-
docker_logs provides logs from specific container
---
# docker_logs (Data Source)
`docker_logs` provides logs from specific container
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `name` (String) The name of the Docker Container
### Optional
- `details` (Boolean)
- `discard_headers` (Boolean) Discard headers that docker appends to each log entry
- `follow` (Boolean)
- `logs_list_string_enabled` (Boolean) If true populate computed value `logs_list_string`
- `show_stderr` (Boolean)
- `show_stdout` (Boolean)
- `since` (String)
- `tail` (String)
- `timestamps` (Boolean)
- `until` (String)
### Read-Only
- `id` (String) The ID of this resource.
- `logs_list_string` (List of String) List of container logs, each element is a line.

View file

@ -0,0 +1,130 @@
package provider
import (
"bufio"
"context"
"github.com/docker/docker/api/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func dataSourceDockerLogs() *schema.Resource {
return &schema.Resource{
Description: "`docker_logs` provides logs from specific container",
ReadContext: dataSourceDockerLogsRead,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Description: "The name of the Docker Container",
Required: true,
},
"logs_list_string": {
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Computed: true,
Description: "List of container logs, each element is a line.",
},
"logs_list_string_enabled": {
Type: schema.TypeBool,
Default: true,
Optional: true,
Description: "If true populate computed value `logs_list_string`",
},
"discard_headers": {
Type: schema.TypeBool,
Default: true,
Optional: true,
Description: "Discard headers that docker appends to each log entry",
},
"show_stdout": {
Type: schema.TypeBool,
Default: true,
Optional: true,
},
"show_stderr": {
Type: schema.TypeBool,
Default: true,
Optional: true,
},
"since": {
Type: schema.TypeString,
Default: "",
Optional: true,
},
"until": {
Type: schema.TypeString,
Default: "",
Optional: true,
},
"timestamps": {
Type: schema.TypeBool,
Default: false,
Optional: true,
},
"follow": {
Type: schema.TypeBool,
Default: false,
Optional: true,
},
"tail": {
Type: schema.TypeString,
Default: "",
Optional: true,
},
"details": {
Type: schema.TypeBool,
Default: false,
Optional: true,
},
},
}
}
func dataSourceDockerLogsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*ProviderConfig).DockerClient
container := d.Get("name").(string)
d.SetId(container)
// call client for logs
readCloser, err := client.ContainerLogs(ctx, container, types.ContainerLogsOptions{
ShowStdout: d.Get("show_stdout").(bool),
ShowStderr: d.Get("show_stderr").(bool),
Since: d.Get("since").(string),
Until: d.Get("until").(string),
Timestamps: d.Get("timestamps").(bool),
Follow: d.Get("follow").(bool),
Tail: d.Get("tail").(string),
Details: d.Get("details").(bool),
})
if err != nil {
return diag.Errorf("dataSourceDockerLogsRead: error while asking for logs %s", err)
}
defer readCloser.Close()
// see https://github.com/moby/moby/issues/7375#issuecomment-51462963
discard := d.Get("discard_headers").(bool)
// read string lines
if d.Get("logs_list_string_enabled").(bool) {
lines := make([]string, 0)
scanner := bufio.NewScanner(readCloser)
// scan each line
for scanner.Scan() {
line := scanner.Text()
if discard {
line = line[8:]
}
lines = append(lines, line)
}
// set string lines
if err := d.Set("logs_list_string", lines); err != nil {
return diag.FromErr(err)
}
}
return nil
}

View file

@ -0,0 +1,27 @@
package provider
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"testing"
)
func TestAccDockerLogsDataSource_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: loadTestConfiguration(t, DATA_SOURCE, "docker_logs", "testAccDockerLogsDataSourceBasic"),
ExpectNonEmptyPlan: true,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.docker_logs.logs_discard_headers_false", "logs_list_string.0", "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\fHello World"),
resource.TestCheckResourceAttr("data.docker_logs.logs_discard_headers_false", "logs_list_string.1", "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\fHello World"),
resource.TestCheckResourceAttr("data.docker_logs.logs_discard_headers_false", "logs_list_string.2", "\u0001\u0000\u0000\u0000\u0000\u0000\u0000\fHello World"),
resource.TestCheckResourceAttr("data.docker_logs.logs_basic", "logs_list_string.0", "Hello World"),
resource.TestCheckResourceAttr("data.docker_logs.logs_basic", "logs_list_string.1", "Hello World"),
resource.TestCheckResourceAttr("data.docker_logs.logs_basic", "logs_list_string.2", "Hello World"),
),
},
},
})
}

View file

@ -154,6 +154,7 @@ func New(version string) func() *schema.Provider {
"docker_network": dataSourceDockerNetwork(),
"docker_plugin": dataSourceDockerPlugin(),
"docker_image": dataSourceDockerImage(),
"docker_logs": dataSourceDockerLogs(),
},
}

View file

@ -0,0 +1,17 @@
resource "docker_container" "busybox" {
name = "busybox"
image = "busybox"
command = ["sh", "-c", "echo Hello World && echo Hello World && echo Hello World"]
must_run = false
}
data "docker_logs" "logs_basic" {
name = docker_container.busybox.id
}
data "docker_logs" "logs_discard_headers_false" {
name = docker_container.busybox.id
discard_headers = false
}