mirror of
https://github.com/kreuzwerker/terraform-provider-docker.git
synced 2025-12-18 23:06:10 -05:00
* chore: Upgrade golangci-lint to next major version * chore: Add //nolint to new tests --------- Co-authored-by: Martin Wentzel <junker@monoceres.uberspace.de>
712 lines
26 KiB
Go
712 lines
26 KiB
Go
package provider
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"reflect"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/docker/docker/api/types/container"
|
|
"github.com/docker/go-units"
|
|
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
|
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
|
|
)
|
|
|
|
var contentDigestRegexp = regexp.MustCompile(`\A[A-Za-z0-9_\+\.-]+:[A-Fa-f0-9]+\z`)
|
|
|
|
func TestAccDockerRegistryImageResource_mapping(t *testing.T) {
|
|
assert := func(condition bool, msg string) {
|
|
if !condition {
|
|
t.Errorf("assertion failed: wrong build parameter %s", msg)
|
|
}
|
|
}
|
|
|
|
dummyProvider := New("dev")()
|
|
dummyResource := dummyProvider.ResourcesMap["docker_image"]
|
|
dummyResource.CreateContext = func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
|
|
|
if value, ok := d.GetOk("build"); ok {
|
|
for _, rawBuild := range value.(*schema.Set).List() {
|
|
build := rawBuild.(map[string]interface{})
|
|
// build := d.Get("build").([]interface{})[0].(map[string]interface{})
|
|
options := createImageBuildOptions(build)
|
|
|
|
assert(options.SuppressOutput == true, "SuppressOutput")
|
|
assert(options.RemoteContext == "fooRemoteContext", "RemoteContext")
|
|
assert(options.NoCache == true, "NoCache")
|
|
assert(options.Remove == true, "Remove")
|
|
assert(options.ForceRemove == true, "ForceRemove")
|
|
assert(options.PullParent == true, "PullParent")
|
|
assert(options.Isolation == container.Isolation("hyperv"), "Isolation")
|
|
assert(options.CPUSetCPUs == "fooCpuSetCpus", "CPUSetCPUs")
|
|
assert(options.CPUSetMems == "fooCpuSetMems", "CPUSetMems")
|
|
assert(options.CPUShares == int64(4), "CPUShares")
|
|
assert(options.CPUQuota == int64(5), "CPUQuota")
|
|
assert(options.CPUPeriod == int64(6), "CPUPeriod")
|
|
assert(options.Memory == int64(1), "Memory")
|
|
assert(options.MemorySwap == int64(2), "MemorySwap")
|
|
assert(options.CgroupParent == "fooCgroupParent", "CgroupParent")
|
|
assert(options.NetworkMode == "fooNetworkMode", "NetworkMode")
|
|
assert(options.ShmSize == int64(3), "ShmSize")
|
|
assert(options.Dockerfile == "fooDockerfile", "Dockerfile")
|
|
assert(len(options.Ulimits) == 1, "Ulimits")
|
|
assert(reflect.DeepEqual(*options.Ulimits[0], units.Ulimit{
|
|
Name: "foo",
|
|
Hard: int64(1),
|
|
Soft: int64(2),
|
|
}), "Ulimits")
|
|
assert(len(options.BuildArgs) == 1, "BuildArgs")
|
|
// DevSkim: ignore DS137138
|
|
assert(*options.BuildArgs["HTTP_PROXY"] == "http://10.20.30.2:1234", "BuildArgs")
|
|
assert(len(options.AuthConfigs) == 1, "AuthConfigs")
|
|
assert(reflect.DeepEqual(options.AuthConfigs["foo.host"], types.AuthConfig{
|
|
Username: "fooUserName",
|
|
Password: "fooPassword",
|
|
Auth: "fooAuth",
|
|
Email: "fooEmail",
|
|
ServerAddress: "fooServerAddress",
|
|
IdentityToken: "fooIdentityToken",
|
|
RegistryToken: "fooRegistryToken",
|
|
}), "AuthConfigs")
|
|
assert(reflect.DeepEqual(options.Labels, map[string]string{"foo": "bar"}), "Labels")
|
|
assert(options.Squash == true, "Squash")
|
|
assert(reflect.DeepEqual(options.CacheFrom, []string{"fooCacheFrom", "barCacheFrom"}), "CacheFrom")
|
|
assert(reflect.DeepEqual(options.SecurityOpt, []string{"fooSecurityOpt", "barSecurityOpt"}), "SecurityOpt")
|
|
assert(reflect.DeepEqual(options.ExtraHosts, []string{"fooExtraHost", "barExtraHost"}), "ExtraHosts")
|
|
assert(options.Target == "fooTarget", "Target")
|
|
assert(options.SessionID == "fooSessionId", "SessionID")
|
|
assert(options.Platform == "fooPlatform", "Platform")
|
|
assert(options.Version == types.BuilderVersion("1"), "Version")
|
|
assert(options.BuildID == "fooBuildId", "BuildID")
|
|
// output
|
|
d.SetId("foo")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
dummyResource.UpdateContext = func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
|
return nil
|
|
}
|
|
dummyResource.DeleteContext = func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
|
return nil
|
|
}
|
|
dummyResource.ReadContext = func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
|
d.Set("id", "foo")
|
|
return nil
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: map[string]func() (*schema.Provider, error){
|
|
"docker": func() (*schema.Provider, error) {
|
|
return dummyProvider, nil
|
|
},
|
|
},
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testBuildDockerImageMappingConfig"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestCheckResourceAttrSet("docker_image.foo", "id"),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImage_basic(t *testing.T) {
|
|
// run a Docker container which refers the Docker image to test "force_remove" option
|
|
containerName := "test-docker-image-force-remove"
|
|
ctx := context.Background()
|
|
if err := exec.Command("docker", "run", "--rm", "-d", "--name", containerName, "alpine:3.16.0", "tail", "-f", "/dev/null").Run(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer func() {
|
|
if err := exec.Command("docker", "stop", containerName).Run(); err != nil {
|
|
t.Logf("failed to stop the Docker container %s: %v", containerName, err)
|
|
}
|
|
}()
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
CheckDestroy: func(state *terraform.State) error {
|
|
return testAccDockerImageDestroy(ctx, state)
|
|
},
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testAccDockerImageConfig"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.foo", "repo_digest", imageRepoDigestRegexp),
|
|
),
|
|
},
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testAccForceRemoveDockerImage"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.test", "repo_digest", imageRepoDigestRegexp),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImage_private(t *testing.T) {
|
|
ctx := context.Background()
|
|
var i types.ImageInspect
|
|
|
|
testCheckImageInspect := func(*terraform.State) error {
|
|
if len(i.RepoTags) != 1 ||
|
|
i.RepoTags[0] != "gcr.io:443/google_containers/pause:1.0" {
|
|
return fmt.Errorf("Image RepoTags is wrong: %v", i.RepoTags)
|
|
}
|
|
|
|
if len(i.RepoDigests) != 1 ||
|
|
i.RepoDigests[0] != "gcr.io:443/google_containers/pause@sha256:a78c2d6208eff9b672de43f880093100050983047b7b0afe0217d3656e1b0d5f" {
|
|
return fmt.Errorf("Image RepoDigests is wrong: %v", i.RepoDigests)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
CheckDestroy: func(state *terraform.State) error {
|
|
return testAccDockerImageDestroy(ctx, state)
|
|
},
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testAddDockerPrivateImageConfig"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.foobar", "repo_digest", imageRepoDigestRegexp),
|
|
testAccImageCreated("docker_image.foobar", &i),
|
|
testCheckImageInspect,
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImage_destroy(t *testing.T) {
|
|
ctx := context.Background()
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
CheckDestroy: func(s *terraform.State) error {
|
|
for _, rs := range s.RootModule().Resources {
|
|
if rs.Type != "docker_image" {
|
|
continue
|
|
}
|
|
|
|
client := testAccProvider.Meta().(*ProviderConfig).DockerClient
|
|
_, _, err := client.ImageInspectWithRaw(ctx, rs.Primary.Attributes["name"])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testAccDockerImageKeepLocallyConfig"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.foobarzoo", "repo_digest", imageRepoDigestRegexp),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImage_data(t *testing.T) {
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
PreventPostDestroyRefresh: true,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testAccDockerImageFromDataConfig"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.foobarbaz", "repo_digest", imageRepoDigestRegexp),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImage_data_pull_trigger(t *testing.T) {
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
PreventPostDestroyRefresh: true,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testAccDockerImageFromDataConfigWithPullTrigger"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.foobarbazoo", "repo_digest", imageRepoDigestRegexp),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImage_data_private(t *testing.T) {
|
|
registry := "127.0.0.1:15000"
|
|
image := "127.0.0.1:15000/tftest-service:v1"
|
|
ctx := context.Background()
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
PreventPostDestroyRefresh: true,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: fmt.Sprintf(loadTestConfiguration(t, RESOURCE, "docker_image", "testAccDockerImageFromDataPrivateConfig"), registry, image),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.foo_private", "repo_digest", imageRepoDigestRegexp),
|
|
),
|
|
},
|
|
},
|
|
CheckDestroy: func(state *terraform.State) error {
|
|
return checkAndRemoveImages(ctx, state)
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImage_data_private_config_file(t *testing.T) {
|
|
registry := "127.0.0.1:15000"
|
|
image := "127.0.0.1:15000/tftest-service:v1"
|
|
wd, _ := os.Getwd()
|
|
dockerConfig := strings.ReplaceAll(filepath.Join(wd, "..", "..", "scripts", "testing", "dockerconfig.json"), "\\", "\\\\")
|
|
ctx := context.Background()
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
PreventPostDestroyRefresh: true,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: fmt.Sprintf(loadTestConfiguration(t, RESOURCE, "docker_image", "testAccDockerImageFromDataPrivateConfigFile"), registry, dockerConfig, image),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.foo_private", "repo_digest", imageRepoDigestRegexp),
|
|
),
|
|
},
|
|
},
|
|
CheckDestroy: func(state *terraform.State) error {
|
|
return checkAndRemoveImages(ctx, state)
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImage_data_private_config_file_content(t *testing.T) {
|
|
registry := "127.0.0.1:15000"
|
|
image := "127.0.0.1:15000/tftest-service:v1"
|
|
wd, _ := os.Getwd()
|
|
dockerConfig := strings.ReplaceAll(filepath.Join(wd, "..", "..", "scripts", "testing", "dockerconfig.json"), "\\", "\\\\")
|
|
ctx := context.Background()
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
PreventPostDestroyRefresh: true,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: fmt.Sprintf(loadTestConfiguration(t, RESOURCE, "docker_image", "testAccDockerImageFromDataPrivateConfigFileContent"), registry, dockerConfig, image),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.foo_private", "repo_digest", imageRepoDigestRegexp),
|
|
),
|
|
},
|
|
},
|
|
CheckDestroy: func(state *terraform.State) error {
|
|
return checkAndRemoveImages(ctx, state)
|
|
},
|
|
})
|
|
}
|
|
|
|
// Changing the name attribute should also force a change of the dependent docker container
|
|
// This test fails, if we remove the ForceTrue: true from the name attribute
|
|
func TestAccDockerImage_name_attr_change(t *testing.T) {
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
PreventPostDestroyRefresh: true,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: fmt.Sprintf(loadTestConfiguration(t, RESOURCE, "docker_image", "testAccDockerImageName"), "ubuntu:precise@sha256:18305429afa14ea462f810146ba44d4363ae76e4c8dfc38288cf73aa07485005"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.ubuntu", "repo_digest", imageRepoDigestRegexp),
|
|
),
|
|
},
|
|
{
|
|
Config: fmt.Sprintf(loadTestConfiguration(t, RESOURCE, "docker_image", "testAccDockerImageName"), "ubuntu:jammy@sha256:b6b83d3c331794420340093eb706a6f152d9c1fa51b262d9bf34594887c2c7ac"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.ubuntu", "repo_digest", imageRepoDigestRegexp),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImage_sha265(t *testing.T) {
|
|
ctx := context.Background()
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
CheckDestroy: func(state *terraform.State) error {
|
|
return testAccDockerImageDestroy(ctx, state)
|
|
},
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testAddDockerImageWithSHA256RepoDigest"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.foobar", "repo_digest", imageRepoDigestRegexp),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func testAccDockerImageDestroy(ctx context.Context, s *terraform.State) error {
|
|
for _, rs := range s.RootModule().Resources {
|
|
if rs.Type != "docker_image" {
|
|
continue
|
|
}
|
|
|
|
client := testAccProvider.Meta().(*ProviderConfig).DockerClient
|
|
_, _, err := client.ImageInspectWithRaw(ctx, rs.Primary.Attributes["name"])
|
|
if err == nil {
|
|
return fmt.Errorf("Image still exists")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func TestAccDockerImage_tag_sha265(t *testing.T) {
|
|
ctx := context.Background()
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
CheckDestroy: func(state *terraform.State) error {
|
|
return testAccDockerImageDestroy(ctx, state)
|
|
},
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testAccDockerImageWithTagAndSHA256RepoDigest"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.nginx", "repo_digest", imageRepoDigestRegexp),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImage_platform(t *testing.T) {
|
|
ctx := context.Background()
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
CheckDestroy: func(state *terraform.State) error {
|
|
return testAccDockerImageDestroy(ctx, state)
|
|
},
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testAccDockerImagePlatform"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestCheckResourceAttr("docker_image.foo", "image_id", "sha256:8336f9f1d0946781f428a155536995f0d8a31209d65997e2a379a23e7a441b78"),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImage_build(t *testing.T) {
|
|
ctx := context.Background()
|
|
wd, _ := os.Getwd()
|
|
dfPath := filepath.Join(wd, "Dockerfile")
|
|
if err := os.WriteFile(dfPath, []byte(testDockerFileExample), 0o644); err != nil {
|
|
t.Fatalf("failed to create a Dockerfile %s for test: %+v", dfPath, err)
|
|
}
|
|
defer os.Remove(dfPath) //nolint:errcheck
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
CheckDestroy: func(state *terraform.State) error {
|
|
return testAccDockerImageDestroy(ctx, state)
|
|
},
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testCreateDockerImage"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.test", "name", contentDigestRegexp),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImageSecrets_build(t *testing.T) {
|
|
const testDockerFileWithSecret = `
|
|
FROM python:3-bookworm
|
|
|
|
WORKDIR /app
|
|
|
|
ARG test_arg
|
|
|
|
RUN echo ${test_arg} > test_arg.txt
|
|
|
|
RUN --mount=type=secret,id=TEST_SECRET_SRC \
|
|
--mount=type=secret,id=TEST_SECRET_ENV \
|
|
apt-get update -qq`
|
|
|
|
ctx := context.Background()
|
|
wd, _ := os.Getwd()
|
|
dfPath := filepath.Join(wd, "Dockerfile")
|
|
if err := os.WriteFile(dfPath, []byte(testDockerFileWithSecret), 0o644); err != nil {
|
|
t.Fatalf("failed to create a Dockerfile %s for test: %+v", dfPath, err)
|
|
}
|
|
defer os.Remove(dfPath) //nolint:errcheck
|
|
|
|
const secretContent = "THIS IS A SECRET"
|
|
sPath := filepath.Join(wd, "secret")
|
|
if err := os.WriteFile(sPath, []byte(secretContent), 0o644); err != nil {
|
|
t.Fatalf("failed to create a secret file %s for test: %+v", sPath, err)
|
|
}
|
|
|
|
defer os.Remove(sPath) //nolint:errcheck
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
CheckDestroy: func(state *terraform.State) error {
|
|
return testAccDockerImageDestroy(ctx, state)
|
|
},
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testDockerImageBuildSecrets"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.test", "name", contentDigestRegexp),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
const testDockerFileExample = `
|
|
FROM python:3-bookworm
|
|
|
|
WORKDIR /app
|
|
|
|
ARG test_arg
|
|
|
|
RUN echo ${test_arg} > test_arg.txt
|
|
|
|
RUN apt-get update -qq
|
|
`
|
|
|
|
// Test for implementation of https://github.com/kreuzwerker/terraform-provider-docker/issues/401
|
|
func TestAccDockerImage_buildOutsideContext(t *testing.T) {
|
|
ctx := context.Background()
|
|
wd, _ := os.Getwd()
|
|
dfPath := filepath.Join(wd, "..", "Dockerfile")
|
|
if err := os.WriteFile(dfPath, []byte(testDockerFileExample), 0o644); err != nil {
|
|
t.Fatalf("failed to create a Dockerfile %s for test: %+v", dfPath, err)
|
|
}
|
|
defer os.Remove(dfPath) //nolint:errcheck
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
CheckDestroy: func(state *terraform.State) error {
|
|
return testAccDockerImageDestroy(ctx, state)
|
|
},
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: loadTestConfiguration(t, RESOURCE, "docker_image", "testDockerImageDockerfileOutsideContext"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestMatchResourceAttr("docker_image.outside_context", "name", regexp.MustCompile(`\Aoutside-context:latest\z`)),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImageResource_build(t *testing.T) {
|
|
name := "tftest-dockerregistryimage:1.0"
|
|
wd, _ := os.Getwd()
|
|
context := strings.ReplaceAll((filepath.Join(wd, "..", "..", "scripts", "testing", "docker_registry_image_context")), "\\", "\\\\")
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: fmt.Sprintf(loadTestConfiguration(t, RESOURCE, "docker_image", "testBuildDockerImageNoKeepConfig"), name, context),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestCheckResourceAttrSet("docker_image.foo", "image_id"),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
// Test for https://github.com/kreuzwerker/terraform-provider-docker/issues/249
|
|
func TestAccDockerImageResource_whitelistDockerignore(t *testing.T) {
|
|
name := "tftest-dockerregistryimage-whitelistdockerignore:1.0"
|
|
wd, _ := os.Getwd()
|
|
context := strings.ReplaceAll((filepath.Join(wd, "..", "..", "scripts", "testing", "docker_registry_image_file_whitelist_dockerignore")), "\\", "\\\\")
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: fmt.Sprintf(loadTestConfiguration(t, RESOURCE, "docker_image", "testDockerImageFilePermissions"), name, context, "Dockerfile"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestCheckResourceAttrSet("docker_image.file_permissions", "image_id"),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
// Tests for issue https://github.com/kreuzwerker/terraform-provider-docker/issues/293
|
|
// First we check if we can build the docker_registry_image resource at all
|
|
// TODO in a second step we want to check whether the file has the correct permissions
|
|
func TestAccDockerImageResource_correctFilePermissions(t *testing.T) {
|
|
name := "tftest-dockerregistryimage-filepermissions:1.0"
|
|
wd, _ := os.Getwd()
|
|
context := strings.ReplaceAll((filepath.Join(wd, "..", "..", "scripts", "testing", "docker_registry_image_file_permissions")), "\\", "\\\\")
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: fmt.Sprintf(loadTestConfiguration(t, RESOURCE, "docker_image", "testDockerImageFilePermissions"), name, context, "Dockerfile"),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestCheckResourceAttrSet("docker_image.file_permissions", "image_id"),
|
|
),
|
|
// TODO another check which starts the the newly built docker image and checks the file permissions to see if they are correct
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccDockerImageResource_buildWithDockerignore(t *testing.T) {
|
|
name := "tftest-dockerregistryimage-ignore:1.0"
|
|
wd, _ := os.Getwd()
|
|
ctx := context.Background()
|
|
context := strings.ReplaceAll((filepath.Join(wd, "..", "..", "scripts", "testing", "docker_registry_image_context_dockerignore")), "\\", "\\\\")
|
|
ignoredFile := context + "/to_be_ignored"
|
|
expectedSha := ""
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
ProviderFactories: providerFactories,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: fmt.Sprintf(loadTestConfiguration(t, RESOURCE, "docker_image", "testBuildDockerImageNoKeepJustCache"), "one", name, context),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestCheckResourceAttrSet("docker_image.one", "image_id"),
|
|
resource.TestCheckResourceAttrWith("docker_image.one", "image_id", func(value string) error {
|
|
expectedSha = value
|
|
return nil
|
|
}),
|
|
),
|
|
},
|
|
{
|
|
PreConfig: func() {
|
|
// create a file that should be ignored
|
|
f, err := os.OpenFile(ignoredFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
panic("failed to create test file")
|
|
}
|
|
f.Close() //nolint:errcheck
|
|
},
|
|
Config: fmt.Sprintf(loadTestConfiguration(t, RESOURCE, "docker_image", "testBuildDockerImageNoKeepJustCache"), "two", name, context),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
resource.TestCheckResourceAttrWith("docker_image.two", "image_id", func(value string) error {
|
|
if value != expectedSha {
|
|
return fmt.Errorf("Image sha256_digest changed, expected %#v, got %#v", expectedSha, value)
|
|
}
|
|
return nil
|
|
}),
|
|
),
|
|
},
|
|
},
|
|
CheckDestroy: func(state *terraform.State) error {
|
|
return testAccDockerImageDestroy(ctx, state)
|
|
},
|
|
})
|
|
}
|
|
|
|
func testAccImageCreated(resourceName string, image *types.ImageInspect) resource.TestCheckFunc {
|
|
return func(s *terraform.State) error {
|
|
ctx := context.Background()
|
|
rs, ok := s.RootModule().Resources[resourceName]
|
|
if !ok {
|
|
return fmt.Errorf("Resource with name '%s' not found in state", resourceName)
|
|
}
|
|
|
|
if rs.Primary.ID == "" {
|
|
return fmt.Errorf("No ID is set")
|
|
}
|
|
|
|
name := rs.Primary.Attributes["name"]
|
|
// TODO mavogel: it's because we set the ID in the format:
|
|
// d.SetId(foundImage.ID + d.Get("name").(string))
|
|
// so we need to strip away the name
|
|
strippedID := strings.ReplaceAll(rs.Primary.ID, name, "")
|
|
|
|
client := testAccProvider.Meta().(*ProviderConfig).DockerClient
|
|
inspectedImage, _, err := client.ImageInspectWithRaw(ctx, strippedID)
|
|
if err != nil {
|
|
return fmt.Errorf("Image with ID '%s': %w", strippedID, err)
|
|
}
|
|
|
|
// we set the value to the pointer to be able to use the value
|
|
// outside of the function
|
|
*image = inspectedImage
|
|
return nil
|
|
|
|
}
|
|
}
|
|
|
|
func TestParseImageOptions(t *testing.T) {
|
|
t.Run("Should parse image name with registry", func(t *testing.T) {
|
|
expected := internalPullImageOptions{Registry: "registry.com", Repository: "image", Tag: "tag"}
|
|
result := parseImageOptions("registry.com/image:tag")
|
|
if !reflect.DeepEqual(expected, result) {
|
|
t.Fatalf("Result %#v did not match expectation %#v", result, expected)
|
|
}
|
|
})
|
|
t.Run("Should parse image name with registryPort", func(t *testing.T) {
|
|
expected := internalPullImageOptions{Registry: "registry.com:8080", Repository: "image", Tag: "tag"}
|
|
result := parseImageOptions("registry.com:8080/image:tag")
|
|
if !reflect.DeepEqual(expected, result) {
|
|
t.Fatalf("Result %#v did not match expectation %#v", result, expected)
|
|
}
|
|
})
|
|
t.Run("Should parse image name with registry and proper repository", func(t *testing.T) {
|
|
expected := internalPullImageOptions{Registry: "registry.com", Repository: "repo/image", Tag: "tag"}
|
|
result := parseImageOptions("registry.com/repo/image:tag")
|
|
if !reflect.DeepEqual(expected, result) {
|
|
t.Fatalf("Result %#v did not match expectation %#v", result, expected)
|
|
}
|
|
})
|
|
t.Run("Should parse image with no tag", func(t *testing.T) {
|
|
expected := internalPullImageOptions{Registry: "registry.com", Repository: "repo/image", Tag: "latest"}
|
|
result := parseImageOptions("registry.com/repo/image")
|
|
if !reflect.DeepEqual(expected, result) {
|
|
t.Fatalf("Result %#v did not match expectation %#v", result, expected)
|
|
}
|
|
})
|
|
t.Run("Should parse image name without registry and default to docker registry", func(t *testing.T) {
|
|
expected := internalPullImageOptions{Registry: "registry-1.docker.io", Repository: "library/image", Tag: "tag"}
|
|
result := parseImageOptions("image:tag")
|
|
if !reflect.DeepEqual(expected, result) {
|
|
t.Fatalf("Result %#v did not match expectation %#v", result, expected)
|
|
}
|
|
})
|
|
}
|