Skip to content

Commit

Permalink
Add data source packer_build
Browse files Browse the repository at this point in the history
  • Loading branch information
simaotwx committed Apr 1, 2022
1 parent c44de50 commit a5d9805
Show file tree
Hide file tree
Showing 12 changed files with 400 additions and 21 deletions.
26 changes: 26 additions & 0 deletions docs/data-sources/build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "packer_build Data Source - terraform-provider-packer"
subcategory: ""
description: |-
Waits for the build specified by its name to finish. This is only useful when you define the name outside of the packerimage resource, allowing both the packerimage resource and this data source to reference the same build. Use this if you want to have the image created before recreating a VM when recreation involves deletion in which case the downtime would include the image build process.
---

# packer_build (Data Source)

Waits for the build specified by its name to finish. This is only useful when you define the name outside of the packer_image resource, allowing both the packer_image resource and this data source to reference the same build. Use this if you want to have the image created before recreating a VM when recreation involves deletion in which case the downtime would include the image build process.



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `name` (String) Name of the build. Use a resource, like random_string otherwise it hangs during plan.

### Read-Only

- `uuid` (String) Build UUID of the referenced build


8 changes: 4 additions & 4 deletions docs/data-sources/files.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ Specify files to detect changes. By default, the current directory will be used.

### Optional

- **directory** (String) Directory to run packer in. Defaults to cwd.
- **file** (String) Packer file to use for building
- **file_dependencies** (Set of String) Files that should be depended on so that the resource is updated when these files change
- `directory` (String) Directory to run packer in. Defaults to cwd.
- `file` (String) Packer file to use for building
- `file_dependencies` (Set of String) Files that should be depended on so that the resource is updated when these files change

### Read-Only

- **files_hash** (String) Hash of the files provided. Used for updates.
- `files_hash` (String) Hash of the files provided. Used for updates.


2 changes: 1 addition & 1 deletion docs/data-sources/version.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ description: |-

### Read-Only

- **version** (String) Version of embedded Packer
- `version` (String) Version of embedded Packer


2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ description: |-

### Optional

- **dummy** (String) Used as a placeholder. Do not use.
- `dummy` (String) Used as a placeholder. Do not use.
21 changes: 11 additions & 10 deletions docs/resources/image.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,19 @@ description: |-

### Optional

- **additional_params** (Set of String) Additional parameters to pass to Packer
- **directory** (String) Working directory to run Packer inside. Default is cwd.
- **environment** (Map of String) Environment variables
- **file** (String) Packer file to use for building
- **force** (Boolean) Force overwriting existing images
- **keep_environment** (Boolean) Passes all environment variables of the provider through to Packer
- **triggers** (Map of String) Values that, when changed, trigger an update of this resource
- **variables** (Map of String) Variables to pass to Packer
- `additional_params` (Set of String) Additional parameters to pass to Packer
- `directory` (String) Working directory to run Packer inside. Default is cwd.
- `environment` (Map of String) Environment variables
- `file` (String) Packer file to use for building
- `force` (Boolean) Force overwriting existing images
- `keep_environment` (Boolean) Passes all environment variables of the provider through to Packer
- `name` (String) Name of this build. Mainly used for data source packer_build
- `triggers` (Map of String) Values that, when changed, trigger an update of this resource
- `variables` (Map of String) Variables to pass to Packer

### Read-Only

- **build_uuid** (String) UUID that is updated whenever the build has finished. This allows detecting changes.
- **id** (String) The ID of this resource.
- `build_uuid` (String) UUID that is updated whenever the build has finished. This allows detecting changes.
- `id` (String) The ID of this resource.


37 changes: 37 additions & 0 deletions examples/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions examples/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,33 @@ resource "packer_image" "image1" {
}
}

resource "random_string" "random" {
length = 16
special = false
lower = true
upper = true
number = true
}

resource "packer_image" "image2" {
directory = data.packer_files.files2.directory
force = true
variables = {
test_var3 = "test 3"
}
keep_environment = true
name = random_string.random.result

triggers = {
packer_version = data.packer_version.version.version
files_hash = data.packer_files.files2.files_hash
}
}

data "packer_build" "image2_wait" {
name = random_string.random.result
}

output "packer_version" {
value = data.packer_version.version.version
}
Expand All @@ -56,6 +69,10 @@ output "build_uuid_2" {
value = resource.packer_image.image2.build_uuid
}

output "build_wait_uuid_2" {
value = data.packer_build.image2_wait.uuid
}

output "file_hash_1" {
value = data.packer_files.files1.files_hash
}
78 changes: 78 additions & 0 deletions provider/data_source_packer_build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package provider

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
)

type dataSourceBuildType struct {
BuildName types.String `tfsdk:"name"`
BuildUUID types.String `tfsdk:"uuid"`
}

func (d dataSourceBuild) updateAutoComputed(resourceState *dataSourceBuildType) error {
return nil
}

