Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add component_type optional argument #347

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions docs/data-sources/packer_image.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ output "packer-registry-ubuntu-east-1" {

~> **Note:** The `channel` attribute in this data source may incur a billable request to HCP Packer. This attribute is intended for convenience when using a single image. When sourcing multiple images from a single iteration, the `hcp_packer_iteration` data source is the alternative for querying a channel just once.

~> **Note:** This data source only returns the first found image's metadata filtered by the given schema values, from the returned list of images associated with the specified iteration. Therefore, if multiple images exist in the same region, it will only pick one of them. If that's the case, you may consider separating your builds into different buckets.

### Multiple image sourcing from a single iteration

```terraform
Expand Down Expand Up @@ -61,7 +59,7 @@ output "packer-registry-ubuntu-west-1" {
}
```

~> **Note:** This data source only returns the first found image's metadata filtered by the given schema values, from the returned list of images associated with the specified iteration. Therefore, if multiple images exist in the same region, it will only pick one of them. If that's the case, you may consider separating your builds into different buckets.
~> **Note:** This data source only returns the first found image's metadata filtered by the given arguments, from the returned list of images associated with the specified iteration. Therefore, if multiple images exist in the same region, it will only pick one of them. In this case, you can filter images by a source build name (Ex: `amazon-ebs.example`) using the `component_type` optional argument.

<!-- schema generated by tfplugindocs -->
## Schema
Expand All @@ -75,14 +73,14 @@ output "packer-registry-ubuntu-west-1" {
### Optional

- `channel` (String) The channel that points to the version of the image being retrieved. Either this or `iteration_id` must be specified. Note: will incur a billable request
- `component_type` (String) Name of the builder that built this image. Ex: `amazon-ebs.example`.
- `iteration_id` (String) The iteration from which to get the image. Either this or `channel` must be specified.
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))

### Read-Only

- `build_id` (String) HCP ID of this build.
- `cloud_image_id` (String) Cloud Image ID or URL string identifying this image for the builder that built it.
- `component_type` (String) Name of the builder that built this. Ex: 'amazon-ebs.example'
- `created_at` (String) Creation time of this build.
- `id` (String) The ID of this resource.
- `labels` (Map of String) Labels associated with this build.
Expand Down
25 changes: 18 additions & 7 deletions internal/provider/data_source_packer_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ func dataSourcePackerImage() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"component_type": {
Description: "Name of the builder that built this image. Ex: `amazon-ebs.example`.",
Type: schema.TypeString,
Optional: true,
Computed: true,
},
// computed outputs
"organization_id": {
Description: "The ID of the organization this HCP Packer registry is located in.",
Expand All @@ -63,11 +69,6 @@ func dataSourcePackerImage() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"component_type": {
Description: "Name of the builder that built this. Ex: 'amazon-ebs.example'",
Type: schema.TypeString,
Computed: true,
},
"created_at": {
Description: "Creation time of this build.",
Type: schema.TypeString,
Expand Down Expand Up @@ -107,6 +108,7 @@ func dataSourcePackerImageRead(ctx context.Context, d *schema.ResourceData, meta
cloudProvider := d.Get("cloud_provider").(string)
region := d.Get("region").(string)
channelSlug := d.Get("channel").(string)
componentType := d.Get("component_type").(string)
iterationID := d.Get("iteration_id").(string)
client := meta.(*clients.Client)

Expand Down Expand Up @@ -162,7 +164,7 @@ func dataSourcePackerImageRead(ctx context.Context, d *schema.ResourceData, meta
continue
}
for _, image := range build.Images {
if image.Region == region {
if image.Region == region && filterBuildByComponentType(build, componentType) {
found = true
d.SetId(image.ID)
if err := d.Set("component_type", build.ComponentType); err != nil {
Expand Down Expand Up @@ -196,8 +198,17 @@ func dataSourcePackerImageRead(ctx context.Context, d *schema.ResourceData, meta
}

if !found {
return diag.Errorf("Unable to load image with region %s and cloud %s for iteration %s.", region, cloudProvider, iterationID)
return diag.Errorf("Unable to load image (region: %s, cloud: %s, iteration: %s, component_type: %s).", region, cloudProvider, iterationID, componentType)
}

return nil
}

func filterBuildByComponentType(build *packermodels.HashicorpCloudPackerBuild, componentType string) bool {
// optional field is not specified, passthrough
if componentType == "" {
return true
}
// if specified, only the matched image metadata is returned by this effect
return build.ComponentType == componentType
}
28 changes: 28 additions & 0 deletions internal/provider/data_source_packer_image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
acctestUbuntuImageBucket = "ubuntu-acctest-imagetest"
acctestArchImageBucket = "arch-acctest-imagetest"
acctestImageChannel = "production-image-test"
componentType = "amazon-ebs.example"
)

var (
Expand All @@ -31,6 +32,27 @@ var (
cloud_provider = "aws"
iteration_id = data.hcp_packer_iteration.alpine-imagetest.id
region = "us-east-1"
component_type = %q
}

# we make sure that this won't fail even when revoke_at is not set
output "revoke_at" {
value = data.hcp_packer_iteration.alpine-imagetest.revoke_at
}
`, acctestImageBucket, acctestImageChannel, acctestImageBucket, componentType)

testAccPackerImageAlpineProductionError = fmt.Sprintf(`
data "hcp_packer_iteration" "alpine-imagetest" {
bucket_name = %q
channel = %q
}

data "hcp_packer_image" "foo" {
bucket_name = %q
cloud_provider = "aws"
iteration_id = data.hcp_packer_iteration.alpine-imagetest.id
region = "us-east-1"
component_type = "amazon-ebs.do-not-exist"
}

# we make sure that this won't fail even when revoke_at is not set
Expand Down Expand Up @@ -123,6 +145,12 @@ func TestAcc_dataSourcePackerImage(t *testing.T) {
resource.TestCheckResourceAttr("data.hcp_packer_image.foo", "labels.test-key", "test-value"),
),
},
// Testing that filtering non-existent image fails properly
{
PlanOnly: true,
Config: testAccPackerImageAlpineProductionError,
ExpectError: regexp.MustCompile("Error: Unable to load image"),
},
},
})
}
Expand Down
4 changes: 1 addition & 3 deletions templates/data-sources/packer_image.md.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@ description: |-

~> **Note:** The `channel` attribute in this data source may incur a billable request to HCP Packer. This attribute is intended for convenience when using a single image. When sourcing multiple images from a single iteration, the `hcp_packer_iteration` data source is the alternative for querying a channel just once.

~> **Note:** This data source only returns the first found image's metadata filtered by the given schema values, from the returned list of images associated with the specified iteration. Therefore, if multiple images exist in the same region, it will only pick one of them. If that's the case, you may consider separating your builds into different buckets.

### Multiple image sourcing from a single iteration

{{ tffile "examples/data-sources/hcp_packer_image/data-source.tf" }}

~> **Note:** This data source only returns the first found image's metadata filtered by the given schema values, from the returned list of images associated with the specified iteration. Therefore, if multiple images exist in the same region, it will only pick one of them. If that's the case, you may consider separating your builds into different buckets.
~> **Note:** This data source only returns the first found image's metadata filtered by the given arguments, from the returned list of images associated with the specified iteration. Therefore, if multiple images exist in the same region, it will only pick one of them. In this case, you can filter images by a source build name (Ex: `amazon-ebs.example`) using the `component_type` optional argument.

{{ .SchemaMarkdown | trimspace }}