|
@@ -0,0 +1,535 @@
|
|
|
+package formatter
|
|
|
+
|
|
|
+import (
|
|
|
+ "bytes"
|
|
|
+ "fmt"
|
|
|
+ "testing"
|
|
|
+ "time"
|
|
|
+
|
|
|
+ "github.com/docker/docker/api/types"
|
|
|
+)
|
|
|
+
|
|
|
+func TestContainerContextWrite(t *testing.T) {
|
|
|
+ unixTime := time.Now().AddDate(0, 0, -1).Unix()
|
|
|
+ expectedTime := time.Unix(unixTime, 0).String()
|
|
|
+
|
|
|
+ contexts := []struct {
|
|
|
+ context ContainerContext
|
|
|
+ expected string
|
|
|
+ }{
|
|
|
+ // Errors
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "{{InvalidFunction}}",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ `Template parsing error: template: :1: function "InvalidFunction" not defined
|
|
|
+`,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "{{nil}}",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ `Template parsing error: template: :1:2: executing "" at <nil>: nil is not a command
|
|
|
+`,
|
|
|
+ },
|
|
|
+ // Table Format
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ `CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
|
|
+containerID1 ubuntu "" 24 hours ago foobar_baz
|
|
|
+containerID2 ubuntu "" 24 hours ago foobar_bar
|
|
|
+`,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table {{.Image}}",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "IMAGE\nubuntu\nubuntu\n",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table {{.Image}}",
|
|
|
+ },
|
|
|
+ Size: true,
|
|
|
+ },
|
|
|
+ "IMAGE SIZE\nubuntu 0 B\nubuntu 0 B\n",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table {{.Image}}",
|
|
|
+ Quiet: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "IMAGE\nubuntu\nubuntu\n",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table",
|
|
|
+ Quiet: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "containerID1\ncontainerID2\n",
|
|
|
+ },
|
|
|
+ // Raw Format
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "raw",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ fmt.Sprintf(`container_id: containerID1
|
|
|
+image: ubuntu
|
|
|
+command: ""
|
|
|
+created_at: %s
|
|
|
+status:
|
|
|
+names: foobar_baz
|
|
|
+labels:
|
|
|
+ports:
|
|
|
+
|
|
|
+container_id: containerID2
|
|
|
+image: ubuntu
|
|
|
+command: ""
|
|
|
+created_at: %s
|
|
|
+status:
|
|
|
+names: foobar_bar
|
|
|
+labels:
|
|
|
+ports:
|
|
|
+
|
|
|
+`, expectedTime, expectedTime),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "raw",
|
|
|
+ },
|
|
|
+ Size: true,
|
|
|
+ },
|
|
|
+ fmt.Sprintf(`container_id: containerID1
|
|
|
+image: ubuntu
|
|
|
+command: ""
|
|
|
+created_at: %s
|
|
|
+status:
|
|
|
+names: foobar_baz
|
|
|
+labels:
|
|
|
+ports:
|
|
|
+size: 0 B
|
|
|
+
|
|
|
+container_id: containerID2
|
|
|
+image: ubuntu
|
|
|
+command: ""
|
|
|
+created_at: %s
|
|
|
+status:
|
|
|
+names: foobar_bar
|
|
|
+labels:
|
|
|
+ports:
|
|
|
+size: 0 B
|
|
|
+
|
|
|
+`, expectedTime, expectedTime),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "raw",
|
|
|
+ Quiet: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "container_id: containerID1\ncontainer_id: containerID2\n",
|
|
|
+ },
|
|
|
+ // Custom Format
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "{{.Image}}",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "ubuntu\nubuntu\n",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "{{.Image}}",
|
|
|
+ },
|
|
|
+ Size: true,
|
|
|
+ },
|
|
|
+ "ubuntu\nubuntu\n",
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, context := range contexts {
|
|
|
+ containers := []types.Container{
|
|
|
+ {ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu", Created: unixTime},
|
|
|
+ {ID: "containerID2", Names: []string{"/foobar_bar"}, Image: "ubuntu", Created: unixTime},
|
|
|
+ }
|
|
|
+ out := bytes.NewBufferString("")
|
|
|
+ context.context.Output = out
|
|
|
+ context.context.Containers = containers
|
|
|
+ context.context.Write()
|
|
|
+ actual := out.String()
|
|
|
+ if actual != context.expected {
|
|
|
+ t.Fatalf("Expected \n%s, got \n%s", context.expected, actual)
|
|
|
+ }
|
|
|
+ // Clean buffer
|
|
|
+ out.Reset()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestContainerContextWriteWithNoContainers(t *testing.T) {
|
|
|
+ out := bytes.NewBufferString("")
|
|
|
+ containers := []types.Container{}
|
|
|
+
|
|
|
+ contexts := []struct {
|
|
|
+ context ContainerContext
|
|
|
+ expected string
|
|
|
+ }{
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "{{.Image}}",
|
|
|
+ Output: out,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table {{.Image}}",
|
|
|
+ Output: out,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "IMAGE\n",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "{{.Image}}",
|
|
|
+ Output: out,
|
|
|
+ },
|
|
|
+ Size: true,
|
|
|
+ },
|
|
|
+ "",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ContainerContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table {{.Image}}",
|
|
|
+ Output: out,
|
|
|
+ },
|
|
|
+ Size: true,
|
|
|
+ },
|
|
|
+ "IMAGE SIZE\n",
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, context := range contexts {
|
|
|
+ context.context.Containers = containers
|
|
|
+ context.context.Write()
|
|
|
+ actual := out.String()
|
|
|
+ if actual != context.expected {
|
|
|
+ t.Fatalf("Expected \n%s, got \n%s", context.expected, actual)
|
|
|
+ }
|
|
|
+ // Clean buffer
|
|
|
+ out.Reset()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestImageContextWrite(t *testing.T) {
|
|
|
+ unixTime := time.Now().AddDate(0, 0, -1).Unix()
|
|
|
+ expectedTime := time.Unix(unixTime, 0).String()
|
|
|
+
|
|
|
+ contexts := []struct {
|
|
|
+ context ImageContext
|
|
|
+ expected string
|
|
|
+ }{
|
|
|
+ // Errors
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "{{InvalidFunction}}",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ `Template parsing error: template: :1: function "InvalidFunction" not defined
|
|
|
+`,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "{{nil}}",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ `Template parsing error: template: :1:2: executing "" at <nil>: nil is not a command
|
|
|
+`,
|
|
|
+ },
|
|
|
+ // Table Format
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ `REPOSITORY TAG IMAGE ID CREATED SIZE
|
|
|
+image tag1 imageID1 24 hours ago 0 B
|
|
|
+image <none> imageID1 24 hours ago 0 B
|
|
|
+image tag2 imageID2 24 hours ago 0 B
|
|
|
+<none> <none> imageID3 24 hours ago 0 B
|
|
|
+`,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table {{.Repository}}",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "REPOSITORY\nimage\nimage\nimage\n<none>\n",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table {{.Repository}}",
|
|
|
+ },
|
|
|
+ Digest: true,
|
|
|
+ },
|
|
|
+ `REPOSITORY DIGEST
|
|
|
+image <none>
|
|
|
+image sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf
|
|
|
+image <none>
|
|
|
+<none> <none>
|
|
|
+`,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table {{.Repository}}",
|
|
|
+ Quiet: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "REPOSITORY\nimage\nimage\nimage\n<none>\n",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table",
|
|
|
+ Quiet: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "imageID1\nimageID1\nimageID2\nimageID3\n",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table",
|
|
|
+ Quiet: false,
|
|
|
+ },
|
|
|
+ Digest: true,
|
|
|
+ },
|
|
|
+ `REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
|
|
|
+image tag1 <none> imageID1 24 hours ago 0 B
|
|
|
+image <none> sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf imageID1 24 hours ago 0 B
|
|
|
+image tag2 <none> imageID2 24 hours ago 0 B
|
|
|
+<none> <none> <none> imageID3 24 hours ago 0 B
|
|
|
+`,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table",
|
|
|
+ Quiet: true,
|
|
|
+ },
|
|
|
+ Digest: true,
|
|
|
+ },
|
|
|
+ "imageID1\nimageID1\nimageID2\nimageID3\n",
|
|
|
+ },
|
|
|
+ // Raw Format
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "raw",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ fmt.Sprintf(`repository: image
|
|
|
+tag: tag1
|
|
|
+image_id: imageID1
|
|
|
+created_at: %s
|
|
|
+virtual_size: 0 B
|
|
|
+
|
|
|
+repository: image
|
|
|
+tag: <none>
|
|
|
+image_id: imageID1
|
|
|
+created_at: %s
|
|
|
+virtual_size: 0 B
|
|
|
+
|
|
|
+repository: image
|
|
|
+tag: tag2
|
|
|
+image_id: imageID2
|
|
|
+created_at: %s
|
|
|
+virtual_size: 0 B
|
|
|
+
|
|
|
+repository: <none>
|
|
|
+tag: <none>
|
|
|
+image_id: imageID3
|
|
|
+created_at: %s
|
|
|
+virtual_size: 0 B
|
|
|
+
|
|
|
+`, expectedTime, expectedTime, expectedTime, expectedTime),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "raw",
|
|
|
+ },
|
|
|
+ Digest: true,
|
|
|
+ },
|
|
|
+ fmt.Sprintf(`repository: image
|
|
|
+tag: tag1
|
|
|
+digest: <none>
|
|
|
+image_id: imageID1
|
|
|
+created_at: %s
|
|
|
+virtual_size: 0 B
|
|
|
+
|
|
|
+repository: image
|
|
|
+tag: <none>
|
|
|
+digest: sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf
|
|
|
+image_id: imageID1
|
|
|
+created_at: %s
|
|
|
+virtual_size: 0 B
|
|
|
+
|
|
|
+repository: image
|
|
|
+tag: tag2
|
|
|
+digest: <none>
|
|
|
+image_id: imageID2
|
|
|
+created_at: %s
|
|
|
+virtual_size: 0 B
|
|
|
+
|
|
|
+repository: <none>
|
|
|
+tag: <none>
|
|
|
+digest: <none>
|
|
|
+image_id: imageID3
|
|
|
+created_at: %s
|
|
|
+virtual_size: 0 B
|
|
|
+
|
|
|
+`, expectedTime, expectedTime, expectedTime, expectedTime),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "raw",
|
|
|
+ Quiet: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ `image_id: imageID1
|
|
|
+image_id: imageID1
|
|
|
+image_id: imageID2
|
|
|
+image_id: imageID3
|
|
|
+`,
|
|
|
+ },
|
|
|
+ // Custom Format
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "{{.Repository}}",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "image\nimage\nimage\n<none>\n",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "{{.Repository}}",
|
|
|
+ },
|
|
|
+ Digest: true,
|
|
|
+ },
|
|
|
+ "image\nimage\nimage\n<none>\n",
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, context := range contexts {
|
|
|
+ images := []types.Image{
|
|
|
+ {ID: "imageID1", RepoTags: []string{"image:tag1"}, RepoDigests: []string{"image@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf"}, Created: unixTime},
|
|
|
+ {ID: "imageID2", RepoTags: []string{"image:tag2"}, Created: unixTime},
|
|
|
+ {ID: "imageID3", RepoTags: []string{"<none>:<none>"}, RepoDigests: []string{"<none>@<none>"}, Created: unixTime},
|
|
|
+ }
|
|
|
+ out := bytes.NewBufferString("")
|
|
|
+ context.context.Output = out
|
|
|
+ context.context.Images = images
|
|
|
+ context.context.Write()
|
|
|
+ actual := out.String()
|
|
|
+ if actual != context.expected {
|
|
|
+ t.Fatalf("Expected \n%s, got \n%s", context.expected, actual)
|
|
|
+ }
|
|
|
+ // Clean buffer
|
|
|
+ out.Reset()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestImageContextWriteWithNoImage(t *testing.T) {
|
|
|
+ out := bytes.NewBufferString("")
|
|
|
+ images := []types.Image{}
|
|
|
+
|
|
|
+ contexts := []struct {
|
|
|
+ context ImageContext
|
|
|
+ expected string
|
|
|
+ }{
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "{{.Repository}}",
|
|
|
+ Output: out,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table {{.Repository}}",
|
|
|
+ Output: out,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ "REPOSITORY\n",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "{{.Repository}}",
|
|
|
+ Output: out,
|
|
|
+ },
|
|
|
+ Digest: true,
|
|
|
+ },
|
|
|
+ "",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ImageContext{
|
|
|
+ Context: Context{
|
|
|
+ Format: "table {{.Repository}}",
|
|
|
+ Output: out,
|
|
|
+ },
|
|
|
+ Digest: true,
|
|
|
+ },
|
|
|
+ "REPOSITORY DIGEST\n",
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, context := range contexts {
|
|
|
+ context.context.Images = images
|
|
|
+ context.context.Write()
|
|
|
+ actual := out.String()
|
|
|
+ if actual != context.expected {
|
|
|
+ t.Fatalf("Expected \n%s, got \n%s", context.expected, actual)
|
|
|
+ }
|
|
|
+ // Clean buffer
|
|
|
+ out.Reset()
|
|
|
+ }
|
|
|
+}
|