mirror of
https://github.com/kreuzwerker/terraform-provider-docker.git
synced 2025-12-20 14:49:41 -05:00
feat: Add build attribute for docker_registry_image (#805)
This commit is contained in:
parent
71485e5cfd
commit
ac05128fba
6 changed files with 459 additions and 396 deletions
|
|
@ -79,7 +79,26 @@ func resourceDockerImage() *schema.Resource {
|
|||
Optional: true,
|
||||
MaxItems: 1,
|
||||
ConflictsWith: []string{"pull_triggers"},
|
||||
Elem: &schema.Resource{
|
||||
Elem: buildSchema,
|
||||
},
|
||||
"triggers": {
|
||||
Description: "A map of arbitrary strings that, when changed, will force the `docker_image` resource to be replaced. This can be used to rebuild an image when contents of source code folders change",
|
||||
Type: schema.TypeMap,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"platform": {
|
||||
Type: schema.TypeString,
|
||||
Description: "The platform to use when pulling the image. Defaults to the platform of the current machine.",
|
||||
Optional: true,
|
||||
Default: "",
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var buildSchema = &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"dockerfile": {
|
||||
Type: schema.TypeString,
|
||||
|
|
@ -437,21 +456,4 @@ func resourceDockerImage() *schema.Resource {
|
|||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"triggers": {
|
||||
Description: "A map of arbitrary strings that, when changed, will force the `docker_image` resource to be replaced. This can be used to rebuild an image when contents of source code folders change",
|
||||
Type: schema.TypeMap,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"platform": {
|
||||
Type: schema.TypeString,
|
||||
Description: "The platform to use when pulling the image. Defaults to the platform of the current machine.",
|
||||
Optional: true,
|
||||
Default: "",
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,42 +37,9 @@ func resourceDockerImageCreate(ctx context.Context, d *schema.ResourceData, meta
|
|||
|
||||
if value, ok := d.GetOk("build"); ok {
|
||||
for _, rawBuild := range value.(*schema.Set).List() {
|
||||
rawBuild := rawBuild.(map[string]interface{})
|
||||
// now we need to determine whether we can use buildx or need to use the legacy builder
|
||||
canUseBuildx, err := canUseBuildx(ctx, client)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
builder := rawBuild["builder"].(string)
|
||||
log.Printf("[DEBUG] canUseBuildx: %v, builder %s", canUseBuildx, builder)
|
||||
// buildx is enabled
|
||||
if canUseBuildx && builder != "" {
|
||||
log.Printf("[DEBUG] Using buildx")
|
||||
dockerCli, err := createAndInitDockerCli(client)
|
||||
if err != nil {
|
||||
return diag.FromErr(fmt.Errorf("failed to create and init Docker CLI: %w", err))
|
||||
}
|
||||
|
||||
options, err := mapBuildAttributesToBuildOptions(rawBuild, imageName)
|
||||
|
||||
if err != nil {
|
||||
return diag.FromErr(fmt.Errorf("Error mapping build attributes: %v", err))
|
||||
}
|
||||
buildLogFile := rawBuild["build_log_file"].(string)
|
||||
|
||||
log.Printf("[DEBUG] build options %#v", options)
|
||||
|
||||
err = runBuild(ctx, dockerCli, options, buildLogFile)
|
||||
if err != nil {
|
||||
return diag.Errorf("Error running buildx build: %v", err)
|
||||
}
|
||||
} else {
|
||||
|
||||
err := buildDockerImage(ctx, rawBuild, imageName, client)
|
||||
if err != nil {
|
||||
return diag.Errorf("Error running legacy build: %v", err)
|
||||
}
|
||||
shouldReturn, d1 := buildImage(ctx, rawBuild, client, imageName)
|
||||
if shouldReturn {
|
||||
return d1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -85,6 +52,47 @@ func resourceDockerImageCreate(ctx context.Context, d *schema.ResourceData, meta
|
|||
return resourceDockerImageRead(ctx, d, meta)
|
||||
}
|
||||
|
||||
func buildImage(ctx context.Context, rawBuild interface{}, client *client.Client, imageName string) (bool, diag.Diagnostics) {
|
||||
rawBuildValue := rawBuild.(map[string]interface{})
|
||||
// now we need to determine whether we can use buildx or need to use the legacy builder
|
||||
canUseBuildx, err := canUseBuildx(ctx, client)
|
||||
if err != nil {
|
||||
return true, diag.FromErr(err)
|
||||
}
|
||||
|
||||
builder := rawBuildValue["builder"].(string)
|
||||
log.Printf("[DEBUG] canUseBuildx: %v, builder %s", canUseBuildx, builder)
|
||||
// buildx is enabled
|
||||
if canUseBuildx && builder != "" {
|
||||
log.Printf("[DEBUG] Using buildx")
|
||||
dockerCli, err := createAndInitDockerCli(client)
|
||||
if err != nil {
|
||||
return true, diag.FromErr(fmt.Errorf("failed to create and init Docker CLI: %w", err))
|
||||
}
|
||||
|
||||
options, err := mapBuildAttributesToBuildOptions(rawBuildValue, imageName)
|
||||
|
||||
if err != nil {
|
||||
return true, diag.FromErr(fmt.Errorf("Error mapping build attributes: %v", err))
|
||||
}
|
||||
buildLogFile := rawBuildValue["build_log_file"].(string)
|
||||
|
||||
log.Printf("[DEBUG] build options %#v", options)
|
||||
|
||||
err = runBuild(ctx, dockerCli, options, buildLogFile)
|
||||
if err != nil {
|
||||
return true, diag.Errorf("Error running buildx build: %v", err)
|
||||
}
|
||||
} else {
|
||||
|
||||
err := legacyBuildDockerImage(ctx, rawBuildValue, imageName, client)
|
||||
if err != nil {
|
||||
return true, diag.Errorf("Error running legacy build: %v", err)
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func resourceDockerImageRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
client := meta.(*ProviderConfig).DockerClient
|
||||
var data Data
|
||||
|
|
@ -353,7 +361,7 @@ func findImage(ctx context.Context, imageName string, client *client.Client, aut
|
|||
return nil, fmt.Errorf("unable to find or pull image %s", imageName)
|
||||
}
|
||||
|
||||
func buildDockerImage(ctx context.Context, rawBuild map[string]interface{}, imageName string, client *client.Client) error {
|
||||
func legacyBuildDockerImage(ctx context.Context, rawBuild map[string]interface{}, imageName string, client *client.Client) error {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
|
|
|||
|
|
@ -63,6 +63,13 @@ func resourceDockerRegistryImage() *schema.Resource {
|
|||
},
|
||||
|
||||
"auth_config": AuthConfigSchema,
|
||||
"build": {
|
||||
Type: schema.TypeSet,
|
||||
Description: "Configuration to build an image. Requires the `Use containerd for pulling and storing images` option to be disabled in the Docker Host(https://github.com/kreuzwerker/terraform-provider-docker/issues/534). Please see [docker build command reference](https://docs.docker.com/engine/reference/commandline/build/#options) too.",
|
||||
Optional: true,
|
||||
MaxItems: 1,
|
||||
Elem: buildSchema,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,14 @@ func resourceDockerRegistryImageCreate(ctx context.Context, d *schema.ResourceDa
|
|||
providerConfig := meta.(*ProviderConfig)
|
||||
name := d.Get("name").(string)
|
||||
log.Printf("[DEBUG] Creating docker image %s", name)
|
||||
if value, ok := d.GetOk("build"); ok {
|
||||
for _, rawBuild := range value.(*schema.Set).List() {
|
||||
shouldReturn, d1 := buildImage(ctx, rawBuild, client, name)
|
||||
if shouldReturn {
|
||||
return d1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pushOpts := createPushImageOptions(name)
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,27 @@ func TestAccDockerRegistryImageResource_buildAndKeep(t *testing.T) {
|
|||
CheckDestroy: testDockerRegistryImageInRegistry("testuser", "testpwd", pushOptions, true),
|
||||
})
|
||||
}
|
||||
func TestAccDockerRegistryImageResource_directBuildAndKeep(t *testing.T) {
|
||||
pushOptions := createPushImageOptions("127.0.0.1:15000/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_registry_image", "testDirectBuildDockerRegistryImageKeepConfig"), pushOptions.Registry, pushOptions.Name, context),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttrSet("docker_registry_image.foo", "sha256_digest"),
|
||||
),
|
||||
},
|
||||
},
|
||||
// as the providerConfig obtained from testAccProvider.Meta().(*ProviderConfig)
|
||||
// is empty after the test the credetials are passed here manually
|
||||
CheckDestroy: testDockerRegistryImageInRegistry("testuser", "testpwd", pushOptions, true),
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccDockerRegistryImageResource_pushMissingImage(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
|
|
|
|||
17
testdata/resources/docker_registry_image/testDirectBuildDockerRegistryImageKeepConfig.tf
vendored
Normal file
17
testdata/resources/docker_registry_image/testDirectBuildDockerRegistryImageKeepConfig.tf
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
provider "docker" {
|
||||
alias = "private"
|
||||
registry_auth {
|
||||
address = "%s"
|
||||
}
|
||||
}
|
||||
|
||||
resource "docker_registry_image" "foo" {
|
||||
provider = "docker.private"
|
||||
name = "%s"
|
||||
|
||||
build {
|
||||
context = "%s"
|
||||
}
|
||||
insecure_skip_verify = true
|
||||
keep_remotely = true
|
||||
}
|
||||
Loading…
Reference in a new issue