func (d dataSourceBuildType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) {
return tfsdk.Schema{
Description: "Waits for the build specified by its name to finish. This is only useful when you define the " +
"name outside of the packer_image resource, allowing both the packer_image resource and this data " +
"source to reference the same build. Use this if you want to have the image created before recreating a " +
"VM when recreation involves deletion in which case the downtime would include the image build process.",
Attributes: map[string]tfsdk.Attribute{
"name": {
Description: "Name of the build. Use a resource, like random_string otherwise it hangs during plan.",
Type: types.StringType,
Validators: []tfsdk.AttributeValidator{
NonEmptyStringValidator{},
},
Required: true,
},
"uuid": {
Description: "Build UUID of the referenced build",
Type: types.StringType,
Computed: true,
},
},
}, nil
}

func (d dataSourceBuildType) NewDataSource(_ context.Context, p tfsdk.Provider) (tfsdk.DataSource, diag.Diagnostics) {
return dataSourceBuild{
p: *(p.(*provider)),
}, nil
}

type dataSourceBuild struct {
p provider
}

func (d dataSourceBuild) Read(ctx context.Context, req tfsdk.ReadDataSourceRequest, resp *tfsdk.ReadDataSourceResponse) {
resourceState := dataSourceBuildType{}
diags := req.Config.Get(ctx, &resourceState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

build := state.GetBuild(resourceState.BuildName.Value)
build.AwaitCompletion()

resourceState.BuildUUID = types.String{Value: build.ImageResourceData.BuildUUID.Value}

err := d.updateAutoComputed(&resourceState)
if err != nil {
resp.Diagnostics.AddError("Failed to run compute attributes", err.Error())
return
}

diags = resp.State.Set(ctx, &resourceState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}
1 change: 1 addition & 0 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,6 @@ func (p *provider) GetDataSources(_ context.Context) (map[string]tfsdk.DataSourc
return map[string]tfsdk.DataSourceType{
"packer_version": dataSourceVersionType{},
"packer_files": dataSourceFilesType{},
"packer_build": dataSourceBuildType{},
}, nil
}
36 changes: 31 additions & 5 deletions provider/resource_packer_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type resourceImageType struct {
Triggers map[string]string `tfsdk:"triggers"`
Force types.Bool `tfsdk:"force"`
BuildUUID types.String `tfsdk:"build_uuid"`
Name types.String `tfsdk:"name"`
}

func (r resourceImageType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) {
Expand All @@ -36,6 +37,11 @@ func (r resourceImageType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diag
Type: types.StringType,
Computed: true,
},
"name": {
Description: "Name of this build. Mainly used for data source packer_build",
Type: types.StringType,
Optional: true,
},
"variables": {
Description: "Variables to pass to Packer",
Type: types.MapType{ElemType: types.StringType},
Expand Down Expand Up @@ -170,6 +176,11 @@ func (r resourceImage) Create(ctx context.Context, req tfsdk.CreateResourceReque
return
}

if err := state.StartBuild(&resourceState); err != nil {
resp.Diagnostics.AddError("Failed to mark build as started", err.Error())
return
}

err := r.packerInit(&resourceState)
if err != nil {
resp.Diagnostics.AddError("Failed to run packer init", err.Error())
Expand All @@ -186,6 +197,9 @@ func (r resourceImage) Create(ctx context.Context, req tfsdk.CreateResourceReque
return
}

state.RefreshBuildData(&resourceState)
state.CompleteBuild(resourceState.Name.Value, true)

diags = resp.State.Set(ctx, &resourceState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
Expand All @@ -194,14 +208,18 @@ func (r resourceImage) Create(ctx context.Context, req tfsdk.CreateResourceReque
}

func (r resourceImage) Read(ctx context.Context, req tfsdk.ReadResourceRequest, resp *tfsdk.ReadResourceResponse) {
var state resourceImageType
diags := req.State.Get(ctx, &state)
var resourceState resourceImageType
diags := req.State.Get(ctx, &resourceState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

diags = resp.State.Set(ctx, &state)
if !resourceState.Name.Null {
state.RefreshBuildData(&resourceState)
}

diags = resp.State.Set(ctx, &resourceState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
Expand All @@ -216,13 +234,18 @@ func (r resourceImage) Update(ctx context.Context, req tfsdk.UpdateResourceReque
return
}

var state resourceImageType
diags = req.State.Get(ctx, &state)
var resourceState resourceImageType
diags = req.State.Get(ctx, &resourceState)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

if err := state.StartBuild(&resourceState); err != nil {
resp.Diagnostics.AddError("Failed to mark build as started", err.Error())
return
}

err := r.packerInit(&plan)
if err != nil {
resp.Diagnostics.AddError("Failed to run packer init", err.Error())
Expand All @@ -239,6 +262,9 @@ func (r resourceImage) Update(ctx context.Context, req tfsdk.UpdateResourceReque
return
}

state.RefreshBuildData(&plan)
state.CompleteBuild(resourceState.Name.Value, true)

diags = resp.State.Set(ctx, plan)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
Expand Down
Loading

0 comments on commit a5d9805

Please sign in to comment.